PageRenderTime 64ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/amanda/tags/zmanda_3_3_1_rc03/device-src/s3-device.c

#
C | 2049 lines | 1511 code | 344 blank | 194 comment | 193 complexity | 1ed987fd54f4dbc896f28c59bb3ba45e MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License version 2 as published
  6. * by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  11. * for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write to the Free Software Foundation, Inc.,
  15. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. *
  17. * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
  18. * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
  19. */
  20. /* An S3 device uses Amazon's S3 service (http://www.amazon.com/s3) to store
  21. * data. It stores data in keys named with a user-specified prefix, inside a
  22. * user-specified bucket. Data is stored in the form of numbered (large)
  23. * blocks.
  24. */
  25. #include "amanda.h"
  26. #include <string.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <unistd.h>
  30. #include <dirent.h>
  31. #include <regex.h>
  32. #include <time.h>
  33. #include "util.h"
  34. #include "conffile.h"
  35. #include "device.h"
  36. #include "s3.h"
  37. #include <curl/curl.h>
  38. #ifdef HAVE_OPENSSL_HMAC_H
  39. # include <openssl/hmac.h>
  40. #else
  41. # ifdef HAVE_CRYPTO_HMAC_H
  42. # include <crypto/hmac.h>
  43. # else
  44. # ifdef HAVE_HMAC_H
  45. # include <hmac.h>
  46. # endif
  47. # endif
  48. #endif
  49. /*
  50. * Type checking and casting macros
  51. */
  52. #define TYPE_S3_DEVICE (s3_device_get_type())
  53. #define S3_DEVICE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), s3_device_get_type(), S3Device)
  54. #define S3_DEVICE_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), s3_device_get_type(), S3Device const)
  55. #define S3_DEVICE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), s3_device_get_type(), S3DeviceClass)
  56. #define IS_S3_DEVICE(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), s3_device_get_type ())
  57. #define S3_DEVICE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), s3_device_get_type(), S3DeviceClass)
  58. static GType s3_device_get_type (void);
  59. /*
  60. * Main object structure
  61. */
  62. typedef struct _S3MetadataFile S3MetadataFile;
  63. typedef struct _S3_by_thread S3_by_thread;
  64. struct _S3_by_thread {
  65. S3Handle * volatile s3;
  66. CurlBuffer volatile curl_buffer;
  67. guint volatile buffer_len;
  68. int volatile idle;
  69. int volatile eof;
  70. int volatile done;
  71. char volatile * volatile filename;
  72. DeviceStatusFlags volatile errflags; /* device_status */
  73. char volatile * volatile errmsg; /* device error message */
  74. };
  75. typedef struct _S3Device S3Device;
  76. struct _S3Device {
  77. Device __parent__;
  78. /* The "easy" curl handle we use to access Amazon S3 */
  79. S3_by_thread *s3t;
  80. /* S3 access information */
  81. char *bucket;
  82. char *prefix;
  83. /* The S3 access information. */
  84. char *secret_key;
  85. char *access_key;
  86. char *user_token;
  87. /* The Openstack swift information. */
  88. char *swift_account_id;
  89. char *swift_access_key;
  90. char *bucket_location;
  91. char *storage_class;
  92. char *host;
  93. char *service_path;
  94. char *server_side_encryption;
  95. char *ca_info;
  96. /* a cache for unsuccessful reads (where we get the file but the caller
  97. * doesn't have space for it or doesn't want it), where we expect the
  98. * next call will request the same file.
  99. */
  100. char *cached_buf;
  101. char *cached_key;
  102. int cached_size;
  103. /* Produce verbose output? */
  104. gboolean verbose;
  105. /* Use SSL? */
  106. gboolean use_ssl;
  107. gboolean openstack_swift_api;
  108. /* Throttling */
  109. guint64 max_send_speed;
  110. guint64 max_recv_speed;
  111. gboolean leom;
  112. guint64 volume_bytes;
  113. guint64 volume_limit;
  114. gboolean enforce_volume_limit;
  115. gboolean use_subdomain;
  116. int nb_threads;
  117. int nb_threads_backup;
  118. int nb_threads_recovery;
  119. GThreadPool *thread_pool_delete;
  120. GThreadPool *thread_pool_write;
  121. GThreadPool *thread_pool_read;
  122. GCond *thread_idle_cond;
  123. GMutex *thread_idle_mutex;
  124. int next_block_to_read;
  125. GSList *keys;
  126. };
  127. /*
  128. * Class definition
  129. */
  130. typedef struct _S3DeviceClass S3DeviceClass;
  131. struct _S3DeviceClass {
  132. DeviceClass __parent__;
  133. };
  134. /*
  135. * Constants and static data
  136. */
  137. #define S3_DEVICE_NAME "s3"
  138. /* Maximum key length as specified in the S3 documentation
  139. * (*excluding* null terminator) */
  140. #define S3_MAX_KEY_LENGTH 1024
  141. /* Note: for compatability, min can only be decreased and max increased */
  142. #define S3_DEVICE_MIN_BLOCK_SIZE 1024
  143. #define S3_DEVICE_MAX_BLOCK_SIZE (3*1024*1024*1024ULL)
  144. #define S3_DEVICE_DEFAULT_BLOCK_SIZE (10*1024*1024)
  145. #define EOM_EARLY_WARNING_ZONE_BLOCKS 4
  146. /* This goes in lieu of file number for metadata. */
  147. #define SPECIAL_INFIX "special-"
  148. /* pointer to the class of our parent */
  149. static DeviceClass *parent_class = NULL;
  150. /*
  151. * device-specific properties
  152. */
  153. /* Authentication information for Amazon S3. Both of these are strings. */
  154. static DevicePropertyBase device_property_s3_access_key;
  155. static DevicePropertyBase device_property_s3_secret_key;
  156. #define PROPERTY_S3_SECRET_KEY (device_property_s3_secret_key.ID)
  157. #define PROPERTY_S3_ACCESS_KEY (device_property_s3_access_key.ID)
  158. /* Authentication information for Openstack Swift. Both of these are strings. */
  159. static DevicePropertyBase device_property_swift_account_id;
  160. static DevicePropertyBase device_property_swift_access_key;
  161. #define PROPERTY_SWIFT_ACCOUNT_ID (device_property_swift_account_id.ID)
  162. #define PROPERTY_SWIFT_ACCESS_KEY (device_property_swift_access_key.ID)
  163. /* Host and path */
  164. static DevicePropertyBase device_property_s3_host;
  165. static DevicePropertyBase device_property_s3_service_path;
  166. #define PROPERTY_S3_HOST (device_property_s3_host.ID)
  167. #define PROPERTY_S3_SERVICE_PATH (device_property_s3_service_path.ID)
  168. /* Same, but for S3 with DevPay. */
  169. static DevicePropertyBase device_property_s3_user_token;
  170. #define PROPERTY_S3_USER_TOKEN (device_property_s3_user_token.ID)
  171. /* Location constraint for new buckets created on Amazon S3. */
  172. static DevicePropertyBase device_property_s3_bucket_location;
  173. #define PROPERTY_S3_BUCKET_LOCATION (device_property_s3_bucket_location.ID)
  174. /* Storage class */
  175. static DevicePropertyBase device_property_s3_storage_class;
  176. #define PROPERTY_S3_STORAGE_CLASS (device_property_s3_storage_class.ID)
  177. /* Storage class */
  178. static DevicePropertyBase device_property_s3_server_side_encryption;
  179. #define PROPERTY_S3_SERVER_SIDE_ENCRYPTION (device_property_s3_server_side_encryption.ID)
  180. /* Path to certificate authority certificate */
  181. static DevicePropertyBase device_property_ssl_ca_info;
  182. #define PROPERTY_SSL_CA_INFO (device_property_ssl_ca_info.ID)
  183. /* Whether to use openstack protocol. */
  184. static DevicePropertyBase device_property_openstack_swift_api;
  185. #define PROPERTY_OPENSTACK_SWIFT_API (device_property_openstack_swift_api.ID)
  186. /* Whether to use SSL with Amazon S3. */
  187. static DevicePropertyBase device_property_s3_ssl;
  188. #define PROPERTY_S3_SSL (device_property_s3_ssl.ID)
  189. /* Speed limits for sending and receiving */
  190. static DevicePropertyBase device_property_max_send_speed;
  191. static DevicePropertyBase device_property_max_recv_speed;
  192. #define PROPERTY_MAX_SEND_SPEED (device_property_max_send_speed.ID)
  193. #define PROPERTY_MAX_RECV_SPEED (device_property_max_recv_speed.ID)
  194. /* Whether to use subdomain */
  195. static DevicePropertyBase device_property_s3_subdomain;
  196. #define PROPERTY_S3_SUBDOMAIN (device_property_s3_subdomain.ID)
  197. /* Number of threads to use */
  198. static DevicePropertyBase device_property_nb_threads_backup;
  199. #define PROPERTY_NB_THREADS_BACKUP (device_property_nb_threads_backup.ID)
  200. static DevicePropertyBase device_property_nb_threads_recovery;
  201. #define PROPERTY_NB_THREADS_RECOVERY (device_property_nb_threads_recovery.ID)
  202. /*
  203. * prototypes
  204. */
  205. void s3_device_register(void);
  206. /*
  207. * utility functions */
  208. /* Given file and block numbers, return an S3 key.
  209. *
  210. * @param self: the S3Device object
  211. * @param file: the file number
  212. * @param block: the block within that file
  213. * @returns: a newly allocated string containing an S3 key.
  214. */
  215. static char *
  216. file_and_block_to_key(S3Device *self,
  217. int file,
  218. guint64 block);
  219. /* Given the name of a special file (such as 'tapestart'), generate
  220. * the S3 key to use for that file.
  221. *
  222. * @param self: the S3Device object
  223. * @param special_name: name of the special file
  224. * @param file: a file number to include; omitted if -1
  225. * @returns: a newly alocated string containing an S3 key.
  226. */
  227. static char *
  228. special_file_to_key(S3Device *self,
  229. char *special_name,
  230. int file);
  231. /* Write an amanda header file to S3.
  232. *
  233. * @param self: the S3Device object
  234. * @param label: the volume label
  235. * @param timestamp: the volume timestamp
  236. */
  237. static gboolean
  238. write_amanda_header(S3Device *self,
  239. char *label,
  240. char * timestamp);
  241. /* "Fast forward" this device to the end by looking up the largest file number
  242. * present and setting the current file number one greater.
  243. *
  244. * @param self: the S3Device object
  245. */
  246. static gboolean
  247. seek_to_end(S3Device *self);
  248. /* Find the number of the last file that contains any data (even just a header).
  249. *
  250. * @param self: the S3Device object
  251. * @returns: the last file, or -1 in event of an error
  252. */
  253. static int
  254. find_last_file(S3Device *self);
  255. /* Delete all blocks in the given file, including the filestart block
  256. *
  257. * @param self: the S3Device object
  258. * @param file: the file to delete
  259. */
  260. static gboolean
  261. delete_file(S3Device *self,
  262. int file);
  263. /* Delete all files in the given device
  264. *
  265. * @param self: the S3Device object
  266. */
  267. static gboolean
  268. delete_all_files(S3Device *self);
  269. /* Set up self->s3t as best as possible.
  270. *
  271. * The return value is TRUE iff self->s3t is useable.
  272. *
  273. * @param self: the S3Device object
  274. * @returns: TRUE if the handle is set up
  275. */
  276. static gboolean
  277. setup_handle(S3Device * self);
  278. static void
  279. s3_wait_thread_delete(S3Device *self);
  280. /*
  281. * class mechanics */
  282. static void
  283. s3_device_init(S3Device * o);
  284. static void
  285. s3_device_class_init(S3DeviceClass * c);
  286. static void
  287. s3_device_finalize(GObject * o);
  288. static Device*
  289. s3_device_factory(char * device_name, char * device_type, char * device_node);
  290. /*
  291. * Property{Get,Set}Fns */
  292. static gboolean s3_device_set_access_key_fn(Device *self,
  293. DevicePropertyBase *base, GValue *val,
  294. PropertySurety surety, PropertySource source);
  295. static gboolean s3_device_set_secret_key_fn(Device *self,
  296. DevicePropertyBase *base, GValue *val,
  297. PropertySurety surety, PropertySource source);
  298. static gboolean s3_device_set_swift_account_id_fn(Device *self,
  299. DevicePropertyBase *base, GValue *val,
  300. PropertySurety surety, PropertySource source);
  301. static gboolean s3_device_set_swift_access_key_fn(Device *self,
  302. DevicePropertyBase *base, GValue *val,
  303. PropertySurety surety, PropertySource source);
  304. static gboolean s3_device_set_user_token_fn(Device *self,
  305. DevicePropertyBase *base, GValue *val,
  306. PropertySurety surety, PropertySource source);
  307. static gboolean s3_device_set_bucket_location_fn(Device *self,
  308. DevicePropertyBase *base, GValue *val,
  309. PropertySurety surety, PropertySource source);
  310. static gboolean s3_device_set_storage_class_fn(Device *self,
  311. DevicePropertyBase *base, GValue *val,
  312. PropertySurety surety, PropertySource source);
  313. static gboolean s3_device_set_server_side_encryption_fn(Device *self,
  314. DevicePropertyBase *base, GValue *val,
  315. PropertySurety surety, PropertySource source);
  316. static gboolean s3_device_set_ca_info_fn(Device *self,
  317. DevicePropertyBase *base, GValue *val,
  318. PropertySurety surety, PropertySource source);
  319. static gboolean s3_device_set_verbose_fn(Device *self,
  320. DevicePropertyBase *base, GValue *val,
  321. PropertySurety surety, PropertySource source);
  322. static gboolean s3_device_set_openstack_swift_api_fn(Device *self,
  323. DevicePropertyBase *base, GValue *val,
  324. PropertySurety surety, PropertySource source);
  325. static gboolean s3_device_set_ssl_fn(Device *self,
  326. DevicePropertyBase *base, GValue *val,
  327. PropertySurety surety, PropertySource source);
  328. static gboolean s3_device_set_max_send_speed_fn(Device *self,
  329. DevicePropertyBase *base, GValue *val,
  330. PropertySurety surety, PropertySource source);
  331. static gboolean s3_device_set_max_recv_speed_fn(Device *self,
  332. DevicePropertyBase *base, GValue *val,
  333. PropertySurety surety, PropertySource source);
  334. static gboolean s3_device_set_nb_threads_backup(Device *self,
  335. DevicePropertyBase *base, GValue *val,
  336. PropertySurety surety, PropertySource source);
  337. static gboolean s3_device_set_nb_threads_recovery(Device *self,
  338. DevicePropertyBase *base, GValue *val,
  339. PropertySurety surety, PropertySource source);
  340. static gboolean s3_device_set_max_volume_usage_fn(Device *p_self,
  341. DevicePropertyBase *base, GValue *val,
  342. PropertySurety surety, PropertySource source);
  343. static gboolean property_set_leom_fn(Device *p_self,
  344. DevicePropertyBase *base, GValue *val,
  345. PropertySurety surety, PropertySource source);
  346. static gboolean s3_device_set_enforce_max_volume_usage_fn(Device *p_self,
  347. DevicePropertyBase *base, GValue *val,
  348. PropertySurety surety, PropertySource source);
  349. static gboolean s3_device_set_use_subdomain_fn(Device *p_self,
  350. DevicePropertyBase *base, GValue *val,
  351. PropertySurety surety, PropertySource source);
  352. static gboolean s3_device_set_host_fn(Device *p_self,
  353. DevicePropertyBase *base, GValue *val,
  354. PropertySurety surety, PropertySource source);
  355. static gboolean s3_device_set_service_path_fn(Device *p_self,
  356. DevicePropertyBase *base, GValue *val,
  357. PropertySurety surety, PropertySource source);
  358. static void s3_thread_read_block(gpointer thread_data,
  359. gpointer data);
  360. static void s3_thread_write_block(gpointer thread_data,
  361. gpointer data);
  362. static gboolean make_bucket(Device * pself);
  363. /* Wait that all threads are done */
  364. static void reset_thread(S3Device *self);
  365. /*
  366. * virtual functions */
  367. static void
  368. s3_device_open_device(Device *pself, char *device_name,
  369. char * device_type, char * device_node);
  370. static DeviceStatusFlags s3_device_read_label(Device * self);
  371. static gboolean
  372. s3_device_start(Device * self,
  373. DeviceAccessMode mode,
  374. char * label,
  375. char * timestamp);
  376. static gboolean
  377. s3_device_finish(Device * self);
  378. static gboolean
  379. s3_device_start_file(Device * self,
  380. dumpfile_t * jobInfo);
  381. static gboolean
  382. s3_device_write_block(Device * self,
  383. guint size,
  384. gpointer data);
  385. static gboolean
  386. s3_device_finish_file(Device * self);
  387. static dumpfile_t*
  388. s3_device_seek_file(Device *pself,
  389. guint file);
  390. static gboolean
  391. s3_device_seek_block(Device *pself,
  392. guint64 block);
  393. static int
  394. s3_device_read_block(Device * pself,
  395. gpointer data,
  396. int *size_req);
  397. static gboolean
  398. s3_device_recycle_file(Device *pself,
  399. guint file);
  400. static gboolean
  401. s3_device_erase(Device *pself);
  402. static gboolean
  403. check_at_leom(S3Device *self,
  404. guint64 size);
  405. static gboolean
  406. check_at_peom(S3Device *self,
  407. guint64 size);
  408. /*
  409. * Private functions
  410. */
  411. static char *
  412. file_and_block_to_key(S3Device *self,
  413. int file,
  414. guint64 block)
  415. {
  416. char *s3_key = g_strdup_printf("%sf%08x-b%016llx.data",
  417. self->prefix, file, (long long unsigned int)block);
  418. g_assert(strlen(s3_key) <= S3_MAX_KEY_LENGTH);
  419. return s3_key;
  420. }
  421. static char *
  422. special_file_to_key(S3Device *self,
  423. char *special_name,
  424. int file)
  425. {
  426. if (file == -1)
  427. return g_strdup_printf("%s" SPECIAL_INFIX "%s", self->prefix, special_name);
  428. else
  429. return g_strdup_printf("%sf%08x-%s", self->prefix, file, special_name);
  430. }
  431. static gboolean
  432. write_amanda_header(S3Device *self,
  433. char *label,
  434. char * timestamp)
  435. {
  436. CurlBuffer amanda_header = {NULL, 0, 0, 0};
  437. char * key = NULL;
  438. gboolean result;
  439. dumpfile_t * dumpinfo = NULL;
  440. Device *d_self = DEVICE(self);
  441. size_t header_size;
  442. /* build the header */
  443. header_size = 0; /* no minimum size */
  444. dumpinfo = make_tapestart_header(DEVICE(self), label, timestamp);
  445. amanda_header.buffer = device_build_amanda_header(DEVICE(self), dumpinfo,
  446. &header_size);
  447. if (amanda_header.buffer == NULL) {
  448. device_set_error(d_self,
  449. stralloc(_("Amanda tapestart header won't fit in a single block!")),
  450. DEVICE_STATUS_DEVICE_ERROR);
  451. dumpfile_free(dumpinfo);
  452. g_free(amanda_header.buffer);
  453. return FALSE;
  454. }
  455. if(check_at_leom(self, header_size))
  456. d_self->is_eom = TRUE;
  457. if(check_at_peom(self, header_size)) {
  458. d_self->is_eom = TRUE;
  459. device_set_error(d_self,
  460. stralloc(_("No space left on device")),
  461. DEVICE_STATUS_DEVICE_ERROR);
  462. g_free(amanda_header.buffer);
  463. return FALSE;
  464. }
  465. /* write out the header and flush the uploads. */
  466. key = special_file_to_key(self, "tapestart", -1);
  467. g_assert(header_size < G_MAXUINT); /* for cast to guint */
  468. amanda_header.buffer_len = (guint)header_size;
  469. result = s3_upload(self->s3t[0].s3, self->bucket, key, S3_BUFFER_READ_FUNCS,
  470. &amanda_header, NULL, NULL);
  471. g_free(amanda_header.buffer);
  472. g_free(key);
  473. if (!result) {
  474. device_set_error(d_self,
  475. vstrallocf(_("While writing amanda header: %s"), s3_strerror(self->s3t[0].s3)),
  476. DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
  477. dumpfile_free(dumpinfo);
  478. } else {
  479. dumpfile_free(d_self->volume_header);
  480. d_self->volume_header = dumpinfo;
  481. self->volume_bytes += header_size;
  482. }
  483. d_self->header_block_size = header_size;
  484. return result;
  485. }
  486. static gboolean
  487. seek_to_end(S3Device *self) {
  488. int last_file;
  489. Device *pself = DEVICE(self);
  490. last_file = find_last_file(self);
  491. if (last_file < 0)
  492. return FALSE;
  493. pself->file = last_file;
  494. return TRUE;
  495. }
  496. /* Convert an object name into a file number, assuming the given prefix
  497. * length. Returns -1 if the object name is invalid, or 0 if the object name
  498. * is a "special" key. */
  499. static int key_to_file(guint prefix_len, const char * key) {
  500. int file;
  501. int i;
  502. /* skip the prefix */
  503. if (strlen(key) <= prefix_len)
  504. return -1;
  505. key += prefix_len;
  506. if (strncmp(key, SPECIAL_INFIX, strlen(SPECIAL_INFIX)) == 0) {
  507. return 0;
  508. }
  509. /* check that key starts with 'f' */
  510. if (key[0] != 'f')
  511. return -1;
  512. key++;
  513. /* check that key is of the form "%08x-" */
  514. for (i = 0; i < 8; i++) {
  515. if (!(key[i] >= '0' && key[i] <= '9') &&
  516. !(key[i] >= 'a' && key[i] <= 'f') &&
  517. !(key[i] >= 'A' && key[i] <= 'F')) break;
  518. }
  519. if (key[i] != '-') return -1;
  520. if (i < 8) return -1;
  521. /* convert the file number */
  522. errno = 0;
  523. file = strtoul(key, NULL, 16);
  524. if (errno != 0) {
  525. g_warning(_("unparseable file number '%s'"), key);
  526. return -1;
  527. }
  528. return file;
  529. }
  530. /* Find the number of the last file that contains any data (even just a header).
  531. * Returns -1 in event of an error
  532. */
  533. static int
  534. find_last_file(S3Device *self) {
  535. gboolean result;
  536. GSList *keys;
  537. unsigned int prefix_len = strlen(self->prefix);
  538. int last_file = 0;
  539. Device *d_self = DEVICE(self);
  540. /* list all keys matching C{PREFIX*-*}, stripping the C{-*} */
  541. result = s3_list_keys(self->s3t[0].s3, self->bucket, self->prefix, "-", &keys, NULL);
  542. if (!result) {
  543. device_set_error(d_self,
  544. vstrallocf(_("While listing S3 keys: %s"), s3_strerror(self->s3t[0].s3)),
  545. DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
  546. return -1;
  547. }
  548. for (; keys; keys = g_slist_remove(keys, keys->data)) {
  549. int file = key_to_file(prefix_len, keys->data);
  550. /* and if it's the last, keep it */
  551. if (file > last_file)
  552. last_file = file;
  553. }
  554. return last_file;
  555. }
  556. /* Find the number of the file following the requested one, if any.
  557. * Returns 0 if there is no such file or -1 in event of an error
  558. */
  559. static int
  560. find_next_file(S3Device *self, int last_file) {
  561. gboolean result;
  562. GSList *keys;
  563. unsigned int prefix_len = strlen(self->prefix);
  564. int next_file = 0;
  565. Device *d_self = DEVICE(self);
  566. /* list all keys matching C{PREFIX*-*}, stripping the C{-*} */
  567. result = s3_list_keys(self->s3t[0].s3, self->bucket, self->prefix, "-",
  568. &keys, NULL);
  569. if (!result) {
  570. device_set_error(d_self,
  571. vstrallocf(_("While listing S3 keys: %s"), s3_strerror(self->s3t[0].s3)),
  572. DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
  573. return -1;
  574. }
  575. for (; keys; keys = g_slist_remove(keys, keys->data)) {
  576. int file;
  577. file = key_to_file(prefix_len, (char*)keys->data);
  578. if (file < 0) {
  579. /* Set this in case we don't find a next file; this is not a
  580. * hard error, so if we can find a next file we'll return that
  581. * instead. */
  582. next_file = -1;
  583. }
  584. if (file < next_file && file > last_file) {
  585. next_file = file;
  586. }
  587. }
  588. return next_file;
  589. }
  590. static gboolean
  591. delete_file(S3Device *self,
  592. int file)
  593. {
  594. int thread = -1;
  595. gboolean result;
  596. GSList *keys;
  597. guint64 total_size = 0;
  598. Device *d_self = DEVICE(self);
  599. char *my_prefix;
  600. if (file == -1) {
  601. my_prefix = g_strdup_printf("%sf", self->prefix);
  602. } else {
  603. my_prefix = g_strdup_printf("%sf%08x-", self->prefix, file);
  604. }
  605. result = s3_list_keys(self->s3t[0].s3, self->bucket, my_prefix, NULL, &keys,
  606. &total_size);
  607. if (!result) {
  608. device_set_error(d_self,
  609. vstrallocf(_("While listing S3 keys: %s"), s3_strerror(self->s3t[0].s3)),
  610. DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
  611. return FALSE;
  612. }
  613. g_mutex_lock(self->thread_idle_mutex);
  614. if (!self->keys) {
  615. self->keys = keys;
  616. } else {
  617. self->keys = g_slist_concat(self->keys, keys);
  618. }
  619. // start the threads
  620. for (thread = 0; thread < self->nb_threads; thread++) {
  621. if (self->s3t[thread].idle == 1) {
  622. /* Check if the thread is in error */
  623. if (self->s3t[thread].errflags != DEVICE_STATUS_SUCCESS) {
  624. device_set_error(d_self,
  625. (char *)self->s3t[thread].errmsg,
  626. self->s3t[thread].errflags);
  627. self->s3t[thread].errflags = DEVICE_STATUS_SUCCESS;
  628. self->s3t[thread].errmsg = NULL;
  629. g_mutex_unlock(self->thread_idle_mutex);
  630. s3_wait_thread_delete(self);
  631. return FALSE;
  632. }
  633. self->s3t[thread].idle = 0;
  634. self->s3t[thread].done = 0;
  635. g_thread_pool_push(self->thread_pool_delete, &self->s3t[thread],
  636. NULL);
  637. }
  638. }
  639. g_cond_wait(self->thread_idle_cond, self->thread_idle_mutex);
  640. g_mutex_unlock(self->thread_idle_mutex);
  641. self->volume_bytes = total_size;
  642. s3_wait_thread_delete(self);
  643. return TRUE;
  644. }
  645. static void
  646. s3_thread_delete_block(
  647. gpointer thread_data,
  648. gpointer data)
  649. {
  650. static int count = 0;
  651. S3_by_thread *s3t = (S3_by_thread *)thread_data;
  652. Device *pself = (Device *)data;
  653. S3Device *self = S3_DEVICE(pself);
  654. gboolean result = 1;
  655. char *filename;
  656. g_mutex_lock(self->thread_idle_mutex);
  657. while (result && self->keys) {
  658. filename = self->keys->data;
  659. self->keys = g_slist_remove(self->keys, self->keys->data);
  660. count++;
  661. if (count >= 1000) {
  662. g_debug("Deleting %s ...", filename);
  663. count = 0;
  664. }
  665. g_mutex_unlock(self->thread_idle_mutex);
  666. result = s3_delete(s3t->s3, (const char *)self->bucket, (const char *)filename);
  667. if (!result) {
  668. s3t->errflags = DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR;
  669. s3t->errmsg = g_strdup_printf(_("While deleting key '%s': %s"),
  670. filename, s3_strerror(s3t->s3));
  671. }
  672. g_free(filename);
  673. g_mutex_lock(self->thread_idle_mutex);
  674. }
  675. s3t->idle = 1;
  676. s3t->done = 1;
  677. g_cond_broadcast(self->thread_idle_cond);
  678. g_mutex_unlock(self->thread_idle_mutex);
  679. }
  680. static void
  681. s3_wait_thread_delete(S3Device *self)
  682. {
  683. Device *d_self = (Device *)self;
  684. int idle_thread = 0;
  685. int thread;
  686. g_mutex_lock(self->thread_idle_mutex);
  687. while (idle_thread != self->nb_threads) {
  688. idle_thread = 0;
  689. for (thread = 0; thread < self->nb_threads; thread++) {
  690. if (self->s3t[thread].idle == 1) {
  691. idle_thread++;
  692. }
  693. /* Check if the thread is in error */
  694. if (self->s3t[thread].errflags != DEVICE_STATUS_SUCCESS) {
  695. device_set_error(d_self, (char *)self->s3t[thread].errmsg,
  696. self->s3t[thread].errflags);
  697. self->s3t[thread].errflags = DEVICE_STATUS_SUCCESS;
  698. self->s3t[thread].errmsg = NULL;
  699. }
  700. }
  701. if (idle_thread != self->nb_threads) {
  702. g_cond_wait(self->thread_idle_cond, self->thread_idle_mutex);
  703. }
  704. }
  705. g_mutex_unlock(self->thread_idle_mutex);
  706. }
  707. static gboolean
  708. delete_all_files(S3Device *self)
  709. {
  710. return delete_file(self, -1);
  711. }
  712. /*
  713. * Class mechanics
  714. */
  715. void
  716. s3_device_register(void)
  717. {
  718. static const char * device_prefix_list[] = { S3_DEVICE_NAME, NULL };
  719. g_assert(s3_init());
  720. /* set up our properties */
  721. device_property_fill_and_register(&device_property_s3_secret_key,
  722. G_TYPE_STRING, "s3_secret_key",
  723. "Secret access key to authenticate with Amazon S3");
  724. device_property_fill_and_register(&device_property_s3_access_key,
  725. G_TYPE_STRING, "s3_access_key",
  726. "Access key ID to authenticate with Amazon S3");
  727. device_property_fill_and_register(&device_property_swift_account_id,
  728. G_TYPE_STRING, "swift_account_id",
  729. "Account ID to authenticate with openstack swift");
  730. device_property_fill_and_register(&device_property_swift_access_key,
  731. G_TYPE_STRING, "swift_access_key",
  732. "Access key to authenticate with openstack swift");
  733. device_property_fill_and_register(&device_property_s3_host,
  734. G_TYPE_STRING, "s3_host",
  735. "hostname:port of the server");
  736. device_property_fill_and_register(&device_property_s3_service_path,
  737. G_TYPE_STRING, "s3_service_path",
  738. "path to add in the url");
  739. device_property_fill_and_register(&device_property_s3_user_token,
  740. G_TYPE_STRING, "s3_user_token",
  741. "User token for authentication Amazon devpay requests");
  742. device_property_fill_and_register(&device_property_s3_bucket_location,
  743. G_TYPE_STRING, "s3_bucket_location",
  744. "Location constraint for buckets on Amazon S3");
  745. device_property_fill_and_register(&device_property_s3_storage_class,
  746. G_TYPE_STRING, "s3_storage_class",
  747. "Storage class as specified by Amazon (STANDARD or REDUCED_REDUNDANCY)");
  748. device_property_fill_and_register(&device_property_s3_server_side_encryption,
  749. G_TYPE_STRING, "s3_server_side_encryption",
  750. "Serve side encryption as specified by Amazon (AES256)");
  751. device_property_fill_and_register(&device_property_ssl_ca_info,
  752. G_TYPE_STRING, "ssl_ca_info",
  753. "Path to certificate authority certificate");
  754. device_property_fill_and_register(&device_property_openstack_swift_api,
  755. G_TYPE_BOOLEAN, "openstack_swift_api",
  756. "Whether to use openstack protocol");
  757. device_property_fill_and_register(&device_property_s3_ssl,
  758. G_TYPE_BOOLEAN, "s3_ssl",
  759. "Whether to use SSL with Amazon S3");
  760. device_property_fill_and_register(&device_property_s3_subdomain,
  761. G_TYPE_BOOLEAN, "s3_subdomain",
  762. "Whether to use subdomain");
  763. device_property_fill_and_register(&device_property_max_send_speed,
  764. G_TYPE_UINT64, "max_send_speed",
  765. "Maximum average upload speed (bytes/sec)");
  766. device_property_fill_and_register(&device_property_max_recv_speed,
  767. G_TYPE_UINT64, "max_recv_speed",
  768. "Maximum average download speed (bytes/sec)");
  769. device_property_fill_and_register(&device_property_nb_threads_backup,
  770. G_TYPE_UINT64, "nb_threads_backup",
  771. "Number of writer thread");
  772. device_property_fill_and_register(&device_property_nb_threads_recovery,
  773. G_TYPE_UINT64, "nb_threads_recovery",
  774. "Number of reader thread");
  775. /* register the device itself */
  776. register_device(s3_device_factory, device_prefix_list);
  777. }
  778. static GType
  779. s3_device_get_type(void)
  780. {
  781. static GType type = 0;
  782. if G_UNLIKELY(type == 0) {
  783. static const GTypeInfo info = {
  784. sizeof (S3DeviceClass),
  785. (GBaseInitFunc) NULL,
  786. (GBaseFinalizeFunc) NULL,
  787. (GClassInitFunc) s3_device_class_init,
  788. (GClassFinalizeFunc) NULL,
  789. NULL /* class_data */,
  790. sizeof (S3Device),
  791. 0 /* n_preallocs */,
  792. (GInstanceInitFunc) s3_device_init,
  793. NULL
  794. };
  795. type = g_type_register_static (TYPE_DEVICE, "S3Device", &info,
  796. (GTypeFlags)0);
  797. }
  798. return type;
  799. }
  800. static void
  801. s3_device_init(S3Device * self)
  802. {
  803. Device * dself = DEVICE(self);
  804. GValue response;
  805. self->volume_bytes = 0;
  806. self->volume_limit = 0;
  807. self->leom = TRUE;
  808. self->enforce_volume_limit = FALSE;
  809. self->use_subdomain = FALSE;
  810. self->nb_threads = 1;
  811. self->nb_threads_backup = 1;
  812. self->nb_threads_recovery = 1;
  813. self->thread_pool_delete = NULL;
  814. self->thread_pool_write = NULL;
  815. self->thread_pool_read = NULL;
  816. self->thread_idle_cond = NULL;
  817. self->thread_idle_mutex = NULL;
  818. /* Register property values
  819. * Note: Some aren't added until s3_device_open_device()
  820. */
  821. bzero(&response, sizeof(response));
  822. g_value_init(&response, CONCURRENCY_PARADIGM_TYPE);
  823. g_value_set_enum(&response, CONCURRENCY_PARADIGM_SHARED_READ);
  824. device_set_simple_property(dself, PROPERTY_CONCURRENCY,
  825. &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
  826. g_value_unset(&response);
  827. g_value_init(&response, STREAMING_REQUIREMENT_TYPE);
  828. g_value_set_enum(&response, STREAMING_REQUIREMENT_NONE);
  829. device_set_simple_property(dself, PROPERTY_STREAMING,
  830. &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
  831. g_value_unset(&response);
  832. g_value_init(&response, G_TYPE_BOOLEAN);
  833. g_value_set_boolean(&response, TRUE);
  834. device_set_simple_property(dself, PROPERTY_APPENDABLE,
  835. &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
  836. g_value_unset(&response);
  837. g_value_init(&response, G_TYPE_BOOLEAN);
  838. g_value_set_boolean(&response, TRUE);
  839. device_set_simple_property(dself, PROPERTY_PARTIAL_DELETION,
  840. &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
  841. g_value_unset(&response);
  842. g_value_init(&response, G_TYPE_BOOLEAN);
  843. g_value_set_boolean(&response, TRUE);
  844. device_set_simple_property(dself, PROPERTY_FULL_DELETION,
  845. &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
  846. g_value_unset(&response);
  847. g_value_init(&response, G_TYPE_BOOLEAN);
  848. g_value_set_boolean(&response, TRUE); /* well, there *is* no EOM on S3 .. */
  849. device_set_simple_property(dself, PROPERTY_LEOM,
  850. &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
  851. g_value_unset(&response);
  852. g_value_init(&response, G_TYPE_BOOLEAN);
  853. g_value_set_boolean(&response, FALSE);
  854. device_set_simple_property(dself, PROPERTY_ENFORCE_MAX_VOLUME_USAGE,
  855. &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
  856. g_value_unset(&response);
  857. g_value_init(&response, G_TYPE_BOOLEAN);
  858. g_value_set_boolean(&response, FALSE);
  859. device_set_simple_property(dself, PROPERTY_S3_SUBDOMAIN,
  860. &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
  861. g_value_unset(&response);
  862. g_value_init(&response, G_TYPE_BOOLEAN);
  863. g_value_set_boolean(&response, FALSE);
  864. device_set_simple_property(dself, PROPERTY_COMPRESSION,
  865. &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
  866. g_value_unset(&response);
  867. g_value_init(&response, MEDIA_ACCESS_MODE_TYPE);
  868. g_value_set_enum(&response, MEDIA_ACCESS_MODE_READ_WRITE);
  869. device_set_simple_property(dself, PROPERTY_MEDIUM_ACCESS_TYPE,
  870. &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
  871. g_value_unset(&response);
  872. }
  873. static void
  874. s3_device_class_init(S3DeviceClass * c G_GNUC_UNUSED)
  875. {
  876. GObjectClass *g_object_class = (GObjectClass*) c;
  877. DeviceClass *device_class = (DeviceClass *)c;
  878. parent_class = g_type_class_ref (TYPE_DEVICE);
  879. device_class->open_device = s3_device_open_device;
  880. device_class->read_label = s3_device_read_label;
  881. device_class->start = s3_device_start;
  882. device_class->finish = s3_device_finish;
  883. device_class->start_file = s3_device_start_file;
  884. device_class->write_block = s3_device_write_block;
  885. device_class->finish_file = s3_device_finish_file;
  886. device_class->seek_file = s3_device_seek_file;
  887. device_class->seek_block = s3_device_seek_block;
  888. device_class->read_block = s3_device_read_block;
  889. device_class->recycle_file = s3_device_recycle_file;
  890. device_class->erase = s3_device_erase;
  891. g_object_class->finalize = s3_device_finalize;
  892. device_class_register_property(device_class, PROPERTY_S3_ACCESS_KEY,
  893. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  894. device_simple_property_get_fn,
  895. s3_device_set_access_key_fn);
  896. device_class_register_property(device_class, PROPERTY_S3_SECRET_KEY,
  897. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  898. device_simple_property_get_fn,
  899. s3_device_set_secret_key_fn);
  900. device_class_register_property(device_class, PROPERTY_SWIFT_ACCOUNT_ID,
  901. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  902. device_simple_property_get_fn,
  903. s3_device_set_swift_account_id_fn);
  904. device_class_register_property(device_class, PROPERTY_SWIFT_ACCESS_KEY,
  905. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  906. device_simple_property_get_fn,
  907. s3_device_set_swift_access_key_fn);
  908. device_class_register_property(device_class, PROPERTY_S3_HOST,
  909. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  910. device_simple_property_get_fn,
  911. s3_device_set_host_fn);
  912. device_class_register_property(device_class, PROPERTY_S3_SERVICE_PATH,
  913. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  914. device_simple_property_get_fn,
  915. s3_device_set_service_path_fn);
  916. device_class_register_property(device_class, PROPERTY_S3_USER_TOKEN,
  917. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  918. device_simple_property_get_fn,
  919. s3_device_set_user_token_fn);
  920. device_class_register_property(device_class, PROPERTY_S3_BUCKET_LOCATION,
  921. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  922. device_simple_property_get_fn,
  923. s3_device_set_bucket_location_fn);
  924. device_class_register_property(device_class, PROPERTY_S3_STORAGE_CLASS,
  925. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  926. device_simple_property_get_fn,
  927. s3_device_set_storage_class_fn);
  928. device_class_register_property(device_class, PROPERTY_S3_SERVER_SIDE_ENCRYPTION,
  929. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  930. device_simple_property_get_fn,
  931. s3_device_set_server_side_encryption_fn);
  932. device_class_register_property(device_class, PROPERTY_SSL_CA_INFO,
  933. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  934. device_simple_property_get_fn,
  935. s3_device_set_ca_info_fn);
  936. device_class_register_property(device_class, PROPERTY_VERBOSE,
  937. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  938. device_simple_property_get_fn,
  939. s3_device_set_verbose_fn);
  940. device_class_register_property(device_class, PROPERTY_OPENSTACK_SWIFT_API,
  941. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  942. device_simple_property_get_fn,
  943. s3_device_set_openstack_swift_api_fn);
  944. device_class_register_property(device_class, PROPERTY_S3_SSL,
  945. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  946. device_simple_property_get_fn,
  947. s3_device_set_ssl_fn);
  948. device_class_register_property(device_class, PROPERTY_MAX_SEND_SPEED,
  949. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  950. device_simple_property_get_fn,
  951. s3_device_set_max_send_speed_fn);
  952. device_class_register_property(device_class, PROPERTY_MAX_RECV_SPEED,
  953. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  954. device_simple_property_get_fn,
  955. s3_device_set_max_recv_speed_fn);
  956. device_class_register_property(device_class, PROPERTY_NB_THREADS_BACKUP,
  957. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  958. device_simple_property_get_fn,
  959. s3_device_set_nb_threads_backup);
  960. device_class_register_property(device_class, PROPERTY_NB_THREADS_RECOVERY,
  961. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  962. device_simple_property_get_fn,
  963. s3_device_set_nb_threads_recovery);
  964. device_class_register_property(device_class, PROPERTY_COMPRESSION,
  965. PROPERTY_ACCESS_GET_MASK,
  966. device_simple_property_get_fn,
  967. NULL);
  968. device_class_register_property(device_class, PROPERTY_LEOM,
  969. PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
  970. device_simple_property_get_fn,
  971. property_set_leom_fn);
  972. device_class_register_property(device_class, PROPERTY_MAX_VOLUME_USAGE,
  973. (PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_MASK) &
  974. (~ PROPERTY_ACCESS_SET_INSIDE_FILE_WRITE),
  975. device_simple_property_get_fn,
  976. s3_device_set_max_volume_usage_fn);
  977. device_class_register_property(device_class, PROPERTY_ENFORCE_MAX_VOLUME_USAGE,
  978. (PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_MASK) &
  979. (~ PROPERTY_ACCESS_SET_INSIDE_FILE_WRITE),
  980. device_simple_property_get_fn,
  981. s3_device_set_enforce_max_volume_usage_fn);
  982. device_class_register_property(device_class, PROPERTY_S3_SUBDOMAIN,
  983. (PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_MASK) &
  984. (~ PROPERTY_ACCESS_SET_INSIDE_FILE_WRITE),
  985. device_simple_property_get_fn,
  986. s3_device_set_use_subdomain_fn);
  987. }
  988. static gboolean
  989. s3_device_set_access_key_fn(Device *p_self, DevicePropertyBase *base,
  990. GValue *val, PropertySurety surety, PropertySource source)
  991. {
  992. S3Device *self = S3_DEVICE(p_self);
  993. amfree(self->access_key);
  994. self->access_key = g_value_dup_string(val);
  995. device_clear_volume_details(p_self);
  996. return device_simple_property_set_fn(p_self, base, val, surety, source);
  997. }
  998. static gboolean
  999. s3_device_set_secret_key_fn(Device *p_self, DevicePropertyBase *base,
  1000. GValue *val, PropertySurety surety, PropertySource source)
  1001. {
  1002. S3Device *self = S3_DEVICE(p_self);
  1003. amfree(self->secret_key);
  1004. self->secret_key = g_value_dup_string(val);
  1005. device_clear_volume_details(p_self);
  1006. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1007. }
  1008. static gboolean
  1009. s3_device_set_swift_account_id_fn(Device *p_self, DevicePropertyBase *base,
  1010. GValue *val, PropertySurety surety, PropertySource source)
  1011. {
  1012. S3Device *self = S3_DEVICE(p_self);
  1013. amfree(self->swift_account_id);
  1014. self->swift_account_id = g_value_dup_string(val);
  1015. device_clear_volume_details(p_self);
  1016. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1017. }
  1018. static gboolean
  1019. s3_device_set_swift_access_key_fn(Device *p_self, DevicePropertyBase *base,
  1020. GValue *val, PropertySurety surety, PropertySource source)
  1021. {
  1022. S3Device *self = S3_DEVICE(p_self);
  1023. amfree(self->swift_access_key);
  1024. self->swift_access_key = g_value_dup_string(val);
  1025. device_clear_volume_details(p_self);
  1026. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1027. }
  1028. static gboolean
  1029. s3_device_set_host_fn(Device *p_self,
  1030. DevicePropertyBase *base, GValue *val,
  1031. PropertySurety surety, PropertySource source)
  1032. {
  1033. S3Device *self = S3_DEVICE(p_self);
  1034. amfree(self->host);
  1035. self->host = g_value_dup_string(val);
  1036. device_clear_volume_details(p_self);
  1037. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1038. }
  1039. static gboolean
  1040. s3_device_set_service_path_fn(Device *p_self,
  1041. DevicePropertyBase *base, GValue *val,
  1042. PropertySurety surety, PropertySource source)
  1043. {
  1044. S3Device *self = S3_DEVICE(p_self);
  1045. amfree(self->service_path);
  1046. self->service_path = g_value_dup_string(val);
  1047. device_clear_volume_details(p_self);
  1048. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1049. }
  1050. static gboolean
  1051. s3_device_set_user_token_fn(Device *p_self, DevicePropertyBase *base,
  1052. GValue *val, PropertySurety surety, PropertySource source)
  1053. {
  1054. S3Device *self = S3_DEVICE(p_self);
  1055. amfree(self->user_token);
  1056. self->user_token = g_value_dup_string(val);
  1057. device_clear_volume_details(p_self);
  1058. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1059. }
  1060. static gboolean
  1061. s3_device_set_bucket_location_fn(Device *p_self, DevicePropertyBase *base,
  1062. GValue *val, PropertySurety surety, PropertySource source)
  1063. {
  1064. S3Device *self = S3_DEVICE(p_self);
  1065. char *str_val = g_value_dup_string(val);
  1066. if (str_val[0] && self->use_ssl && !s3_curl_location_compat()) {
  1067. device_set_error(p_self, stralloc(_(
  1068. "Location constraint given for Amazon S3 bucket, "
  1069. "but libcurl is too old support wildcard certificates.")),
  1070. DEVICE_STATUS_DEVICE_ERROR);
  1071. goto fail;
  1072. }
  1073. if (str_val[0] && !s3_bucket_location_compat(self->bucket)) {
  1074. device_set_error(p_self, g_strdup_printf(_(
  1075. "Location constraint given for Amazon S3 bucket, "
  1076. "but the bucket name (%s) is not usable as a subdomain."),
  1077. self->bucket),
  1078. DEVICE_STATUS_DEVICE_ERROR);
  1079. goto fail;
  1080. }
  1081. amfree(self->bucket_location);
  1082. self->bucket_location = str_val;
  1083. device_clear_volume_details(p_self);
  1084. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1085. fail:
  1086. g_free(str_val);
  1087. return FALSE;
  1088. }
  1089. static gboolean
  1090. s3_device_set_storage_class_fn(Device *p_self, DevicePropertyBase *base,
  1091. GValue *val, PropertySurety surety, PropertySource source)
  1092. {
  1093. S3Device *self = S3_DEVICE(p_self);
  1094. char *str_val = g_value_dup_string(val);
  1095. amfree(self->storage_class);
  1096. self->storage_class = str_val;
  1097. device_clear_volume_details(p_self);
  1098. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1099. }
  1100. static gboolean
  1101. s3_device_set_server_side_encryption_fn(Device *p_self, DevicePropertyBase *base,
  1102. GValue *val, PropertySurety surety, PropertySource source)
  1103. {
  1104. S3Device *self = S3_DEVICE(p_self);
  1105. char *str_val = g_value_dup_string(val);
  1106. amfree(self->server_side_encryption);
  1107. self->server_side_encryption = str_val;
  1108. device_clear_volume_details(p_self);
  1109. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1110. }
  1111. static gboolean
  1112. s3_device_set_ca_info_fn(Device *p_self, DevicePropertyBase *base,
  1113. GValue *val, PropertySurety surety, PropertySource source)
  1114. {
  1115. S3Device *self = S3_DEVICE(p_self);
  1116. amfree(self->ca_info);
  1117. self->ca_info = g_value_dup_string(val);
  1118. device_clear_volume_details(p_self);
  1119. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1120. }
  1121. static gboolean
  1122. s3_device_set_verbose_fn(Device *p_self, DevicePropertyBase *base,
  1123. GValue *val, PropertySurety surety, PropertySource source)
  1124. {
  1125. S3Device *self = S3_DEVICE(p_self);
  1126. int thread;
  1127. self->verbose = g_value_get_boolean(val);
  1128. /* Our S3 handle may not yet have been instantiated; if so, it will
  1129. * get the proper verbose setting when it is created */
  1130. if (self->s3t) {
  1131. for (thread = 0; thread < self->nb_threads; thread++) {
  1132. if (self->s3t[thread].s3)
  1133. s3_verbose(self->s3t[thread].s3, self->verbose);
  1134. }
  1135. }
  1136. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1137. }
  1138. static gboolean
  1139. s3_device_set_openstack_swift_api_fn(Device *p_self, DevicePropertyBase *base,
  1140. GValue *val, PropertySurety surety, PropertySource source)
  1141. {
  1142. S3Device *self = S3_DEVICE(p_self);
  1143. self->openstack_swift_api = g_value_get_boolean(val);
  1144. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1145. }
  1146. static gboolean
  1147. s3_device_set_ssl_fn(Device *p_self, DevicePropertyBase *base,
  1148. GValue *val, PropertySurety surety, PropertySource source)
  1149. {
  1150. S3Device *self = S3_DEVICE(p_self);
  1151. gboolean new_val;
  1152. int thread;
  1153. new_val = g_value_get_boolean(val);
  1154. /* Our S3 handle may not yet have been instantiated; if so, it will
  1155. * get the proper use_ssl setting when it is created */
  1156. if (self->s3t) {
  1157. for (thread = 0; thread < self->nb_threads; thread++) {
  1158. if (self->s3t[thread].s3 && !s3_use_ssl(self->s3t[thread].s3, new_val)) {
  1159. device_set_error(p_self, g_strdup_printf(_(
  1160. "Error setting S3 SSL/TLS use "
  1161. "(tried to enable SSL/TLS for S3, but curl doesn't support it?)")),
  1162. DEVICE_STATUS_DEVICE_ERROR);
  1163. return FALSE;
  1164. }
  1165. }
  1166. }
  1167. self->use_ssl = new_val;
  1168. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1169. }
  1170. static gboolean
  1171. s3_device_set_max_send_speed_fn(Device *p_self,
  1172. DevicePropertyBase *base, GValue *val,
  1173. PropertySurety surety, PropertySource source)
  1174. {
  1175. S3Device *self = S3_DEVICE(p_self);
  1176. guint64 new_val;
  1177. int thread;
  1178. new_val = g_value_get_uint64(val);
  1179. if (self->s3t) {
  1180. for (thread = 0; thread < self->nb_threads; thread++) {
  1181. if (self->s3t[thread].s3 && !s3_set_max_send_speed(self->s3t[thread].s3, new_val)) {
  1182. device_set_error(p_self,
  1183. g_strdup("Could not set S3 maximum send speed"),
  1184. DEVICE_STATUS_DEVICE_ERROR);
  1185. return FALSE;
  1186. }
  1187. }
  1188. }
  1189. self->max_send_speed = new_val;
  1190. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1191. }
  1192. static gboolean
  1193. s3_device_set_max_recv_speed_fn(Device *p_self,
  1194. DevicePropertyBase *base, GValue *val,
  1195. PropertySurety surety, PropertySource source)
  1196. {
  1197. S3Device *self = S3_DEVICE(p_self);
  1198. guint64 new_val;
  1199. int thread;
  1200. new_val = g_value_get_uint64(val);
  1201. if (self->s3t) {
  1202. for (thread = 0; thread < self->nb_threads; thread++) {
  1203. if (self->s3t[thread].s3 &&
  1204. !s3_set_max_recv_speed(self->s3t[thread].s3, new_val)) {
  1205. device_set_error(p_self,
  1206. g_strdup("Could not set S3 maximum recv speed"),
  1207. DEVICE_STATUS_DEVICE_ERROR);
  1208. return FALSE;
  1209. }
  1210. }
  1211. }
  1212. self->max_recv_speed = new_val;
  1213. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1214. }
  1215. static gboolean
  1216. s3_device_set_nb_threads_backup(Device *p_self,
  1217. DevicePropertyBase *base, GValue *val,
  1218. PropertySurety surety, PropertySource source)
  1219. {
  1220. S3Device *self = S3_DEVICE(p_self);
  1221. guint64 new_val;
  1222. new_val = g_value_get_uint64(val);
  1223. self->nb_threads_backup = new_val;
  1224. if (self->nb_threads_backup > self->nb_threads) {
  1225. self->nb_threads = self->nb_threads_backup;
  1226. }
  1227. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1228. }
  1229. static gboolean
  1230. s3_device_set_nb_threads_recovery(Device *p_self,
  1231. DevicePropertyBase *base, GValue *val,
  1232. PropertySurety surety, PropertySource source)
  1233. {
  1234. S3Device *self = S3_DEVICE(p_self);
  1235. guint64 new_val;
  1236. new_val = g_value_get_uint64(val);
  1237. self->nb_threads_recovery = new_val;
  1238. if (self->nb_threads_recovery > self->nb_threads) {
  1239. self->nb_threads = self->nb_threads_recovery;
  1240. }
  1241. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1242. }
  1243. static gboolean
  1244. s3_device_set_max_volume_usage_fn(Device *p_self,
  1245. DevicePropertyBase *base, GValue *val,
  1246. PropertySurety surety, PropertySource source)
  1247. {
  1248. S3Device *self = S3_DEVICE(p_self);
  1249. self->volume_limit = g_value_get_uint64(val);
  1250. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1251. }
  1252. static gboolean
  1253. s3_device_set_enforce_max_volume_usage_fn(Device *p_self,
  1254. DevicePropertyBase *base, GValue *val,
  1255. PropertySurety surety, PropertySource source)
  1256. {
  1257. S3Device *self = S3_DEVICE(p_self);
  1258. self->enforce_volume_limit = g_value_get_boolean(val);
  1259. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1260. }
  1261. static gboolean
  1262. s3_device_set_use_subdomain_fn(Device *p_self,
  1263. DevicePropertyBase *base, GValue *val,
  1264. PropertySurety surety, PropertySource source)
  1265. {
  1266. S3Device *self = S3_DEVICE(p_self);
  1267. self->use_subdomain = g_value_get_boolean(val);
  1268. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1269. }
  1270. static gboolean
  1271. property_set_leom_fn(Device *p_self,
  1272. DevicePropertyBase *base, GValue *val,
  1273. PropertySurety surety, PropertySource source)
  1274. {
  1275. S3Device *self = S3_DEVICE(p_self);
  1276. self->leom = g_value_get_boolean(val);
  1277. return device_simple_property_set_fn(p_self, base, val, surety, source);
  1278. }
  1279. static Device*
  1280. s3_device_factory(char * device_name, char * device_type, char * device_node)
  1281. {
  1282. Device *rval;
  1283. g_assert(0 == strcmp(device_type, S3_DEVICE_NAME));
  1284. rval = DEVICE(g_object_new(TYPE_S3_DEVICE, NULL));

Large files files are truncated, but you can click here to view the full file