Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / cls / rgw / cls_rgw_client.h
1 #ifndef CEPH_CLS_RGW_CLIENT_H
2 #define CEPH_CLS_RGW_CLIENT_H
3
4 #include "include/str_list.h"
5 #include "include/rados/librados.hpp"
6 #include "cls_rgw_ops.h"
7 #include "common/RefCountedObj.h"
8 #include "include/compat.h"
9 #include "common/ceph_time.h"
10
11 // Forward declaration
12 class BucketIndexAioManager;
13 /*
14  * Bucket index AIO request argument, this is used to pass a argument
15  * to callback.
16  */
17 struct BucketIndexAioArg : public RefCountedObject {
18   BucketIndexAioArg(int _id, BucketIndexAioManager* _manager) :
19     id(_id), manager(_manager) {}
20   int id;
21   BucketIndexAioManager* manager;
22 };
23
24 /*
25  * This class manages AIO completions. This class is not completely thread-safe,
26  * methods like *get_next* is not thread-safe and is expected to be called from
27  * within one thread.
28  */
29 class BucketIndexAioManager {
30 private:
31   map<int, librados::AioCompletion*> pendings;
32   map<int, librados::AioCompletion*> completions;
33   map<int, string> pending_objs;
34   map<int, string> completion_objs;
35   int next;
36   Mutex lock;
37   Cond cond;
38   /*
39    * Callback implementation for AIO request.
40    */
41   static void bucket_index_op_completion_cb(void* cb, void* arg) {
42     BucketIndexAioArg* cb_arg = (BucketIndexAioArg*) arg;
43     cb_arg->manager->do_completion(cb_arg->id);
44     cb_arg->put();
45   }
46
47   /*
48    * Get next request ID. This method is not thread-safe.
49    *
50    * Return next request ID.
51    */
52   int get_next() { return next++; }
53     
54   /*
55    * Add a new pending AIO completion instance.
56    *
57    * @param id         - the request ID.
58    * @param completion - the AIO completion instance.
59    * @param oid        - the object id associated with the object, if it is NULL, we don't
60    *                     track the object id per callback.
61    */
62   void add_pending(int id, librados::AioCompletion* completion, const string& oid) {
63     pendings[id] = completion;
64     pending_objs[id] = oid;
65   }
66 public:
67   /*
68    * Create a new instance.
69    */
70   BucketIndexAioManager() : next(0), lock("BucketIndexAioManager::lock") {}
71
72
73   /*
74    * Do completion for the given AIO request.
75    */
76   void do_completion(int id);
77
78   /*
79    * Wait for AIO completions.
80    *
81    * valid_ret_code  - valid AIO return code.
82    * num_completions - number of completions.
83    * ret_code        - return code of failed AIO.
84    * objs            - a list of objects that has been finished the AIO.
85    *
86    * Return false if there is no pending AIO, true otherwise.
87    */
88   bool wait_for_completions(int valid_ret_code, int *num_completions, int *ret_code,
89       map<int, string> *objs);
90
91   /**
92    * Do aio read operation.
93    */
94   bool aio_operate(librados::IoCtx& io_ctx, const string& oid, librados::ObjectReadOperation *op) {
95     Mutex::Locker l(lock);
96     BucketIndexAioArg *arg = new BucketIndexAioArg(get_next(), this);
97     librados::AioCompletion *c = librados::Rados::aio_create_completion((void*)arg, NULL, bucket_index_op_completion_cb);
98     int r = io_ctx.aio_operate(oid, c, (librados::ObjectReadOperation*)op, NULL);
99     if (r >= 0) {
100       add_pending(arg->id, c, oid);
101     } else {
102       c->release();
103     }
104     return r;
105   }
106
107   /**
108    * Do aio write operation.
109    */
110   bool aio_operate(librados::IoCtx& io_ctx, const string& oid, librados::ObjectWriteOperation *op) {
111     Mutex::Locker l(lock);
112     BucketIndexAioArg *arg = new BucketIndexAioArg(get_next(), this);
113     librados::AioCompletion *c = librados::Rados::aio_create_completion((void*)arg, NULL, bucket_index_op_completion_cb);
114     int r = io_ctx.aio_operate(oid, c, (librados::ObjectWriteOperation*)op);
115     if (r >= 0) {
116       add_pending(arg->id, c, oid);
117     } else {
118       c->release();
119     }
120     return r;
121   }
122 };
123
124 class RGWGetDirHeader_CB : public RefCountedObject {
125 public:
126   ~RGWGetDirHeader_CB() override {}
127   virtual void handle_response(int r, rgw_bucket_dir_header& header) = 0;
128 };
129
130 class BucketIndexShardsManager {
131 private:
132   // Per shard setting manager, for example, marker.
133   map<int, string> value_by_shards;
134 public:
135   const static string KEY_VALUE_SEPARATOR;
136   const static string SHARDS_SEPARATOR;
137
138   void add(int shard, const string& value) {
139     value_by_shards[shard] = value;
140   }
141
142   const string& get(int shard, const string& default_value) {
143     map<int, string>::iterator iter = value_by_shards.find(shard);
144     return (iter == value_by_shards.end() ? default_value : iter->second);
145   }
146
147   map<int, string>& get() {
148     return value_by_shards;
149   }
150
151   bool empty() {
152     return value_by_shards.empty();
153   }
154
155   void to_string(string *out) const {
156     if (!out) {
157       return;
158     }
159     out->clear();
160     map<int, string>::const_iterator iter = value_by_shards.begin();
161     for (; iter != value_by_shards.end(); ++iter) {
162       if (out->length()) {
163         // Not the first item, append a separator first
164         out->append(SHARDS_SEPARATOR);
165       }
166       char buf[16];
167       snprintf(buf, sizeof(buf), "%d", iter->first);
168       out->append(buf);
169       out->append(KEY_VALUE_SEPARATOR);
170       out->append(iter->second);
171     }
172   }
173
174   static bool is_shards_marker(const string& marker) {
175     return marker.find(KEY_VALUE_SEPARATOR) != string::npos;
176   }
177
178   /*
179    * convert from string. There are two options of how the string looks like:
180    *
181    * 1. Single shard, no shard id specified, e.g. 000001.23.1
182    *
183    * for this case, if passed shard_id >= 0, use this shard id, otherwise assume that it's a
184    * bucket with no shards.
185    *
186    * 2. One or more shards, shard id specified for each shard, e.g., 0#00002.12,1#00003.23.2
187    *
188    */
189   int from_string(const string& composed_marker, int shard_id) {
190     value_by_shards.clear();
191     vector<string> shards;
192     get_str_vec(composed_marker, SHARDS_SEPARATOR.c_str(), shards);
193     if (shards.size() > 1 && shard_id >= 0) {
194       return -EINVAL;
195     }
196     vector<string>::const_iterator iter = shards.begin();
197     for (; iter != shards.end(); ++iter) {
198       size_t pos = iter->find(KEY_VALUE_SEPARATOR);
199       if (pos == string::npos) {
200         if (!value_by_shards.empty()) {
201           return -EINVAL;
202         }
203         if (shard_id < 0) {
204           add(0, *iter);
205         } else {
206           add(shard_id, *iter);
207         }
208         return 0;
209       }
210       string shard_str = iter->substr(0, pos);
211       string err;
212       int shard = (int)strict_strtol(shard_str.c_str(), 10, &err);
213       if (!err.empty()) {
214         return -EINVAL;
215       }
216       add(shard, iter->substr(pos + 1));
217     }
218     return 0;
219   }
220 };
221
222 /* bucket index */
223 void cls_rgw_bucket_init(librados::ObjectWriteOperation& o);
224
225 class CLSRGWConcurrentIO {
226 protected:
227   librados::IoCtx& io_ctx;
228   map<int, string>& objs_container;
229   map<int, string>::iterator iter;
230   uint32_t max_aio;
231   BucketIndexAioManager manager;
232
233   virtual int issue_op(int shard_id, const string& oid) = 0;
234
235   virtual void cleanup() {}
236   virtual int valid_ret_code() { return 0; }
237   // Return true if multiple rounds of OPs might be needed, this happens when
238   // OP needs to be re-send until a certain code is returned.
239   virtual bool need_multiple_rounds() { return false; }
240   // Add a new object to the end of the container.
241   virtual void add_object(int shard, const string& oid) {}
242   virtual void reset_container(map<int, string>& objs) {}
243
244 public:
245   CLSRGWConcurrentIO(librados::IoCtx& ioc, map<int, string>& _objs_container,
246                      uint32_t _max_aio) : io_ctx(ioc), objs_container(_objs_container), max_aio(_max_aio) {}
247   virtual ~CLSRGWConcurrentIO() {}
248
249   int operator()() {
250     int ret = 0;
251     iter = objs_container.begin();
252     for (; iter != objs_container.end() && max_aio-- > 0; ++iter) {
253       ret = issue_op(iter->first, iter->second);
254       if (ret < 0)
255         break;
256     }
257
258     int num_completions, r = 0;
259     map<int, string> objs;
260     map<int, string> *pobjs = (need_multiple_rounds() ? &objs : NULL);
261     while (manager.wait_for_completions(valid_ret_code(), &num_completions, &r, pobjs)) {
262       if (r >= 0 && ret >= 0) {
263         for(int i = 0; i < num_completions && iter != objs_container.end(); ++i, ++iter) {
264           int issue_ret = issue_op(iter->first, iter->second);
265           if(issue_ret < 0) {
266             ret = issue_ret;
267             break;
268           }
269         }
270       } else if (ret >= 0) {
271         ret = r;
272       }
273       if (need_multiple_rounds() && iter == objs_container.end() && !objs.empty()) {
274         // For those objects which need another round, use them to reset
275         // the container
276         reset_container(objs);
277       }
278     }
279
280     if (ret < 0) {
281       cleanup();
282     }
283     return ret;
284   }
285 };
286
287 class CLSRGWIssueBucketIndexInit : public CLSRGWConcurrentIO {
288 protected:
289   int issue_op(int shard_id, const string& oid) override;
290   int valid_ret_code() override { return -EEXIST; }
291   void cleanup() override;
292 public:
293   CLSRGWIssueBucketIndexInit(librados::IoCtx& ioc, map<int, string>& _bucket_objs,
294                      uint32_t _max_aio) :
295     CLSRGWConcurrentIO(ioc, _bucket_objs, _max_aio) {}
296 };
297
298 class CLSRGWIssueSetTagTimeout : public CLSRGWConcurrentIO {
299   uint64_t tag_timeout;
300 protected:
301   int issue_op(int shard_id, const string& oid) override;
302 public:
303   CLSRGWIssueSetTagTimeout(librados::IoCtx& ioc, map<int, string>& _bucket_objs,
304                      uint32_t _max_aio, uint64_t _tag_timeout) :
305     CLSRGWConcurrentIO(ioc, _bucket_objs, _max_aio), tag_timeout(_tag_timeout) {}
306 };
307
308 void cls_rgw_bucket_update_stats(librados::ObjectWriteOperation& o, bool absolute,
309                                  const map<uint8_t, rgw_bucket_category_stats>& stats);
310
311 void cls_rgw_bucket_prepare_op(librados::ObjectWriteOperation& o, RGWModifyOp op, string& tag,
312                                const cls_rgw_obj_key& key, const string& locator, bool log_op,
313                                uint16_t bilog_op, rgw_zone_set& zones_trace);
314
315 void cls_rgw_bucket_complete_op(librados::ObjectWriteOperation& o, RGWModifyOp op, string& tag,
316                                 rgw_bucket_entry_ver& ver,
317                                 const cls_rgw_obj_key& key,
318                                 rgw_bucket_dir_entry_meta& dir_meta,
319                                 list<cls_rgw_obj_key> *remove_objs, bool log_op,
320                                 uint16_t bilog_op, rgw_zone_set *zones_trace);
321
322 void cls_rgw_remove_obj(librados::ObjectWriteOperation& o, list<string>& keep_attr_prefixes);
323 void cls_rgw_obj_store_pg_ver(librados::ObjectWriteOperation& o, const string& attr);
324 void cls_rgw_obj_check_attrs_prefix(librados::ObjectOperation& o, const string& prefix, bool fail_if_exist);
325 void cls_rgw_obj_check_mtime(librados::ObjectOperation& o, const ceph::real_time& mtime, bool high_precision_time, RGWCheckMTimeType type);
326
327 int cls_rgw_bi_get(librados::IoCtx& io_ctx, const string oid,
328                    BIIndexType index_type, cls_rgw_obj_key& key,
329                    rgw_cls_bi_entry *entry);
330 int cls_rgw_bi_put(librados::IoCtx& io_ctx, const string oid, rgw_cls_bi_entry& entry);
331 void cls_rgw_bi_put(librados::ObjectWriteOperation& op, const string oid, rgw_cls_bi_entry& entry);
332 int cls_rgw_bi_list(librados::IoCtx& io_ctx, const string oid,
333                    const string& name, const string& marker, uint32_t max,
334                    list<rgw_cls_bi_entry> *entries, bool *is_truncated);
335
336
337 int cls_rgw_bucket_link_olh(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op,
338                             const string& oid, const cls_rgw_obj_key& key, bufferlist& olh_tag,
339                             bool delete_marker, const string& op_tag, struct rgw_bucket_dir_entry_meta *meta,
340                             uint64_t olh_epoch, ceph::real_time unmod_since, bool high_precision_time, bool log_op, rgw_zone_set& zones_trace);
341 int cls_rgw_bucket_unlink_instance(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op,
342                                    const string& oid, const cls_rgw_obj_key& key, const string& op_tag,
343                                    const string& olh_tag, uint64_t olh_epoch, bool log_op, rgw_zone_set& zones_trace);
344 int cls_rgw_get_olh_log(librados::IoCtx& io_ctx, string& oid, librados::ObjectReadOperation& op, const cls_rgw_obj_key& olh, uint64_t ver_marker,
345                         const string& olh_tag,
346                         map<uint64_t, vector<struct rgw_bucket_olh_log_entry> > *log, bool *is_truncated);
347 void cls_rgw_trim_olh_log(librados::ObjectWriteOperation& op, const cls_rgw_obj_key& olh, uint64_t ver, const string& olh_tag);
348 int cls_rgw_clear_olh(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op, string& oid, const cls_rgw_obj_key& olh, const string& olh_tag);
349
350 /**
351  * List the bucket with the starting object and filter prefix.
352  * NOTE: this method do listing requests for each bucket index shards identified by
353  *       the keys of the *list_results* map, which means the map should be popludated
354  *       by the caller to fill with each bucket index object id.
355  *
356  * io_ctx        - IO context for rados.
357  * start_obj     - marker for the listing.
358  * filter_prefix - filter prefix.
359  * num_entries   - number of entries to request for each object (note the total
360  *                 amount of entries returned depends on the number of shardings).
361  * list_results  - the list results keyed by bucket index object id.
362  * max_aio       - the maximum number of AIO (for throttling).
363  *
364  * Return 0 on success, a failure code otherwise.
365 */
366
367 class CLSRGWIssueBucketList : public CLSRGWConcurrentIO {
368   cls_rgw_obj_key start_obj;
369   string filter_prefix;
370   uint32_t num_entries;
371   bool list_versions;
372   map<int, rgw_cls_list_ret>& result;
373 protected:
374   int issue_op(int shard_id, const string& oid) override;
375 public:
376   CLSRGWIssueBucketList(librados::IoCtx& io_ctx, const cls_rgw_obj_key& _start_obj,
377                         const string& _filter_prefix, uint32_t _num_entries,
378                         bool _list_versions,
379                         map<int, string>& oids,
380                         map<int, struct rgw_cls_list_ret>& list_results,
381                         uint32_t max_aio) :
382   CLSRGWConcurrentIO(io_ctx, oids, max_aio),
383   start_obj(_start_obj), filter_prefix(_filter_prefix), num_entries(_num_entries), list_versions(_list_versions), result(list_results) {}
384 };
385
386 class CLSRGWIssueBILogList : public CLSRGWConcurrentIO {
387   map<int, struct cls_rgw_bi_log_list_ret>& result;
388   BucketIndexShardsManager& marker_mgr;
389   uint32_t max;
390 protected:
391   int issue_op(int shard_id, const string& oid) override;
392 public:
393   CLSRGWIssueBILogList(librados::IoCtx& io_ctx, BucketIndexShardsManager& _marker_mgr, uint32_t _max,
394                        map<int, string>& oids,
395                        map<int, struct cls_rgw_bi_log_list_ret>& bi_log_lists, uint32_t max_aio) :
396     CLSRGWConcurrentIO(io_ctx, oids, max_aio), result(bi_log_lists),
397     marker_mgr(_marker_mgr), max(_max) {}
398 };
399
400 class CLSRGWIssueBILogTrim : public CLSRGWConcurrentIO {
401   BucketIndexShardsManager& start_marker_mgr;
402   BucketIndexShardsManager& end_marker_mgr;
403 protected:
404   int issue_op(int shard_id, const string& oid) override;
405   // Trim until -ENODATA is returned.
406   int valid_ret_code() override { return -ENODATA; }
407   bool need_multiple_rounds() override { return true; }
408   void add_object(int shard, const string& oid) override { objs_container[shard] = oid; }
409   void reset_container(map<int, string>& objs) override {
410     objs_container.swap(objs);
411     iter = objs_container.begin();
412     objs.clear();
413   }
414 public:
415   CLSRGWIssueBILogTrim(librados::IoCtx& io_ctx, BucketIndexShardsManager& _start_marker_mgr,
416       BucketIndexShardsManager& _end_marker_mgr, map<int, string>& _bucket_objs, uint32_t max_aio) :
417     CLSRGWConcurrentIO(io_ctx, _bucket_objs, max_aio),
418     start_marker_mgr(_start_marker_mgr), end_marker_mgr(_end_marker_mgr) {}
419 };
420
421 /**
422  * Check the bucket index.
423  *
424  * io_ctx          - IO context for rados.
425  * bucket_objs_ret - check result for all shards.
426  * max_aio         - the maximum number of AIO (for throttling).
427  *
428  * Return 0 on success, a failure code otherwise.
429  */
430 class CLSRGWIssueBucketCheck : public CLSRGWConcurrentIO /*<map<string, struct rgw_cls_check_index_ret> >*/ {
431   map<int, struct rgw_cls_check_index_ret>& result;
432 protected:
433   int issue_op(int shard_id, const string& oid) override;
434 public:
435   CLSRGWIssueBucketCheck(librados::IoCtx& ioc, map<int, string>& oids, map<int, struct rgw_cls_check_index_ret>& bucket_objs_ret,
436                      uint32_t _max_aio) :
437     CLSRGWConcurrentIO(ioc, oids, _max_aio), result(bucket_objs_ret) {}
438 };
439
440 class CLSRGWIssueBucketRebuild : public CLSRGWConcurrentIO {
441 protected:
442   int issue_op(int shard_id, const string& oid) override;
443 public:
444   CLSRGWIssueBucketRebuild(librados::IoCtx& io_ctx, map<int, string>& bucket_objs,
445                            uint32_t max_aio) : CLSRGWConcurrentIO(io_ctx, bucket_objs, max_aio) {}
446 };
447
448 class CLSRGWIssueGetDirHeader : public CLSRGWConcurrentIO {
449   map<int, rgw_cls_list_ret>& result;
450 protected:
451   int issue_op(int shard_id, const string& oid) override;
452 public:
453   CLSRGWIssueGetDirHeader(librados::IoCtx& io_ctx, map<int, string>& oids, map<int, rgw_cls_list_ret>& dir_headers,
454                           uint32_t max_aio) :
455     CLSRGWConcurrentIO(io_ctx, oids, max_aio), result(dir_headers) {}
456 };
457
458 class CLSRGWIssueSetBucketResharding : public CLSRGWConcurrentIO {
459   cls_rgw_bucket_instance_entry entry;
460 protected:
461   int issue_op(int shard_id, const string& oid) override;
462 public:
463   CLSRGWIssueSetBucketResharding(librados::IoCtx& ioc, map<int, string>& _bucket_objs,
464                                  const cls_rgw_bucket_instance_entry& _entry,
465                                  uint32_t _max_aio) : CLSRGWConcurrentIO(ioc, _bucket_objs, _max_aio), entry(_entry) {}
466 };
467
468 class CLSRGWIssueResyncBucketBILog : public CLSRGWConcurrentIO {
469 protected:
470   int issue_op(int shard_id, const string& oid);
471 public:
472   CLSRGWIssueResyncBucketBILog(librados::IoCtx& io_ctx, map<int, string>& _bucket_objs, uint32_t max_aio) :
473     CLSRGWConcurrentIO(io_ctx, _bucket_objs, max_aio) {}
474 };
475
476 class CLSRGWIssueBucketBILogStop : public CLSRGWConcurrentIO {
477 protected:
478   int issue_op(int shard_id, const string& oid);
479 public:
480   CLSRGWIssueBucketBILogStop(librados::IoCtx& io_ctx, map<int, string>& _bucket_objs, uint32_t max_aio) :
481     CLSRGWConcurrentIO(io_ctx, _bucket_objs, max_aio) {}
482 };
483
484 int cls_rgw_get_dir_header_async(librados::IoCtx& io_ctx, string& oid, RGWGetDirHeader_CB *ctx);
485
486 void cls_rgw_encode_suggestion(char op, rgw_bucket_dir_entry& dirent, bufferlist& updates);
487
488 void cls_rgw_suggest_changes(librados::ObjectWriteOperation& o, bufferlist& updates);
489
490 /* usage logging */
491 int cls_rgw_usage_log_read(librados::IoCtx& io_ctx, string& oid, string& user,
492                            uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries,
493                            string& read_iter, map<rgw_user_bucket, rgw_usage_log_entry>& usage,
494                            bool *is_truncated);
495
496 void cls_rgw_usage_log_trim(librados::ObjectWriteOperation& op, string& user,
497                            uint64_t start_epoch, uint64_t end_epoch);
498
499 void cls_rgw_usage_log_add(librados::ObjectWriteOperation& op, rgw_usage_log_info& info);
500
501 /* garbage collection */
502 void cls_rgw_gc_set_entry(librados::ObjectWriteOperation& op, uint32_t expiration_secs, cls_rgw_gc_obj_info& info);
503 void cls_rgw_gc_defer_entry(librados::ObjectWriteOperation& op, uint32_t expiration_secs, const string& tag);
504
505 int cls_rgw_gc_list(librados::IoCtx& io_ctx, string& oid, string& marker, uint32_t max, bool expired_only,
506                     list<cls_rgw_gc_obj_info>& entries, bool *truncated, string& next_marker);
507
508 void cls_rgw_gc_remove(librados::ObjectWriteOperation& op, const list<string>& tags);
509
510 /* lifecycle */
511 int cls_rgw_lc_get_head(librados::IoCtx& io_ctx, string& oid, cls_rgw_lc_obj_head& head);
512 int cls_rgw_lc_put_head(librados::IoCtx& io_ctx, string& oid, cls_rgw_lc_obj_head& head);
513 int cls_rgw_lc_get_next_entry(librados::IoCtx& io_ctx, string& oid, string& marker, pair<string, int>& entry);
514 int cls_rgw_lc_rm_entry(librados::IoCtx& io_ctx, string& oid, pair<string, int>& entry);
515 int cls_rgw_lc_set_entry(librados::IoCtx& io_ctx, string& oid, pair<string, int>& entry);
516 int cls_rgw_lc_list(librados::IoCtx& io_ctx, string& oid,
517                     const string& marker,
518                     uint32_t max_entries,
519                     map<string, int>& entries);
520
521 /* resharding */
522 void cls_rgw_reshard_add(librados::ObjectWriteOperation& op, const cls_rgw_reshard_entry& entry);
523 int cls_rgw_reshard_list(librados::IoCtx& io_ctx, const string& oid, string& marker, uint32_t max,
524                          list<cls_rgw_reshard_entry>& entries, bool* is_truncated);
525 int cls_rgw_reshard_get(librados::IoCtx& io_ctx, const string& oid, cls_rgw_reshard_entry& entry);
526 int cls_rgw_reshard_get_head(librados::IoCtx& io_ctx, const string& oid, cls_rgw_reshard_entry& entry);
527 void cls_rgw_reshard_remove(librados::ObjectWriteOperation& op, const cls_rgw_reshard_entry& entry);
528
529 /* resharding attribute  */
530 int cls_rgw_set_bucket_resharding(librados::IoCtx& io_ctx, const string& oid,
531                                   const cls_rgw_bucket_instance_entry& entry);
532 int cls_rgw_clear_bucket_resharding(librados::IoCtx& io_ctx, const string& oid);
533 void cls_rgw_guard_bucket_resharding(librados::ObjectOperation& op, int ret_err);
534 int cls_rgw_get_bucket_resharding(librados::IoCtx& io_ctx, const string& oid,
535                                   cls_rgw_bucket_instance_entry *entry);
536
537 #endif