Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / cls / rgw / cls_rgw_client.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 #include <errno.h>
4
5 #include "cls/rgw/cls_rgw_const.h"
6 #include "cls/rgw/cls_rgw_client.h"
7
8 #include "common/debug.h"
9
10 using namespace librados;
11
12 const string BucketIndexShardsManager::KEY_VALUE_SEPARATOR = "#";
13 const string BucketIndexShardsManager::SHARDS_SEPARATOR = ",";
14
15 /**
16  * This class represents the bucket index object operation callback context.
17  */
18 template <typename T>
19 class ClsBucketIndexOpCtx : public ObjectOperationCompletion {
20 private:
21   T *data;
22   int *ret_code;
23 public:
24   ClsBucketIndexOpCtx(T* _data, int *_ret_code) : data(_data), ret_code(_ret_code) { assert(data); }
25   ~ClsBucketIndexOpCtx() override {}
26   void handle_completion(int r, bufferlist& outbl) override {
27     if (r >= 0) {
28       try {
29         bufferlist::iterator iter = outbl.begin();
30         ::decode((*data), iter);
31       } catch (buffer::error& err) {
32         r = -EIO;
33       }
34     }
35     if (ret_code) {
36       *ret_code = r;
37     }
38   }
39 };
40
41 void BucketIndexAioManager::do_completion(int id) {
42   Mutex::Locker l(lock);
43
44   map<int, librados::AioCompletion*>::iterator iter = pendings.find(id);
45   assert(iter != pendings.end());
46   completions[id] = iter->second;
47   pendings.erase(iter);
48
49   // If the caller needs a list of finished objects, store them
50   // for further processing
51   map<int, string>::iterator miter = pending_objs.find(id);
52   if (miter != pending_objs.end()) {
53     completion_objs[id] = miter->second;
54     pending_objs.erase(miter);
55   }
56
57   cond.Signal();
58 }
59
60 bool BucketIndexAioManager::wait_for_completions(int valid_ret_code,
61     int *num_completions, int *ret_code, map<int, string> *objs) {
62   lock.Lock();
63   if (pendings.empty() && completions.empty()) {
64     lock.Unlock();
65     return false;
66   }
67
68   if (completions.empty()) {
69     // Wait for AIO completion
70     cond.Wait(lock);
71   }
72
73   // Clear the completed AIOs
74   map<int, librados::AioCompletion*>::iterator iter = completions.begin();
75   for (; iter != completions.end(); ++iter) {
76     int r = iter->second->get_return_value();
77     if (objs && r == 0) { /* update list of successfully completed objs */
78       map<int, string>::iterator liter = completion_objs.find(iter->first);
79       if (liter != completion_objs.end()) {
80         (*objs)[liter->first] = liter->second;
81       }
82     }
83     if (ret_code && (r < 0 && r != valid_ret_code))
84       (*ret_code) = r;
85     iter->second->release();
86   }
87   if (num_completions)
88     (*num_completions) = completions.size();
89   completions.clear();
90   lock.Unlock();
91
92   return true;
93 }
94
95 void cls_rgw_bucket_init(ObjectWriteOperation& o)
96 {
97   bufferlist in;
98   o.exec(RGW_CLASS, RGW_BUCKET_INIT_INDEX, in);
99 }
100
101 static bool issue_bucket_index_init_op(librados::IoCtx& io_ctx,
102     const string& oid, BucketIndexAioManager *manager) {
103   bufferlist in;
104   librados::ObjectWriteOperation op;
105   op.create(true);
106   op.exec(RGW_CLASS, RGW_BUCKET_INIT_INDEX, in);
107   return manager->aio_operate(io_ctx, oid, &op);
108 }
109
110 static bool issue_bucket_set_tag_timeout_op(librados::IoCtx& io_ctx,
111     const string& oid, uint64_t timeout, BucketIndexAioManager *manager) {
112   bufferlist in;
113   struct rgw_cls_tag_timeout_op call;
114   call.tag_timeout = timeout;
115   ::encode(call, in);
116   ObjectWriteOperation op;
117   op.exec(RGW_CLASS, RGW_BUCKET_SET_TAG_TIMEOUT, in);
118   return manager->aio_operate(io_ctx, oid, &op);
119 }
120
121 int CLSRGWIssueBucketIndexInit::issue_op(int shard_id, const string& oid)
122 {
123   return issue_bucket_index_init_op(io_ctx, oid, &manager);
124 }
125
126 void CLSRGWIssueBucketIndexInit::cleanup()
127 {
128   // Do best effort removal
129   for (map<int, string>::iterator citer = objs_container.begin(); citer != iter; ++citer) {
130     io_ctx.remove(citer->second);
131   }
132 }
133
134 int CLSRGWIssueSetTagTimeout::issue_op(int shard_id, const string& oid)
135 {
136   return issue_bucket_set_tag_timeout_op(io_ctx, oid, tag_timeout, &manager);
137 }
138
139 void cls_rgw_bucket_update_stats(librados::ObjectWriteOperation& o, bool absolute,
140                                  const map<uint8_t, rgw_bucket_category_stats>& stats)
141 {
142   struct rgw_cls_bucket_update_stats_op call;
143   call.absolute = absolute;
144   call.stats = stats;
145   bufferlist in;
146   ::encode(call, in);
147   o.exec(RGW_CLASS, RGW_BUCKET_UPDATE_STATS, in);
148 }
149
150 void cls_rgw_bucket_prepare_op(ObjectWriteOperation& o, RGWModifyOp op, string& tag,
151                                const cls_rgw_obj_key& key, const string& locator, bool log_op,
152                                uint16_t bilog_flags, rgw_zone_set& zones_trace)
153 {
154   struct rgw_cls_obj_prepare_op call;
155   call.op = op;
156   call.tag = tag;
157   call.key = key;
158   call.locator = locator;
159   call.log_op = log_op;
160   call.bilog_flags = bilog_flags;
161   call.zones_trace = zones_trace;
162   bufferlist in;
163   ::encode(call, in);
164   o.exec(RGW_CLASS, RGW_BUCKET_PREPARE_OP, in);
165 }
166
167 void cls_rgw_bucket_complete_op(ObjectWriteOperation& o, RGWModifyOp op, string& tag,
168                                 rgw_bucket_entry_ver& ver,
169                                 const cls_rgw_obj_key& key,
170                                 rgw_bucket_dir_entry_meta& dir_meta,
171                                 list<cls_rgw_obj_key> *remove_objs, bool log_op,
172                                 uint16_t bilog_flags,
173                                 rgw_zone_set *zones_trace)
174 {
175
176   bufferlist in;
177   struct rgw_cls_obj_complete_op call;
178   call.op = op;
179   call.tag = tag;
180   call.key = key;
181   call.ver = ver;
182   call.meta = dir_meta;
183   call.log_op = log_op;
184   call.bilog_flags = bilog_flags;
185   if (remove_objs)
186     call.remove_objs = *remove_objs;
187   if (zones_trace) {
188     call.zones_trace = *zones_trace;
189   }
190   ::encode(call, in);
191   o.exec(RGW_CLASS, RGW_BUCKET_COMPLETE_OP, in);
192 }
193
194 static bool issue_bucket_list_op(librados::IoCtx& io_ctx,
195     const string& oid, const cls_rgw_obj_key& start_obj, const string& filter_prefix,
196     uint32_t num_entries, bool list_versions, BucketIndexAioManager *manager,
197     struct rgw_cls_list_ret *pdata) {
198   bufferlist in;
199   struct rgw_cls_list_op call;
200   call.start_obj = start_obj;
201   call.filter_prefix = filter_prefix;
202   call.num_entries = num_entries;
203   call.list_versions = list_versions;
204   ::encode(call, in);
205
206   librados::ObjectReadOperation op;
207   op.exec(RGW_CLASS, RGW_BUCKET_LIST, in, new ClsBucketIndexOpCtx<struct rgw_cls_list_ret>(pdata, NULL));
208   return manager->aio_operate(io_ctx, oid, &op);
209 }
210
211 int CLSRGWIssueBucketList::issue_op(int shard_id, const string& oid)
212 {
213   return issue_bucket_list_op(io_ctx, oid, start_obj, filter_prefix, num_entries, list_versions, &manager, &result[shard_id]);
214 }
215
216 void cls_rgw_remove_obj(librados::ObjectWriteOperation& o, list<string>& keep_attr_prefixes)
217 {
218   bufferlist in;
219   struct rgw_cls_obj_remove_op call;
220   call.keep_attr_prefixes = keep_attr_prefixes;
221   ::encode(call, in);
222   o.exec(RGW_CLASS, RGW_OBJ_REMOVE, in);
223 }
224
225 void cls_rgw_obj_store_pg_ver(librados::ObjectWriteOperation& o, const string& attr)
226 {
227   bufferlist in;
228   struct rgw_cls_obj_store_pg_ver_op call;
229   call.attr = attr;
230   ::encode(call, in);
231   o.exec(RGW_CLASS, RGW_OBJ_STORE_PG_VER, in);
232 }
233
234 void cls_rgw_obj_check_attrs_prefix(librados::ObjectOperation& o, const string& prefix, bool fail_if_exist)
235 {
236   bufferlist in;
237   struct rgw_cls_obj_check_attrs_prefix call;
238   call.check_prefix = prefix;
239   call.fail_if_exist = fail_if_exist;
240   ::encode(call, in);
241   o.exec(RGW_CLASS, RGW_OBJ_CHECK_ATTRS_PREFIX, in);
242 }
243
244 void cls_rgw_obj_check_mtime(librados::ObjectOperation& o, const real_time& mtime, bool high_precision_time, RGWCheckMTimeType type)
245 {
246   bufferlist in;
247   struct rgw_cls_obj_check_mtime call;
248   call.mtime = mtime;
249   call.high_precision_time = high_precision_time;
250   call.type = type;
251   ::encode(call, in);
252   o.exec(RGW_CLASS, RGW_OBJ_CHECK_MTIME, in);
253 }
254
255 int cls_rgw_bi_get(librados::IoCtx& io_ctx, const string oid,
256                    BIIndexType index_type, cls_rgw_obj_key& key,
257                    rgw_cls_bi_entry *entry)
258 {
259   bufferlist in, out;
260   struct rgw_cls_bi_get_op call;
261   call.key = key;
262   call.type = index_type;
263   ::encode(call, in);
264   int r = io_ctx.exec(oid, RGW_CLASS, RGW_BI_GET, in, out);
265   if (r < 0)
266     return r;
267
268   struct rgw_cls_bi_get_ret op_ret;
269   bufferlist::iterator iter = out.begin();
270   try {
271     ::decode(op_ret, iter);
272   } catch (buffer::error& err) {
273     return -EIO;
274   }
275
276   *entry = op_ret.entry;
277
278   return 0;
279 }
280
281 int cls_rgw_bi_put(librados::IoCtx& io_ctx, const string oid, rgw_cls_bi_entry& entry)
282 {
283   bufferlist in, out;
284   struct rgw_cls_bi_put_op call;
285   call.entry = entry;
286   ::encode(call, in);
287   int r = io_ctx.exec(oid, RGW_CLASS, RGW_BI_PUT, in, out);
288   if (r < 0)
289     return r;
290
291   return 0;
292 }
293
294 void cls_rgw_bi_put(ObjectWriteOperation& op, const string oid, rgw_cls_bi_entry& entry)
295 {
296   bufferlist in, out;
297   struct rgw_cls_bi_put_op call;
298   call.entry = entry;
299   ::encode(call, in);
300   op.exec(RGW_CLASS, RGW_BI_PUT, in);
301 }
302
303 int cls_rgw_bi_list(librados::IoCtx& io_ctx, const string oid,
304                    const string& name, const string& marker, uint32_t max,
305                    list<rgw_cls_bi_entry> *entries, bool *is_truncated)
306 {
307   bufferlist in, out;
308   struct rgw_cls_bi_list_op call;
309   call.name = name;
310   call.marker = marker;
311   call.max = max;
312   ::encode(call, in);
313   int r = io_ctx.exec(oid, RGW_CLASS, RGW_BI_LIST, in, out);
314   if (r < 0)
315     return r;
316
317   struct rgw_cls_bi_list_ret op_ret;
318   bufferlist::iterator iter = out.begin();
319   try {
320     ::decode(op_ret, iter);
321   } catch (buffer::error& err) {
322     return -EIO;
323   }
324
325   entries->swap(op_ret.entries);
326   *is_truncated = op_ret.is_truncated;
327
328   return 0;
329 }
330
331 int cls_rgw_bucket_link_olh(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op,
332                             const string& oid, const cls_rgw_obj_key& key, bufferlist& olh_tag,
333                             bool delete_marker, const string& op_tag, struct rgw_bucket_dir_entry_meta *meta,
334                             uint64_t olh_epoch, ceph::real_time unmod_since, bool high_precision_time, bool log_op, rgw_zone_set& zones_trace)
335 {
336   bufferlist in, out;
337   struct rgw_cls_link_olh_op call;
338   call.key = key;
339   call.olh_tag = string(olh_tag.c_str(), olh_tag.length());
340   call.op_tag = op_tag;
341   call.delete_marker = delete_marker;
342   if (meta) {
343     call.meta = *meta;
344   }
345   call.olh_epoch = olh_epoch;
346   call.log_op = log_op;
347   call.unmod_since = unmod_since;
348   call.high_precision_time = high_precision_time;
349   call.zones_trace = zones_trace;
350   ::encode(call, in);
351   op.exec(RGW_CLASS, RGW_BUCKET_LINK_OLH, in);
352   int r = io_ctx.operate(oid, &op);
353   if (r < 0)
354     return r;
355
356   return 0;
357 }
358
359 int cls_rgw_bucket_unlink_instance(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op,
360                                    const string& oid,
361                                    const cls_rgw_obj_key& key, const string& op_tag,
362                                    const string& olh_tag, uint64_t olh_epoch, bool log_op, rgw_zone_set& zones_trace)
363 {
364   bufferlist in, out;
365   struct rgw_cls_unlink_instance_op call;
366   call.key = key;
367   call.op_tag = op_tag;
368   call.olh_epoch = olh_epoch;
369   call.olh_tag = olh_tag;
370   call.log_op = log_op;
371   call.zones_trace = zones_trace;
372   ::encode(call, in);
373   op.exec(RGW_CLASS, RGW_BUCKET_UNLINK_INSTANCE, in);
374   int r = io_ctx.operate(oid, &op);
375   if (r < 0)
376     return r;
377
378   return 0;
379 }
380
381 int cls_rgw_get_olh_log(IoCtx& io_ctx, string& oid, librados::ObjectReadOperation& op, const cls_rgw_obj_key& olh, uint64_t ver_marker,
382                         const string& olh_tag,
383                         map<uint64_t, vector<struct rgw_bucket_olh_log_entry> > *log, bool *is_truncated)
384 {
385   bufferlist in, out;
386   struct rgw_cls_read_olh_log_op call;
387   call.olh = olh;
388   call.ver_marker = ver_marker;
389   call.olh_tag = olh_tag;
390   ::encode(call, in);
391   int op_ret;
392   op.exec(RGW_CLASS, RGW_BUCKET_READ_OLH_LOG, in, &out, &op_ret);
393   int r = io_ctx.operate(oid, &op, NULL);
394   if (r < 0) {
395     return r;
396   }
397   if (op_ret < 0) {
398     return op_ret;
399   }
400
401   struct rgw_cls_read_olh_log_ret ret;
402   try {
403     bufferlist::iterator iter = out.begin();
404     ::decode(ret, iter);
405   } catch (buffer::error& err) {
406     return -EIO;
407   }
408
409   if (log) {
410     *log = ret.log;
411   }
412   if (is_truncated) {
413     *is_truncated = ret.is_truncated;
414   }
415
416  return r;
417 }
418
419 void cls_rgw_trim_olh_log(librados::ObjectWriteOperation& op, const cls_rgw_obj_key& olh, uint64_t ver, const string& olh_tag)
420 {
421   bufferlist in;
422   struct rgw_cls_trim_olh_log_op call;
423   call.olh = olh;
424   call.ver = ver;
425   call.olh_tag = olh_tag;
426   ::encode(call, in);
427   op.exec(RGW_CLASS, RGW_BUCKET_TRIM_OLH_LOG, in);
428 }
429
430 int cls_rgw_clear_olh(IoCtx& io_ctx, librados::ObjectWriteOperation& op, string& oid, const cls_rgw_obj_key& olh, const string& olh_tag)
431 {
432   bufferlist in, out;
433   struct rgw_cls_bucket_clear_olh_op call;
434   call.key = olh;
435   call.olh_tag = olh_tag;
436   ::encode(call, in);
437   int op_ret;
438   op.exec(RGW_CLASS, RGW_BUCKET_CLEAR_OLH, in, &out, &op_ret);
439   int r = io_ctx.operate(oid, &op);
440   if (r < 0) {
441     return r;
442   }
443   return op_ret;
444 }
445
446 static bool issue_bi_log_list_op(librados::IoCtx& io_ctx, const string& oid, int shard_id,
447                                  BucketIndexShardsManager& marker_mgr, uint32_t max, BucketIndexAioManager *manager,
448     struct cls_rgw_bi_log_list_ret *pdata) {
449   bufferlist in;
450   cls_rgw_bi_log_list_op call;
451   call.marker = marker_mgr.get(shard_id, "");
452   call.max = max;
453   ::encode(call, in);
454
455   librados::ObjectReadOperation op;
456   op.exec(RGW_CLASS, RGW_BI_LOG_LIST, in, new ClsBucketIndexOpCtx<struct cls_rgw_bi_log_list_ret>(pdata, NULL));
457   return manager->aio_operate(io_ctx, oid, &op);
458 }
459
460 int CLSRGWIssueBILogList::issue_op(int shard_id, const string& oid)
461 {
462   return issue_bi_log_list_op(io_ctx, oid, shard_id, marker_mgr, max, &manager, &result[shard_id]);
463 }
464
465 static bool issue_bi_log_trim(librados::IoCtx& io_ctx, const string& oid, int shard_id,
466                               BucketIndexShardsManager& start_marker_mgr,
467                               BucketIndexShardsManager& end_marker_mgr, BucketIndexAioManager *manager) {
468   bufferlist in;
469   cls_rgw_bi_log_trim_op call;
470   call.start_marker = start_marker_mgr.get(shard_id, "");
471   call.end_marker = end_marker_mgr.get(shard_id, "");
472   ::encode(call, in);
473   ObjectWriteOperation op;
474   op.exec(RGW_CLASS, RGW_BI_LOG_TRIM, in);
475   return manager->aio_operate(io_ctx, oid, &op);
476 }
477
478 int CLSRGWIssueBILogTrim::issue_op(int shard_id, const string& oid)
479 {
480   return issue_bi_log_trim(io_ctx, oid, shard_id, start_marker_mgr, end_marker_mgr, &manager);
481 }
482
483 static bool issue_bucket_check_index_op(IoCtx& io_ctx, const string& oid, BucketIndexAioManager *manager,
484     struct rgw_cls_check_index_ret *pdata) {
485   bufferlist in;
486   librados::ObjectReadOperation op;
487   op.exec(RGW_CLASS, RGW_BUCKET_CHECK_INDEX, in, new ClsBucketIndexOpCtx<struct rgw_cls_check_index_ret>(
488         pdata, NULL));
489   return manager->aio_operate(io_ctx, oid, &op);
490 }
491
492 int CLSRGWIssueBucketCheck::issue_op(int shard_id, const string& oid)
493 {
494   return issue_bucket_check_index_op(io_ctx, oid, &manager, &result[shard_id]);
495 }
496
497 static bool issue_bucket_rebuild_index_op(IoCtx& io_ctx, const string& oid,
498     BucketIndexAioManager *manager) {
499   bufferlist in;
500   librados::ObjectWriteOperation op;
501   op.exec(RGW_CLASS, RGW_BUCKET_REBUILD_INDEX, in);
502   return manager->aio_operate(io_ctx, oid, &op);
503 }
504
505 int CLSRGWIssueBucketRebuild::issue_op(int shard_id, const string& oid)
506 {
507   return issue_bucket_rebuild_index_op(io_ctx, oid, &manager);
508 }
509
510 void cls_rgw_encode_suggestion(char op, rgw_bucket_dir_entry& dirent, bufferlist& updates)
511 {
512   updates.append(op);
513   ::encode(dirent, updates);
514 }
515
516 void cls_rgw_suggest_changes(ObjectWriteOperation& o, bufferlist& updates)
517 {
518   o.exec(RGW_CLASS, RGW_DIR_SUGGEST_CHANGES, updates);
519 }
520
521 int CLSRGWIssueGetDirHeader::issue_op(int shard_id, const string& oid)
522 {
523   cls_rgw_obj_key nokey;
524   return issue_bucket_list_op(io_ctx, oid, nokey, "", 0, false, &manager, &result[shard_id]);
525 }
526
527 static bool issue_resync_bi_log(librados::IoCtx& io_ctx, const string& oid, BucketIndexAioManager *manager)
528 {
529   bufferlist in;
530   librados::ObjectWriteOperation op;
531   op.exec("rgw", "bi_log_resync", in);
532   return manager->aio_operate(io_ctx, oid, &op);
533 }
534
535 int CLSRGWIssueResyncBucketBILog::issue_op(int shard_id, const string& oid)
536 {
537   return issue_resync_bi_log(io_ctx, oid, &manager);
538 }
539
540 static bool issue_bi_log_stop(librados::IoCtx& io_ctx, const string& oid, BucketIndexAioManager *manager)
541 {
542   bufferlist in;
543   librados::ObjectWriteOperation op;
544   op.exec("rgw", "bi_log_stop", in);
545   return manager->aio_operate(io_ctx, oid, &op); 
546 }
547
548 int CLSRGWIssueBucketBILogStop::issue_op(int shard_id, const string& oid)
549 {
550   return issue_bi_log_stop(io_ctx, oid, &manager);
551 }
552
553 class GetDirHeaderCompletion : public ObjectOperationCompletion {
554   RGWGetDirHeader_CB *ret_ctx;
555 public:
556   explicit GetDirHeaderCompletion(RGWGetDirHeader_CB *_ctx) : ret_ctx(_ctx) {}
557   ~GetDirHeaderCompletion() override {
558     ret_ctx->put();
559   }
560   void handle_completion(int r, bufferlist& outbl) override {
561     struct rgw_cls_list_ret ret;
562     try {
563       bufferlist::iterator iter = outbl.begin();
564       ::decode(ret, iter);
565     } catch (buffer::error& err) {
566       r = -EIO;
567     }
568
569     ret_ctx->handle_response(r, ret.dir.header);
570   }
571 };
572
573 int cls_rgw_get_dir_header_async(IoCtx& io_ctx, string& oid, RGWGetDirHeader_CB *ctx)
574 {
575   bufferlist in, out;
576   struct rgw_cls_list_op call;
577   call.num_entries = 0;
578   ::encode(call, in);
579   ObjectReadOperation op;
580   GetDirHeaderCompletion *cb = new GetDirHeaderCompletion(ctx);
581   op.exec(RGW_CLASS, RGW_BUCKET_LIST, in, cb);
582   AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL);
583   int r = io_ctx.aio_operate(oid, c, &op, NULL);
584   c->release();
585   if (r < 0)
586     return r;
587
588   return 0;
589 }
590
591 int cls_rgw_usage_log_read(IoCtx& io_ctx, string& oid, string& user,
592                            uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries,
593                            string& read_iter, map<rgw_user_bucket, rgw_usage_log_entry>& usage,
594                            bool *is_truncated)
595 {
596   if (is_truncated)
597     *is_truncated = false;
598
599   bufferlist in, out;
600   rgw_cls_usage_log_read_op call;
601   call.start_epoch = start_epoch;
602   call.end_epoch = end_epoch;
603   call.owner = user;
604   call.max_entries = max_entries;
605   call.iter = read_iter;
606   ::encode(call, in);
607   int r = io_ctx.exec(oid, RGW_CLASS, RGW_USER_USAGE_LOG_READ, in, out);
608   if (r < 0)
609     return r;
610
611   try {
612     rgw_cls_usage_log_read_ret result;
613     bufferlist::iterator iter = out.begin();
614     ::decode(result, iter);
615     read_iter = result.next_iter;
616     if (is_truncated)
617       *is_truncated = result.truncated;
618
619     usage = result.usage;
620   } catch (buffer::error& e) {
621     return -EINVAL;
622   }
623
624   return 0;
625 }
626
627 void cls_rgw_usage_log_trim(ObjectWriteOperation& op, string& user,
628                            uint64_t start_epoch, uint64_t end_epoch)
629 {
630   bufferlist in;
631   rgw_cls_usage_log_trim_op call;
632   call.start_epoch = start_epoch;
633   call.end_epoch = end_epoch;
634   call.user = user;
635   ::encode(call, in);
636   op.exec(RGW_CLASS, RGW_USER_USAGE_LOG_TRIM, in);
637 }
638
639 void cls_rgw_usage_log_add(ObjectWriteOperation& op, rgw_usage_log_info& info)
640 {
641   bufferlist in;
642   rgw_cls_usage_log_add_op call;
643   call.info = info;
644   ::encode(call, in);
645   op.exec(RGW_CLASS, RGW_USER_USAGE_LOG_ADD, in);
646 }
647
648 /* garbage collection */
649
650 void cls_rgw_gc_set_entry(ObjectWriteOperation& op, uint32_t expiration_secs, cls_rgw_gc_obj_info& info)
651 {
652   bufferlist in;
653   cls_rgw_gc_set_entry_op call;
654   call.expiration_secs = expiration_secs;
655   call.info = info;
656   ::encode(call, in);
657   op.exec(RGW_CLASS, RGW_GC_SET_ENTRY, in);
658 }
659
660 void cls_rgw_gc_defer_entry(ObjectWriteOperation& op, uint32_t expiration_secs, const string& tag)
661 {
662   bufferlist in;
663   cls_rgw_gc_defer_entry_op call;
664   call.expiration_secs = expiration_secs;
665   call.tag = tag;
666   ::encode(call, in);
667   op.exec(RGW_CLASS, RGW_GC_DEFER_ENTRY, in);
668 }
669
670 int cls_rgw_gc_list(IoCtx& io_ctx, string& oid, string& marker, uint32_t max, bool expired_only,
671                     list<cls_rgw_gc_obj_info>& entries, bool *truncated, string& next_marker)
672 {
673   bufferlist in, out;
674   cls_rgw_gc_list_op call;
675   call.marker = marker;
676   call.max = max;
677   call.expired_only = expired_only;
678   ::encode(call, in);
679   int r = io_ctx.exec(oid, RGW_CLASS, RGW_GC_LIST, in, out);
680   if (r < 0)
681     return r;
682
683   cls_rgw_gc_list_ret ret;
684   try {
685     bufferlist::iterator iter = out.begin();
686     ::decode(ret, iter);
687   } catch (buffer::error& err) {
688     return -EIO;
689   }
690
691   entries.swap(ret.entries);
692
693   if (truncated)
694     *truncated = ret.truncated;
695   next_marker = std::move(ret.next_marker);
696   return r;
697 }
698
699 void cls_rgw_gc_remove(librados::ObjectWriteOperation& op, const list<string>& tags)
700 {
701   bufferlist in;
702   cls_rgw_gc_remove_op call;
703   call.tags = tags;
704   ::encode(call, in);
705   op.exec(RGW_CLASS, RGW_GC_REMOVE, in);
706 }
707
708 int cls_rgw_lc_get_head(IoCtx& io_ctx, string& oid, cls_rgw_lc_obj_head& head)
709 {
710   bufferlist in, out;
711   int r = io_ctx.exec(oid, RGW_CLASS, RGW_LC_GET_HEAD, in, out);
712   if (r < 0)
713     return r;
714
715   cls_rgw_lc_get_head_ret ret;
716   try {
717     bufferlist::iterator iter = out.begin();
718     ::decode(ret, iter);
719   } catch (buffer::error& err) {
720     return -EIO;
721   }
722   head = ret.head;
723
724  return r;
725 }
726
727 int cls_rgw_lc_put_head(IoCtx& io_ctx, string& oid, cls_rgw_lc_obj_head& head)
728 {
729   bufferlist in, out;
730   cls_rgw_lc_put_head_op call;
731   call.head = head;
732   ::encode(call, in);
733   int r = io_ctx.exec(oid, RGW_CLASS, RGW_LC_PUT_HEAD, in, out);
734   return r;
735 }
736
737 int cls_rgw_lc_get_next_entry(IoCtx& io_ctx, string& oid, string& marker, pair<string, int>& entry)
738 {
739   bufferlist in, out;
740   cls_rgw_lc_get_next_entry_op call;
741   call.marker = marker;
742   ::encode(call, in);
743   int r = io_ctx.exec(oid, RGW_CLASS, RGW_LC_GET_NEXT_ENTRY, in, out);
744   if (r < 0)
745     return r;
746
747   cls_rgw_lc_get_next_entry_ret ret;
748   try {
749     bufferlist::iterator iter = out.begin();
750     ::decode(ret, iter);
751   } catch (buffer::error& err) {
752     return -EIO;
753   }
754   entry = ret.entry;
755
756  return r;
757 }
758
759 int cls_rgw_lc_rm_entry(IoCtx& io_ctx, string& oid, pair<string, int>& entry)
760 {
761   bufferlist in, out;
762   cls_rgw_lc_rm_entry_op call;
763   call.entry = entry;
764   ::encode(call, in);
765   int r = io_ctx.exec(oid, RGW_CLASS, RGW_LC_RM_ENTRY, in, out);
766  return r;
767 }
768
769 int cls_rgw_lc_set_entry(IoCtx& io_ctx, string& oid, pair<string, int>& entry)
770 {
771   bufferlist in, out;
772   cls_rgw_lc_set_entry_op call;
773   call.entry = entry;
774   ::encode(call, in);
775   int r = io_ctx.exec(oid, RGW_CLASS, RGW_LC_SET_ENTRY, in, out);
776   return r;
777 }
778
779 int cls_rgw_lc_list(IoCtx& io_ctx, string& oid,
780                     const string& marker,
781                     uint32_t max_entries,
782                     map<string, int>& entries)
783 {
784   bufferlist in, out;
785   cls_rgw_lc_list_entries_op op;
786
787   entries.clear();
788
789   op.marker = marker;
790   op.max_entries = max_entries;
791
792   ::encode(op, in);
793
794   int r = io_ctx.exec(oid, RGW_CLASS, RGW_LC_LIST_ENTRIES, in, out);
795   if (r < 0)
796     return r;
797
798   cls_rgw_lc_list_entries_ret ret;
799   try {
800     bufferlist::iterator iter = out.begin();
801     ::decode(ret, iter);
802   } catch (buffer::error& err) {
803     return -EIO;
804   }
805   entries.insert(ret.entries.begin(),ret.entries.end());
806
807  return r;
808 }
809
810 void cls_rgw_reshard_add(librados::ObjectWriteOperation& op, const cls_rgw_reshard_entry& entry)
811 {
812   bufferlist in;
813   struct cls_rgw_reshard_add_op call;
814   call.entry = entry;
815   ::encode(call, in);
816   op.exec("rgw", "reshard_add", in);
817 }
818
819 int cls_rgw_reshard_list(librados::IoCtx& io_ctx, const string& oid, string& marker, uint32_t max,
820                          list<cls_rgw_reshard_entry>& entries, bool* is_truncated)
821 {
822   bufferlist in, out;
823   struct cls_rgw_reshard_list_op call;
824   call.marker = marker;
825   call.max = max;
826   ::encode(call, in);
827   int r = io_ctx.exec(oid, "rgw", "reshard_list", in, out);
828   if (r < 0)
829     return r;
830
831   struct cls_rgw_reshard_list_ret op_ret;
832   bufferlist::iterator iter = out.begin();
833   try {
834     ::decode(op_ret, iter);
835   } catch (buffer::error& err) {
836     return -EIO;
837   }
838
839   entries.swap(op_ret.entries);
840   *is_truncated = op_ret.is_truncated;
841
842   return 0;
843 }
844
845 int cls_rgw_reshard_get(librados::IoCtx& io_ctx, const string& oid, cls_rgw_reshard_entry& entry)
846 {
847   bufferlist in, out;
848   struct cls_rgw_reshard_get_op call;
849   call.entry = entry;
850   ::encode(call, in);
851   int r = io_ctx.exec(oid, "rgw", "reshard_get", in, out);
852   if (r < 0)
853     return r;
854
855   struct cls_rgw_reshard_get_ret op_ret;
856   bufferlist::iterator iter = out.begin();
857   try {
858     ::decode(op_ret, iter);
859   } catch (buffer::error& err) {
860     return -EIO;
861   }
862
863   entry = op_ret.entry;
864
865   return 0;
866 }
867
868 void cls_rgw_reshard_remove(librados::ObjectWriteOperation& op, const cls_rgw_reshard_entry& entry)
869 {
870   bufferlist in;
871   struct cls_rgw_reshard_remove_op call;
872   call.tenant = entry.tenant;
873   call.bucket_name = entry.bucket_name;
874   call.bucket_id = entry.bucket_id;
875   ::encode(call, in);
876   op.exec("rgw", "reshard_remove", in);
877 }
878
879 int cls_rgw_set_bucket_resharding(librados::IoCtx& io_ctx, const string& oid,
880                                   const cls_rgw_bucket_instance_entry& entry)
881 {
882   bufferlist in, out;
883   struct cls_rgw_set_bucket_resharding_op call;
884   call.entry = entry;
885   ::encode(call, in);
886   return io_ctx.exec(oid, "rgw", "set_bucket_resharding", in, out);
887 }
888
889 int cls_rgw_clear_bucket_resharding(librados::IoCtx& io_ctx, const string& oid)
890 {
891   bufferlist in, out;
892   struct cls_rgw_clear_bucket_resharding_op call;
893   ::encode(call, in);
894   return io_ctx.exec(oid, "rgw", "clear_bucket_resharding", in, out);
895 }
896
897 int cls_rgw_get_bucket_resharding(librados::IoCtx& io_ctx, const string& oid,
898                                   cls_rgw_bucket_instance_entry *entry)
899 {
900   bufferlist in, out;
901   struct cls_rgw_get_bucket_resharding_op call;
902   ::encode(call, in);
903   int r= io_ctx.exec(oid, "rgw", "get_bucket_resharding", in, out);
904   if (r < 0)
905     return r;
906
907   struct cls_rgw_get_bucket_resharding_ret op_ret;
908   bufferlist::iterator iter = out.begin();
909   try {
910     ::decode(op_ret, iter);
911   } catch (buffer::error& err) {
912     return -EIO;
913   }
914
915   *entry = op_ret.new_instance;
916
917   return 0;
918 }
919
920 void cls_rgw_guard_bucket_resharding(librados::ObjectOperation& op, int ret_err)
921 {
922   bufferlist in, out;
923   struct cls_rgw_guard_bucket_resharding_op call;
924   call.ret_err = ret_err;
925   ::encode(call, in);
926   op.exec("rgw", "guard_bucket_resharding", in);
927 }
928
929 static bool issue_set_bucket_resharding(librados::IoCtx& io_ctx, const string& oid,
930                                         const cls_rgw_bucket_instance_entry& entry,
931                                         BucketIndexAioManager *manager) {
932   bufferlist in;
933   struct cls_rgw_set_bucket_resharding_op call;
934   call.entry = entry;
935   ::encode(call, in);
936   librados::ObjectWriteOperation op;
937   op.exec("rgw", "set_bucket_resharding", in);
938   return manager->aio_operate(io_ctx, oid, &op);
939 }
940
941 int CLSRGWIssueSetBucketResharding::issue_op(int shard_id, const string& oid)
942 {
943   return issue_set_bucket_resharding(io_ctx, oid, entry, &manager);
944 }
945