PageRenderTime 96ms CodeModel.GetById 27ms RepoModel.GetById 3ms app.codeStats 1ms

/amanda/trunk/device-src/s3-device.c

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

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