Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / rgw / rgw_rados.cc
1
2 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
3 // vim: ts=8 sw=2 smarttab
4
5 #include "include/compat.h"
6 #include <errno.h>
7 #include <stdlib.h>
8 #include <sys/types.h>
9 #include <boost/algorithm/string.hpp>
10
11 #include <boost/format.hpp>
12 #include <boost/optional.hpp>
13 #include <boost/utility/in_place_factory.hpp>
14
15 #include "common/ceph_json.h"
16 #include "common/utf8.h"
17
18 #include "common/errno.h"
19 #include "common/Formatter.h"
20 #include "common/Throttle.h"
21 #include "common/Finisher.h"
22
23 #include "rgw_rados.h"
24 #include "rgw_cache.h"
25 #include "rgw_acl.h"
26 #include "rgw_acl_s3.h" /* for dumping s3policy in debug log */
27 #include "rgw_metadata.h"
28 #include "rgw_bucket.h"
29 #include "rgw_rest_conn.h"
30 #include "rgw_cr_rados.h"
31 #include "rgw_cr_rest.h"
32
33 #include "cls/rgw/cls_rgw_ops.h"
34 #include "cls/rgw/cls_rgw_types.h"
35 #include "cls/rgw/cls_rgw_client.h"
36 #include "cls/rgw/cls_rgw_const.h"
37 #include "cls/refcount/cls_refcount_client.h"
38 #include "cls/version/cls_version_client.h"
39 #include "cls/log/cls_log_client.h"
40 #include "cls/statelog/cls_statelog_client.h"
41 #include "cls/timeindex/cls_timeindex_client.h"
42 #include "cls/lock/cls_lock_client.h"
43 #include "cls/user/cls_user_client.h"
44 #include "osd/osd_types.h"
45
46 #include "rgw_tools.h"
47 #include "rgw_coroutine.h"
48 #include "rgw_compression.h"
49
50 #undef fork // fails to compile RGWPeriod::fork() below
51
52 #include "common/Clock.h"
53
54 #include "include/rados/librados.hpp"
55 using namespace librados;
56
57 #include <string>
58 #include <iostream>
59 #include <vector>
60 #include <atomic>
61 #include <list>
62 #include <map>
63 #include "auth/Crypto.h" // get_random_bytes()
64
65 #include "rgw_log.h"
66
67 #include "rgw_gc.h"
68 #include "rgw_lc.h"
69
70 #include "rgw_object_expirer_core.h"
71 #include "rgw_sync.h"
72 #include "rgw_data_sync.h"
73 #include "rgw_realm_watcher.h"
74 #include "rgw_reshard.h"
75
76 #include "compressor/Compressor.h"
77
78 #define dout_context g_ceph_context
79 #define dout_subsys ceph_subsys_rgw
80
81 using namespace std;
82
83 static string notify_oid_prefix = "notify";
84 static string *notify_oids = NULL;
85 static string shadow_ns = "shadow";
86 static string dir_oid_prefix = ".dir.";
87 static string default_storage_pool_suffix = "rgw.buckets.data";
88 static string default_bucket_index_pool_suffix = "rgw.buckets.index";
89 static string default_storage_extra_pool_suffix = "rgw.buckets.non-ec";
90 static string avail_pools = ".pools.avail";
91
92 static string zone_info_oid_prefix = "zone_info.";
93 static string zone_names_oid_prefix = "zone_names.";
94 static string region_info_oid_prefix = "region_info.";
95 static string zone_group_info_oid_prefix = "zonegroup_info.";
96 static string realm_names_oid_prefix = "realms_names.";
97 static string realm_info_oid_prefix = "realms.";
98 static string default_region_info_oid = "default.region";
99 static string default_zone_group_info_oid = "default.zonegroup";
100 static string period_info_oid_prefix = "periods.";
101 static string period_latest_epoch_info_oid = ".latest_epoch";
102 static string region_map_oid = "region_map";
103 static string zonegroup_map_oid = "zonegroup_map";
104 static string log_lock_name = "rgw_log_lock";
105 static string default_realm_info_oid = "default.realm";
106 const string default_zonegroup_name = "default";
107 const string default_zone_name = "default";
108 static string zonegroup_names_oid_prefix = "zonegroups_names.";
109 static RGWObjCategory main_category = RGW_OBJ_CATEGORY_MAIN;
110 #define RGW_USAGE_OBJ_PREFIX "usage."
111 #define FIRST_EPOCH 1
112 static string RGW_DEFAULT_ZONE_ROOT_POOL = "rgw.root";
113 static string RGW_DEFAULT_ZONEGROUP_ROOT_POOL = "rgw.root";
114 static string RGW_DEFAULT_REALM_ROOT_POOL = "rgw.root";
115 static string RGW_DEFAULT_PERIOD_ROOT_POOL = "rgw.root";
116
117 #define RGW_STATELOG_OBJ_PREFIX "statelog."
118
119 #define dout_subsys ceph_subsys_rgw
120
121
122 static bool rgw_get_obj_data_pool(const RGWZoneGroup& zonegroup, const RGWZoneParams& zone_params,
123                                   const string& placement_id, const rgw_obj& obj, rgw_pool *pool)
124 {
125   if (!zone_params.get_head_data_pool(placement_id, obj, pool)) {
126     RGWZonePlacementInfo placement;
127     if (!zone_params.get_placement(zonegroup.default_placement, &placement)) {
128       return false;
129     }
130
131     if (!obj.in_extra_data) {
132       *pool = placement.data_pool;
133     } else {
134       *pool = placement.get_data_extra_pool();
135     }
136   }
137
138   return true;
139 }
140
141 static bool rgw_obj_to_raw(const RGWZoneGroup& zonegroup, const RGWZoneParams& zone_params,
142                            const string& placement_id, const rgw_obj& obj, rgw_raw_obj *raw_obj)
143 {
144   get_obj_bucket_and_oid_loc(obj, raw_obj->oid, raw_obj->loc);
145
146   return rgw_get_obj_data_pool(zonegroup, zone_params, placement_id, obj, &raw_obj->pool);
147 }
148
149 rgw_raw_obj rgw_obj_select::get_raw_obj(const RGWZoneGroup& zonegroup, const RGWZoneParams& zone_params) const
150 {
151   if (!is_raw) {
152     rgw_raw_obj r;
153     rgw_obj_to_raw(zonegroup, zone_params, placement_rule, obj, &r);
154     return r;
155   }
156   return raw_obj;
157 }
158
159 rgw_raw_obj rgw_obj_select::get_raw_obj(RGWRados *store) const
160 {
161   if (!is_raw) {
162     rgw_raw_obj r;
163     store->obj_to_raw(placement_rule, obj, &r);
164     return r;
165   }
166   return raw_obj;
167 }
168
169 int rgw_init_ioctx(librados::Rados *rados, const rgw_pool& pool, IoCtx& ioctx, bool create)
170 {
171   int r = rados->ioctx_create(pool.name.c_str(), ioctx);
172   if (r == -ENOENT && create) {
173     r = rados->pool_create(pool.name.c_str());
174     if (r < 0 && r != -EEXIST) {
175       return r;
176     }
177
178     r = rados->ioctx_create(pool.name.c_str(), ioctx);
179     if (r < 0) {
180       return r;
181     }
182
183     r = ioctx.application_enable(pg_pool_t::APPLICATION_NAME_RGW, false);
184     if (r < 0 && r != -EOPNOTSUPP) {
185       return r;
186     }
187   } else if (r < 0) {
188     return r;
189   }
190   if (!pool.ns.empty()) {
191     ioctx.set_namespace(pool.ns);
192   }
193   return 0;
194 }
195
196 template<>
197 void RGWObjectCtxImpl<rgw_obj, RGWObjState>::invalidate(rgw_obj& obj) {
198   RWLock::WLocker wl(lock);
199   auto iter = objs_state.find(obj);
200   if (iter == objs_state.end()) {
201     return;
202   }
203   bool is_atomic = iter->second.is_atomic;
204   bool prefetch_data = iter->second.prefetch_data;
205
206   objs_state.erase(iter);
207
208   if (is_atomic || prefetch_data) {
209     auto& s = objs_state[obj];
210     s.is_atomic = is_atomic;
211     s.prefetch_data = prefetch_data;
212   }
213 }
214
215 template<>
216 void RGWObjectCtxImpl<rgw_raw_obj, RGWRawObjState>::invalidate(rgw_raw_obj& obj) {
217   RWLock::WLocker wl(lock);
218   auto iter = objs_state.find(obj);
219   if (iter == objs_state.end()) {
220     return;
221   }
222
223   objs_state.erase(iter);
224 }
225
226 void RGWDefaultZoneGroupInfo::dump(Formatter *f) const {
227   encode_json("default_zonegroup", default_zonegroup, f);
228 }
229
230 void RGWDefaultZoneGroupInfo::decode_json(JSONObj *obj) {
231
232   JSONDecoder::decode_json("default_zonegroup", default_zonegroup, obj);
233   /* backward compatability with region */
234   if (default_zonegroup.empty()) {
235     JSONDecoder::decode_json("default_region", default_zonegroup, obj);
236   }
237 }
238
239 rgw_pool RGWZoneGroup::get_pool(CephContext *cct_)
240 {
241   if (cct_->_conf->rgw_zonegroup_root_pool.empty()) {
242     return rgw_pool(RGW_DEFAULT_ZONEGROUP_ROOT_POOL);
243   }
244
245   return rgw_pool(cct_->_conf->rgw_zonegroup_root_pool);
246 }
247
248 int RGWZoneGroup::create_default(bool old_format)
249 {
250   name = default_zonegroup_name;
251   is_master = true;
252
253   RGWZoneGroupPlacementTarget placement_target;
254   placement_target.name = "default-placement";
255   placement_targets[placement_target.name] = placement_target;
256   default_placement = "default-placement";
257
258   RGWZoneParams zone_params(default_zone_name);
259
260   int r = zone_params.init(cct, store, false);
261   if (r < 0) {
262     ldout(cct, 0) << "create_default: error initializing zone params: " << cpp_strerror(-r) << dendl;
263     return r;
264   }
265
266   r = zone_params.create_default();
267   if (r < 0 && r != -EEXIST) {
268     ldout(cct, 0) << "create_default: error in create_default  zone params: " << cpp_strerror(-r) << dendl;
269     return r;
270   } else if (r == -EEXIST) {
271     ldout(cct, 10) << "zone_params::create_default() returned -EEXIST, we raced with another default zone_params creation" << dendl;
272     zone_params.clear_id();
273     r = zone_params.init(cct, store);
274     if (r < 0) {
275       ldout(cct, 0) << "create_default: error in init existing zone params: " << cpp_strerror(-r) << dendl;
276       return r;
277     }
278     ldout(cct, 20) << "zone_params::create_default() " << zone_params.get_name() << " id " << zone_params.get_id()
279                    << dendl;
280   }
281   
282   RGWZone& default_zone = zones[zone_params.get_id()];
283   default_zone.name = zone_params.get_name();
284   default_zone.id = zone_params.get_id();
285   master_zone = default_zone.id;
286   
287   r = create();
288   if (r < 0 && r != -EEXIST) {
289     ldout(cct, 0) << "error storing zone group info: " << cpp_strerror(-r) << dendl;
290     return r;
291   }
292
293   if (r == -EEXIST) {
294     ldout(cct, 10) << "create_default() returned -EEXIST, we raced with another zonegroup creation" << dendl;
295     id.clear();
296     r = init(cct, store);
297     if (r < 0) {
298       return r;
299     }
300   }
301
302   if (old_format) {
303     name = id;
304   }
305
306   post_process_params();
307
308   return 0;
309 }
310
311 const string RGWZoneGroup::get_default_oid(bool old_region_format)
312 {
313   if (old_region_format) {
314     if (cct->_conf->rgw_default_region_info_oid.empty()) {
315       return default_region_info_oid;
316     }
317     return cct->_conf->rgw_default_region_info_oid;
318   }
319
320   string default_oid = cct->_conf->rgw_default_zonegroup_info_oid;
321
322   if (cct->_conf->rgw_default_zonegroup_info_oid.empty()) {
323     default_oid = default_zone_group_info_oid;
324   }
325
326   default_oid += "." + realm_id;
327
328   return default_oid;
329 }
330
331 const string& RGWZoneGroup::get_info_oid_prefix(bool old_region_format)
332 {
333   if (old_region_format) {
334     return region_info_oid_prefix;
335   }
336   return zone_group_info_oid_prefix;
337 }
338
339 const string& RGWZoneGroup::get_names_oid_prefix()
340 {
341   return zonegroup_names_oid_prefix;
342 }
343
344 const string& RGWZoneGroup::get_predefined_name(CephContext *cct) {
345   return cct->_conf->rgw_zonegroup;
346 }
347
348 int RGWZoneGroup::equals(const string& other_zonegroup) const
349 {
350   if (is_master && other_zonegroup.empty())
351     return true;
352
353   return (id  == other_zonegroup);
354 }
355
356 int RGWZoneGroup::add_zone(const RGWZoneParams& zone_params, bool *is_master, bool *read_only,
357                            const list<string>& endpoints, const string *ptier_type,
358                            bool *psync_from_all, list<string>& sync_from, list<string>& sync_from_rm)
359 {
360   auto& zone_id = zone_params.get_id();
361   auto& zone_name = zone_params.get_name();
362
363   // check for duplicate zone name on insert
364   if (!zones.count(zone_id)) {
365     for (const auto& zone : zones) {
366       if (zone.second.name == zone_name) {
367         ldout(cct, 0) << "ERROR: found existing zone name " << zone_name
368             << " (" << zone.first << ") in zonegroup " << get_name() << dendl;
369         return -EEXIST;
370       }
371     }
372   }
373
374   if (is_master) {
375     if (*is_master) {
376       if (!master_zone.empty() && master_zone != zone_params.get_id()) {
377         ldout(cct, 0) << "NOTICE: overriding master zone: " << master_zone << dendl;
378       }
379       master_zone = zone_params.get_id();
380     } else if (master_zone == zone_params.get_id()) {
381       master_zone.clear();
382     }
383   }
384
385   RGWZone& zone = zones[zone_params.get_id()];
386   zone.name = zone_params.get_name();
387   zone.id = zone_params.get_id();
388   if (!endpoints.empty()) {
389     zone.endpoints = endpoints;
390   }
391   if (read_only) {
392     zone.read_only = *read_only;
393   }
394   if (ptier_type) {
395     zone.tier_type = *ptier_type;
396   }
397
398   if (psync_from_all) {
399     zone.sync_from_all = *psync_from_all;
400   }
401
402   for (auto add : sync_from) {
403     zone.sync_from.insert(add);
404   }
405
406   for (auto rm : sync_from_rm) {
407     zone.sync_from.erase(rm);
408   }
409
410   post_process_params();
411
412   return update();
413 }
414
415
416 int RGWZoneGroup::rename_zone(const RGWZoneParams& zone_params)
417
418   RGWZone& zone = zones[zone_params.get_id()];
419   zone.name = zone_params.get_name();
420   
421   return update();
422 }
423
424 void RGWZoneGroup::post_process_params()
425 {
426   bool log_data = zones.size() > 1;
427
428   if (master_zone.empty()) {
429     map<string, RGWZone>::iterator iter = zones.begin();
430     if (iter != zones.end()) {
431       master_zone = iter->first;
432     }
433   }
434   
435   for (map<string, RGWZone>::iterator iter = zones.begin(); iter != zones.end(); ++iter) {
436     RGWZone& zone = iter->second;
437     zone.log_data = log_data;
438
439     RGWZoneParams zone_params(zone.id, zone.name);
440     int ret = zone_params.init(cct, store);
441     if (ret < 0) {
442       ldout(cct, 0) << "WARNING: could not read zone params for zone id=" << zone.id << " name=" << zone.name << dendl;
443       continue;
444     }
445
446     for (map<string, RGWZonePlacementInfo>::iterator iter = zone_params.placement_pools.begin(); 
447          iter != zone_params.placement_pools.end(); ++iter) {
448       const string& placement_name = iter->first;
449       if (placement_targets.find(placement_name) == placement_targets.end()) {
450         RGWZoneGroupPlacementTarget placement_target;
451         placement_target.name = placement_name;
452         placement_targets[placement_name] = placement_target;
453       }
454     }
455   }
456
457   if (default_placement.empty() && !placement_targets.empty()) {
458     default_placement = placement_targets.begin()->first;
459   }
460 }
461
462 int RGWZoneGroup::remove_zone(const std::string& zone_id)
463 {
464   map<string, RGWZone>::iterator iter = zones.find(zone_id);
465   if (iter == zones.end()) {
466     ldout(cct, 0) << "zone id " << zone_id << " is not a part of zonegroup "
467         << name << dendl;
468     return -ENOENT;
469   }
470
471   zones.erase(iter);
472
473   post_process_params();
474
475   return update();
476 }
477
478 int RGWZoneGroup::read_default_id(string& default_id, bool old_format)
479 {
480   if (realm_id.empty()) {
481     /* try using default realm */
482     RGWRealm realm;
483     int ret = realm.init(cct, store);
484     if (ret < 0) {
485       ldout(cct, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
486       return -ENOENT;
487     }
488     realm_id = realm.get_id();
489   }
490
491   return RGWSystemMetaObj::read_default_id(default_id, old_format);
492 }
493
494 int RGWZoneGroup::set_as_default(bool exclusive)
495 {
496   if (realm_id.empty()) {
497     /* try using default realm */
498     RGWRealm realm;
499     int ret = realm.init(cct, store);
500     if (ret < 0) {
501       ldout(cct, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
502       return -EINVAL;
503     }
504     realm_id = realm.get_id();
505   }
506
507   return RGWSystemMetaObj::set_as_default(exclusive);
508 }
509
510 int RGWSystemMetaObj::init(CephContext *_cct, RGWRados *_store, bool setup_obj, bool old_format)
511 {
512   cct = _cct;
513   store = _store;
514
515   if (!setup_obj)
516     return 0;
517
518   if (old_format && id.empty()) {
519     id = name;
520   }
521
522   if (id.empty()) {
523     int r;
524     if (name.empty()) {
525       name = get_predefined_name(cct);
526     }
527     if (name.empty()) {
528       r = use_default(old_format);
529       if (r < 0) {
530         return r;
531       }
532     } else if (!old_format) {
533       r = read_id(name, id);
534       if (r < 0) {
535         if (r != -ENOENT) {
536           ldout(cct, 0) << "error in read_id for object name: " << name << " : " << cpp_strerror(-r) << dendl;
537         }
538         return r;
539       }
540     }
541   }
542
543   return read_info(id, old_format);
544 }
545
546 int RGWSystemMetaObj::read_default(RGWDefaultSystemMetaObjInfo& default_info, const string& oid)
547 {
548   auto pool = get_pool(cct);
549   bufferlist bl;
550   RGWObjectCtx obj_ctx(store);
551   int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
552   if (ret < 0)
553     return ret;
554
555   try {
556     bufferlist::iterator iter = bl.begin();
557     ::decode(default_info, iter);
558   } catch (buffer::error& err) {
559     ldout(cct, 0) << "error decoding data from " << pool << ":" << oid << dendl;
560     return -EIO;
561   }
562
563   return 0;
564 }
565
566 int RGWSystemMetaObj::read_default_id(string& default_id, bool old_format)
567 {
568   RGWDefaultSystemMetaObjInfo default_info;
569
570   int ret = read_default(default_info, get_default_oid(old_format));
571   if (ret < 0) {
572     return ret;
573   }
574
575   default_id = default_info.default_id;
576
577   return 0;
578 }
579
580 int RGWSystemMetaObj::use_default(bool old_format)
581 {
582   return read_default_id(id, old_format);
583 }
584
585 int RGWSystemMetaObj::set_as_default(bool exclusive)
586 {
587   string oid  = get_default_oid();
588
589   rgw_pool pool(get_pool(cct));
590   bufferlist bl;
591
592   RGWDefaultSystemMetaObjInfo default_info;
593   default_info.default_id = id;
594
595   ::encode(default_info, bl);
596
597   int ret = rgw_put_system_obj(store, pool, oid, bl.c_str(), bl.length(),
598                                exclusive, NULL, real_time(), NULL);
599   if (ret < 0)
600     return ret;
601
602   return 0;
603 }
604
605 int RGWSystemMetaObj::read_id(const string& obj_name, string& object_id)
606 {
607   rgw_pool pool(get_pool(cct));
608   bufferlist bl;
609
610   string oid = get_names_oid_prefix() + obj_name;
611
612   RGWObjectCtx obj_ctx(store);
613   int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
614   if (ret < 0) {
615     return ret;
616   }
617
618   RGWNameToId nameToId;
619   try {
620     bufferlist::iterator iter = bl.begin();
621     ::decode(nameToId, iter);
622   } catch (buffer::error& err) {
623     ldout(cct, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
624     return -EIO;
625   }
626   object_id = nameToId.obj_id;
627   return 0;
628 }
629
630 int RGWSystemMetaObj::delete_obj(bool old_format)
631 {
632   rgw_pool pool(get_pool(cct));
633
634   /* check to see if obj is the default */
635   RGWDefaultSystemMetaObjInfo default_info;
636   int ret = read_default(default_info, get_default_oid(old_format));
637   if (ret < 0 && ret != -ENOENT)
638     return ret;
639   if (default_info.default_id == id || (old_format && default_info.default_id == name)) {
640     string oid = get_default_oid(old_format);
641     rgw_raw_obj default_named_obj(pool, oid);
642     ret = store->delete_system_obj(default_named_obj);
643     if (ret < 0) {
644       ldout(cct, 0) << "Error delete default obj name  " << name << ": " << cpp_strerror(-ret) << dendl;
645       return ret;
646     }
647   }
648   if (!old_format) {
649     string oid  = get_names_oid_prefix() + name;
650     rgw_raw_obj object_name(pool, oid);
651     ret = store->delete_system_obj(object_name);
652     if (ret < 0) {
653       ldout(cct, 0) << "Error delete obj name  " << name << ": " << cpp_strerror(-ret) << dendl;
654       return ret;
655     }
656   }
657
658   string oid = get_info_oid_prefix(old_format);
659   if (old_format) {
660     oid += name;
661   } else {
662     oid += id;
663   }
664
665   rgw_raw_obj object_id(pool, oid);
666   ret = store->delete_system_obj(object_id);
667   if (ret < 0) {
668     ldout(cct, 0) << "Error delete object id " << id << ": " << cpp_strerror(-ret) << dendl;
669   }
670
671   return ret;
672 }
673
674 int RGWSystemMetaObj::store_name(bool exclusive)
675 {
676   rgw_pool pool(get_pool(cct));
677   string oid = get_names_oid_prefix() + name;
678
679   RGWNameToId nameToId;
680   nameToId.obj_id = id;
681
682   bufferlist bl;
683   ::encode(nameToId, bl);
684   return  rgw_put_system_obj(store, pool, oid, bl.c_str(), bl.length(), exclusive, NULL, real_time(), NULL);
685 }
686
687 int RGWSystemMetaObj::rename(const string& new_name)
688 {
689   string new_id;
690   int ret = read_id(new_name, new_id);
691   if (!ret) {
692     return -EEXIST;
693   }
694   if (ret < 0 && ret != -ENOENT) {
695     ldout(cct, 0) << "Error read_id " << new_name << ": " << cpp_strerror(-ret) << dendl;
696     return ret;
697   }
698   string old_name = name;
699   name = new_name;
700   ret = update();
701   if (ret < 0) {
702     ldout(cct, 0) << "Error storing new obj info " << new_name << ": " << cpp_strerror(-ret) << dendl;
703     return ret;
704   }
705   ret = store_name(true);
706   if (ret < 0) {
707     ldout(cct, 0) << "Error storing new name " << new_name << ": " << cpp_strerror(-ret) << dendl;
708     return ret;
709   }
710   /* delete old name */
711   rgw_pool pool(get_pool(cct));
712   string oid = get_names_oid_prefix() + old_name;
713   rgw_raw_obj old_name_obj(pool, oid);
714   ret = store->delete_system_obj(old_name_obj);
715   if (ret < 0) {
716     ldout(cct, 0) << "Error delete old obj name  " << old_name << ": " << cpp_strerror(-ret) << dendl;
717     return ret;
718   }
719
720   return ret;
721 }
722
723 int RGWSystemMetaObj::read_info(const string& obj_id, bool old_format)
724 {
725   rgw_pool pool(get_pool(cct));
726
727   bufferlist bl;
728
729   string oid = get_info_oid_prefix(old_format) + obj_id;
730
731   RGWObjectCtx obj_ctx(store);
732   int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
733   if (ret < 0) {
734     ldout(cct, 0) << "failed reading obj info from " << pool << ":" << oid << ": " << cpp_strerror(-ret) << dendl;
735     return ret;
736   }
737
738   try {
739     bufferlist::iterator iter = bl.begin();
740     ::decode(*this, iter);
741   } catch (buffer::error& err) {
742     ldout(cct, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
743     return -EIO;
744   }
745
746   return 0;
747 }
748
749 int RGWSystemMetaObj::read()
750 {
751   int ret = read_id(name, id);
752   if (ret < 0) {
753     return ret;
754   }
755
756   return read_info(id);
757 }
758
759 int RGWSystemMetaObj::create(bool exclusive)
760 {
761   int ret;
762   
763   /* check to see the name is not used */
764   ret = read_id(name, id);
765   if (exclusive && ret == 0) {
766     ldout(cct, 10) << "ERROR: name " << name << " already in use for obj id " << id << dendl;
767     return -EEXIST;
768   } else if ( ret < 0 && ret != -ENOENT) {
769     ldout(cct, 0) << "failed reading obj id  " << id << ": " << cpp_strerror(-ret) << dendl;
770     return ret;
771   }
772
773   if (id.empty()) {
774     /* create unique id */
775     uuid_d new_uuid;
776     char uuid_str[37];
777     new_uuid.generate_random();
778     new_uuid.print(uuid_str);
779     id = uuid_str;
780   }
781
782   ret = store_info(exclusive);
783   if (ret < 0) {
784     ldout(cct, 0) << "ERROR:  storing info for " << id << ": " << cpp_strerror(-ret) << dendl;
785     return ret;
786   }
787
788   return store_name(exclusive);
789 }
790
791 int RGWSystemMetaObj::store_info(bool exclusive)
792 {
793   rgw_pool pool(get_pool(cct));
794
795   string oid = get_info_oid_prefix() + id;
796
797   bufferlist bl;
798   ::encode(*this, bl);
799   return  rgw_put_system_obj(store, pool, oid, bl.c_str(), bl.length(), exclusive, NULL, real_time(), NULL);
800 }
801
802 int RGWSystemMetaObj::write(bool exclusive)
803 {
804   int ret = store_info(exclusive);
805   if (ret < 0) {
806     ldout(cct, 20) << __func__ << "(): store_info() returned ret=" << ret << dendl;
807     return ret;
808   }
809   ret = store_name(exclusive);
810   if (ret < 0) {
811     ldout(cct, 20) << __func__ << "(): store_name() returned ret=" << ret << dendl;
812     return ret;
813   }
814   return 0;
815 }
816
817
818 const string& RGWRealm::get_predefined_name(CephContext *cct) {
819   return cct->_conf->rgw_realm;
820 }
821
822 int RGWRealm::create(bool exclusive)
823 {
824   int ret = RGWSystemMetaObj::create(exclusive);
825   if (ret < 0) {
826     ldout(cct, 0) << "ERROR creating new realm object " << name << ": " << cpp_strerror(-ret) << dendl;
827     return ret;
828   }
829   // create the control object for watch/notify
830   ret = create_control(exclusive);
831   if (ret < 0) {
832     ldout(cct, 0) << "ERROR creating control for new realm " << name << ": " << cpp_strerror(-ret) << dendl;
833     return ret;
834   }
835   RGWPeriod period;
836   if (current_period.empty()) {
837     /* create new period for the realm */
838     ret = period.init(cct, store, id, name, false);
839     if (ret < 0 ) {
840       return ret;
841     }
842     ret = period.create(true);
843     if (ret < 0) {
844       ldout(cct, 0) << "ERROR: creating new period for realm " << name << ": " << cpp_strerror(-ret) << dendl;
845       return ret;
846     }
847   } else {
848     period = RGWPeriod(current_period, 0);
849     int ret = period.init(cct, store, id, name);
850     if (ret < 0) {
851       ldout(cct, 0) << "ERROR: failed to init period " << current_period << dendl;
852       return ret;
853     }
854   }
855   ret = set_current_period(period);
856   if (ret < 0) {
857     ldout(cct, 0) << "ERROR: failed set current period " << current_period << dendl;
858     return ret;
859   }
860   // try to set as default. may race with another create, so pass exclusive=true
861   // so we don't override an existing default
862   ret = set_as_default(true);
863   if (ret < 0 && ret != -EEXIST) {
864     ldout(cct, 0) << "WARNING: failed to set realm as default realm, ret=" << ret << dendl;
865   }
866
867   return 0;
868 }
869
870 int RGWRealm::delete_obj()
871 {
872   int ret = RGWSystemMetaObj::delete_obj();
873   if (ret < 0) {
874     return ret;
875   }
876   return delete_control();
877 }
878
879 int RGWRealm::create_control(bool exclusive)
880 {
881   auto pool = rgw_pool{get_pool(cct)};
882   auto oid = get_control_oid();
883   return rgw_put_system_obj(store, pool, oid, nullptr, 0, exclusive,
884                             nullptr, real_time(), nullptr);
885 }
886
887 int RGWRealm::delete_control()
888 {
889   auto pool = rgw_pool{get_pool(cct)};
890   auto obj = rgw_raw_obj{pool, get_control_oid()};
891   return store->delete_system_obj(obj);
892 }
893
894 rgw_pool RGWRealm::get_pool(CephContext *cct)
895 {
896   if (cct->_conf->rgw_realm_root_pool.empty()) {
897     return rgw_pool(RGW_DEFAULT_REALM_ROOT_POOL);
898   }
899   return rgw_pool(cct->_conf->rgw_realm_root_pool);
900 }
901
902 const string RGWRealm::get_default_oid(bool old_format)
903 {
904   if (cct->_conf->rgw_default_realm_info_oid.empty()) {
905     return default_realm_info_oid;
906   }
907   return cct->_conf->rgw_default_realm_info_oid;
908 }
909
910 const string& RGWRealm::get_names_oid_prefix()
911 {
912   return realm_names_oid_prefix;
913 }
914
915 const string& RGWRealm::get_info_oid_prefix(bool old_format)
916 {
917   return realm_info_oid_prefix;
918 }
919
920 int RGWRealm::set_current_period(RGWPeriod& period)
921 {
922   // update realm epoch to match the period's
923   if (epoch > period.get_realm_epoch()) {
924     ldout(cct, 0) << "ERROR: set_current_period with old realm epoch "
925         << period.get_realm_epoch() << ", current epoch=" << epoch << dendl;
926     return -EINVAL;
927   }
928   if (epoch == period.get_realm_epoch() && current_period != period.get_id()) {
929     ldout(cct, 0) << "ERROR: set_current_period with same realm epoch "
930         << period.get_realm_epoch() << ", but different period id "
931         << period.get_id() << " != " << current_period << dendl;
932     return -EINVAL;
933   }
934
935   epoch = period.get_realm_epoch();
936   current_period = period.get_id();
937
938   int ret = update();
939   if (ret < 0) {
940     ldout(cct, 0) << "ERROR: period update: " << cpp_strerror(-ret) << dendl;
941     return ret;
942   }
943
944   ret = period.reflect();
945   if (ret < 0) {
946     ldout(cct, 0) << "ERROR: period.reflect(): " << cpp_strerror(-ret) << dendl;
947     return ret;
948   }
949
950   return 0;
951 }
952
953 string RGWRealm::get_control_oid()
954 {
955   return get_info_oid_prefix() + id + ".control";
956 }
957
958 int RGWRealm::notify_zone(bufferlist& bl)
959 {
960   // open a context on the realm's pool
961   rgw_pool pool{get_pool(cct)};
962   librados::IoCtx ctx;
963   int r = rgw_init_ioctx(store->get_rados_handle(), pool, ctx);
964   if (r < 0) {
965     ldout(cct, 0) << "Failed to open pool " << pool << dendl;
966     return r;
967   }
968   // send a notify on the realm object
969   r = ctx.notify2(get_control_oid(), bl, 0, nullptr);
970   if (r < 0) {
971     ldout(cct, 0) << "Realm notify failed with " << r << dendl;
972     return r;
973   }
974   return 0;
975 }
976
977 int RGWRealm::notify_new_period(const RGWPeriod& period)
978 {
979   bufferlist bl;
980   // push the period to dependent zonegroups/zones
981   ::encode(RGWRealmNotify::ZonesNeedPeriod, bl);
982   ::encode(period, bl);
983   // reload the gateway with the new period
984   ::encode(RGWRealmNotify::Reload, bl);
985
986   return notify_zone(bl);
987 }
988
989 std::string RGWPeriodConfig::get_oid(const std::string& realm_id)
990 {
991   if (realm_id.empty()) {
992     return "period_config.default";
993   }
994   return "period_config." + realm_id;
995 }
996
997 rgw_pool RGWPeriodConfig::get_pool(CephContext *cct)
998 {
999   const auto& pool_name = cct->_conf->rgw_period_root_pool;
1000   if (pool_name.empty()) {
1001     return {RGW_DEFAULT_PERIOD_ROOT_POOL};
1002   }
1003   return {pool_name};
1004 }
1005
1006 int RGWPeriodConfig::read(RGWRados *store, const std::string& realm_id)
1007 {
1008   RGWObjectCtx obj_ctx(store);
1009   const auto& pool = get_pool(store->ctx());
1010   const auto& oid = get_oid(realm_id);
1011   bufferlist bl;
1012
1013   int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, nullptr, nullptr);
1014   if (ret < 0) {
1015     return ret;
1016   }
1017   try {
1018     bufferlist::iterator iter = bl.begin();
1019     ::decode(*this, iter);
1020   } catch (buffer::error& err) {
1021     return -EIO;
1022   }
1023   return 0;
1024 }
1025
1026 int RGWPeriodConfig::write(RGWRados *store, const std::string& realm_id)
1027 {
1028   const auto& pool = get_pool(store->ctx());
1029   const auto& oid = get_oid(realm_id);
1030   bufferlist bl;
1031   ::encode(*this, bl);
1032   return rgw_put_system_obj(store, pool, oid, bl.c_str(), bl.length(),
1033                             false, nullptr, real_time(), nullptr);
1034 }
1035
1036 int RGWPeriod::init(CephContext *_cct, RGWRados *_store, const string& period_realm_id,
1037                     const string& period_realm_name, bool setup_obj)
1038 {
1039   cct = _cct;
1040   store = _store;
1041   realm_id = period_realm_id;
1042   realm_name = period_realm_name;
1043
1044   if (!setup_obj)
1045     return 0;
1046
1047   return init(_cct, _store, setup_obj);
1048 }
1049
1050
1051 int RGWPeriod::init(CephContext *_cct, RGWRados *_store, bool setup_obj)
1052 {
1053   cct = _cct;
1054   store = _store;
1055
1056   if (!setup_obj)
1057     return 0;
1058
1059   if (id.empty()) {
1060     RGWRealm realm(realm_id, realm_name);
1061     int ret = realm.init(cct, store);
1062     if (ret < 0) {
1063       ldout(cct, 0) << "RGWPeriod::init failed to init realm " << realm_name  << " id " << realm_id << " : " <<
1064         cpp_strerror(-ret) << dendl;
1065       return ret;
1066     }
1067     id = realm.get_current_period();
1068     realm_id = realm.get_id();
1069   }
1070
1071   if (!epoch) {
1072     int ret = use_latest_epoch();
1073     if (ret < 0) {
1074       ldout(cct, 0) << "failed to use_latest_epoch period id " << id << " realm " << realm_name  << " id " << realm_id
1075            << " : " << cpp_strerror(-ret) << dendl;
1076       return ret;
1077     }
1078   }
1079
1080   return read_info();
1081 }
1082
1083
1084 int RGWPeriod::get_zonegroup(RGWZoneGroup& zonegroup, const string& zonegroup_id) {
1085   map<string, RGWZoneGroup>::const_iterator iter;
1086   if (!zonegroup_id.empty()) {
1087     iter = period_map.zonegroups.find(zonegroup_id);
1088   } else {
1089     iter = period_map.zonegroups.find("default");
1090   }
1091   if (iter != period_map.zonegroups.end()) {
1092     zonegroup = iter->second;
1093     return 0;
1094   }
1095
1096   return -ENOENT;
1097 }
1098
1099 const string& RGWPeriod::get_latest_epoch_oid()
1100 {
1101   if (cct->_conf->rgw_period_latest_epoch_info_oid.empty()) {
1102     return period_latest_epoch_info_oid;
1103   }
1104   return cct->_conf->rgw_period_latest_epoch_info_oid;
1105 }
1106
1107 const string& RGWPeriod::get_info_oid_prefix()
1108 {
1109   return period_info_oid_prefix;
1110 }
1111
1112 const string RGWPeriod::get_period_oid_prefix()
1113 {
1114   return get_info_oid_prefix() + id;
1115 }
1116
1117 const string RGWPeriod::get_period_oid()
1118 {
1119   std::ostringstream oss;
1120   oss << get_period_oid_prefix();
1121   // skip the epoch for the staging period
1122   if (id != get_staging_id(realm_id))
1123     oss << "." << epoch;
1124   return oss.str();
1125 }
1126
1127 int RGWPeriod::read_latest_epoch(RGWPeriodLatestEpochInfo& info,
1128                                  RGWObjVersionTracker *objv)
1129 {
1130   string oid = get_period_oid_prefix() + get_latest_epoch_oid();
1131
1132   rgw_pool pool(get_pool(cct));
1133   bufferlist bl;
1134   RGWObjectCtx obj_ctx(store);
1135   int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, objv, nullptr);
1136   if (ret < 0) {
1137     ldout(cct, 1) << "error read_lastest_epoch " << pool << ":" << oid << dendl;
1138     return ret;
1139   }
1140   try {
1141     bufferlist::iterator iter = bl.begin();
1142     ::decode(info, iter);
1143   } catch (buffer::error& err) {
1144     ldout(cct, 0) << "error decoding data from " << pool << ":" << oid << dendl;
1145     return -EIO;
1146   }
1147
1148   return 0;
1149 }
1150
1151 int RGWPeriod::get_latest_epoch(epoch_t& latest_epoch)
1152 {
1153   RGWPeriodLatestEpochInfo info;
1154
1155   int ret = read_latest_epoch(info);
1156   if (ret < 0) {
1157     return ret;
1158   }
1159
1160   latest_epoch = info.epoch;
1161
1162   return 0;
1163 }
1164
1165 int RGWPeriod::use_latest_epoch()
1166 {
1167   RGWPeriodLatestEpochInfo info;
1168   int ret = read_latest_epoch(info);
1169   if (ret < 0) {
1170     return ret;
1171   }
1172
1173   epoch = info.epoch;
1174
1175   return 0;
1176 }
1177
1178 int RGWPeriod::set_latest_epoch(epoch_t epoch, bool exclusive,
1179                                 RGWObjVersionTracker *objv)
1180 {
1181   string oid = get_period_oid_prefix() + get_latest_epoch_oid();
1182
1183   rgw_pool pool(get_pool(cct));
1184   bufferlist bl;
1185
1186   RGWPeriodLatestEpochInfo info;
1187   info.epoch = epoch;
1188
1189   ::encode(info, bl);
1190
1191   return rgw_put_system_obj(store, pool, oid, bl.c_str(), bl.length(),
1192                             exclusive, objv, real_time(), nullptr);
1193 }
1194
1195 int RGWPeriod::update_latest_epoch(epoch_t epoch)
1196 {
1197   static constexpr int MAX_RETRIES = 20;
1198
1199   for (int i = 0; i < MAX_RETRIES; i++) {
1200     RGWPeriodLatestEpochInfo info;
1201     RGWObjVersionTracker objv;
1202     bool exclusive = false;
1203
1204     // read existing epoch
1205     int r = read_latest_epoch(info, &objv);
1206     if (r == -ENOENT) {
1207       // use an exclusive create to set the epoch atomically
1208       exclusive = true;
1209       ldout(cct, 20) << "creating initial latest_epoch=" << epoch
1210           << " for period=" << id << dendl;
1211     } else if (r < 0) {
1212       ldout(cct, 0) << "ERROR: failed to read latest_epoch" << dendl;
1213       return r;
1214     } else if (epoch <= info.epoch) {
1215       r = -EEXIST; // fail with EEXIST if epoch is not newer
1216       ldout(cct, 1) << "found existing latest_epoch " << info.epoch
1217           << " >= given epoch " << epoch << ", returning r=" << r << dendl;
1218       return r;
1219     } else {
1220       ldout(cct, 20) << "updating latest_epoch from " << info.epoch
1221           << " -> " << epoch << " on period=" << id << dendl;
1222     }
1223
1224     r = set_latest_epoch(epoch, exclusive, &objv);
1225     if (r == -EEXIST) {
1226       continue; // exclusive create raced with another update, retry
1227     } else if (r == -ECANCELED) {
1228       continue; // write raced with a conflicting version, retry
1229     }
1230     if (r < 0) {
1231       ldout(cct, 0) << "ERROR: failed to write latest_epoch" << dendl;
1232       return r;
1233     }
1234     return 0; // return success
1235   }
1236
1237   return -ECANCELED; // fail after max retries
1238 }
1239
1240 int RGWPeriod::delete_obj()
1241 {
1242   rgw_pool pool(get_pool(cct));
1243
1244   // delete the object for each period epoch
1245   for (epoch_t e = 1; e <= epoch; e++) {
1246     RGWPeriod p{get_id(), e};
1247     rgw_raw_obj oid{pool, p.get_period_oid()};
1248     int ret = store->delete_system_obj(oid);
1249     if (ret < 0) {
1250       ldout(cct, 0) << "WARNING: failed to delete period object " << oid
1251           << ": " << cpp_strerror(-ret) << dendl;
1252     }
1253   }
1254
1255   // delete the .latest_epoch object
1256   rgw_raw_obj oid{pool, get_period_oid_prefix() + get_latest_epoch_oid()};
1257   int ret = store->delete_system_obj(oid);
1258   if (ret < 0) {
1259     ldout(cct, 0) << "WARNING: failed to delete period object " << oid
1260         << ": " << cpp_strerror(-ret) << dendl;
1261   }
1262   return ret;
1263 }
1264
1265 int RGWPeriod::read_info()
1266 {
1267   rgw_pool pool(get_pool(cct));
1268
1269   bufferlist bl;
1270
1271   RGWObjectCtx obj_ctx(store);
1272   int ret = rgw_get_system_obj(store, obj_ctx, pool, get_period_oid(), bl, NULL, NULL);
1273   if (ret < 0) {
1274     ldout(cct, 0) << "failed reading obj info from " << pool << ":" << get_period_oid() << ": " << cpp_strerror(-ret) << dendl;
1275     return ret;
1276   }
1277
1278   try {
1279     bufferlist::iterator iter = bl.begin();
1280     ::decode(*this, iter);
1281   } catch (buffer::error& err) {
1282     ldout(cct, 0) << "ERROR: failed to decode obj from " << pool << ":" << get_period_oid() << dendl;
1283     return -EIO;
1284   }
1285
1286   return 0;
1287 }
1288
1289 int RGWPeriod::create(bool exclusive)
1290 {
1291   int ret;
1292   
1293   /* create unique id */
1294   uuid_d new_uuid;
1295   char uuid_str[37];
1296   new_uuid.generate_random();
1297   new_uuid.print(uuid_str);
1298   id = uuid_str;
1299
1300   epoch = FIRST_EPOCH;
1301
1302   period_map.id = id;
1303   
1304   ret = store_info(exclusive);
1305   if (ret < 0) {
1306     ldout(cct, 0) << "ERROR:  storing info for " << id << ": " << cpp_strerror(-ret) << dendl;
1307     return ret;
1308   }
1309
1310   ret = set_latest_epoch(epoch);
1311   if (ret < 0) {
1312     ldout(cct, 0) << "ERROR: setting latest epoch " << id << ": " << cpp_strerror(-ret) << dendl;
1313   }
1314
1315   return ret;
1316 }
1317
1318 int RGWPeriod::store_info(bool exclusive)
1319 {
1320   rgw_pool pool(get_pool(cct));
1321
1322   string oid = get_period_oid();
1323   bufferlist bl;
1324   ::encode(*this, bl);
1325
1326   return rgw_put_system_obj(store, pool, oid, bl.c_str(), bl.length(),
1327                             exclusive, NULL, real_time(), NULL);
1328 }
1329
1330 rgw_pool RGWPeriod::get_pool(CephContext *cct)
1331 {
1332   if (cct->_conf->rgw_period_root_pool.empty()) {
1333     return rgw_pool(RGW_DEFAULT_PERIOD_ROOT_POOL);
1334   }
1335   return rgw_pool(cct->_conf->rgw_period_root_pool);
1336 }
1337
1338 int RGWPeriod::add_zonegroup(const RGWZoneGroup& zonegroup)
1339 {
1340   if (zonegroup.realm_id != realm_id) {
1341     return 0;
1342   }
1343   int ret = period_map.update(zonegroup, cct);
1344   if (ret < 0) {
1345     ldout(cct, 0) << "ERROR: updating period map: " << cpp_strerror(-ret) << dendl;
1346     return ret;
1347   }
1348
1349   return store_info(false);
1350 }
1351
1352 int RGWPeriod::update()
1353 {
1354   ldout(cct, 20) << __func__ << " realm " << realm_id << " period " << get_id() << dendl;
1355   list<string> zonegroups;
1356   int ret = store->list_zonegroups(zonegroups);
1357   if (ret < 0) {
1358     ldout(cct, 0) << "ERROR: failed to list zonegroups: " << cpp_strerror(-ret) << dendl;
1359     return ret;
1360   }
1361
1362   // clear zone short ids of removed zones. period_map.update() will add the
1363   // remaining zones back
1364   period_map.short_zone_ids.clear();
1365
1366   for (auto& iter : zonegroups) {
1367     RGWZoneGroup zg(string(), iter);
1368     ret = zg.init(cct, store);
1369     if (ret < 0) {
1370       ldout(cct, 0) << "WARNING: zg.init() failed: " << cpp_strerror(-ret) << dendl;
1371       continue;
1372     }
1373
1374     if (zg.realm_id != realm_id) {
1375       ldout(cct, 20) << "skipping zonegroup " << zg.get_name() << " zone realm id " << zg.realm_id << ", not on our realm " << realm_id << dendl;
1376       continue;
1377     }
1378
1379     if (zg.master_zone.empty()) {
1380       ldout(cct, 0) << "ERROR: zonegroup " << zg.get_name() << " should have a master zone " << dendl;
1381       return -EINVAL;
1382     }  
1383     
1384     if (zg.is_master_zonegroup()) {
1385       master_zonegroup = zg.get_id();
1386       master_zone = zg.master_zone;
1387     }
1388
1389     int ret = period_map.update(zg, cct);
1390     if (ret < 0) {
1391       return ret;
1392     }
1393   }
1394
1395   ret = period_config.read(store, realm_id);
1396   if (ret < 0 && ret != -ENOENT) {
1397     ldout(cct, 0) << "ERROR: failed to read period config: "
1398         << cpp_strerror(ret) << dendl;
1399     return ret;
1400   }
1401   return 0;
1402 }
1403
1404 int RGWPeriod::reflect()
1405 {
1406   for (auto& iter : period_map.zonegroups) {
1407     RGWZoneGroup& zg = iter.second;
1408     zg.reinit_instance(cct, store);
1409     int r = zg.write(false);
1410     if (r < 0) {
1411       ldout(cct, 0) << "ERROR: failed to store zonegroup info for zonegroup=" << iter.first << ": " << cpp_strerror(-r) << dendl;
1412       return r;
1413     }
1414     if (zg.is_master_zonegroup()) {
1415       // set master as default if no default exists
1416       r = zg.set_as_default(true);
1417       if (r == 0) {
1418         ldout(cct, 1) << "Set the period's master zonegroup " << zg.get_id()
1419             << " as the default" << dendl;
1420       }
1421     }
1422   }
1423
1424   int r = period_config.write(store, realm_id);
1425   if (r < 0) {
1426     ldout(cct, 0) << "ERROR: failed to store period config: "
1427         << cpp_strerror(-r) << dendl;
1428     return r;
1429   }
1430   return 0;
1431 }
1432
1433 void RGWPeriod::fork()
1434 {
1435   ldout(cct, 20) << __func__ << " realm " << realm_id << " period " << id << dendl;
1436   predecessor_uuid = id;
1437   id = get_staging_id(realm_id);
1438   period_map.reset();
1439   realm_epoch++;
1440 }
1441
1442 static int read_sync_status(RGWRados *store, rgw_meta_sync_status *sync_status)
1443 {
1444   // initialize a sync status manager to read the status
1445   RGWMetaSyncStatusManager mgr(store, store->get_async_rados());
1446   int r = mgr.init();
1447   if (r < 0) {
1448     return r;
1449   }
1450   r = mgr.read_sync_status(sync_status);
1451   mgr.stop();
1452   return r;
1453 }
1454
1455 int RGWPeriod::update_sync_status(const RGWPeriod &current_period,
1456                                   std::ostream& error_stream,
1457                                   bool force_if_stale)
1458 {
1459   rgw_meta_sync_status status;
1460   int r = read_sync_status(store, &status);
1461   if (r < 0) {
1462     ldout(cct, 0) << "period failed to read sync status: "
1463         << cpp_strerror(-r) << dendl;
1464     return r;
1465   }
1466
1467   std::vector<std::string> markers;
1468
1469   const auto current_epoch = current_period.get_realm_epoch();
1470   if (current_epoch != status.sync_info.realm_epoch) {
1471     // no sync status markers for the current period
1472     assert(current_epoch > status.sync_info.realm_epoch);
1473     const int behind = current_epoch - status.sync_info.realm_epoch;
1474     if (!force_if_stale && current_epoch > 1) {
1475       error_stream << "ERROR: This zone is " << behind << " period(s) behind "
1476           "the current master zone in metadata sync. If this zone is promoted "
1477           "to master, any metadata changes during that time are likely to "
1478           "be lost.\n"
1479           "Waiting for this zone to catch up on metadata sync (see "
1480           "'radosgw-admin sync status') is recommended.\n"
1481           "To promote this zone to master anyway, add the flag "
1482           "--yes-i-really-mean-it." << std::endl;
1483       return -EINVAL;
1484     }
1485     // empty sync status markers - other zones will skip this period during
1486     // incremental metadata sync
1487     markers.resize(status.sync_info.num_shards);
1488   } else {
1489     markers.reserve(status.sync_info.num_shards);
1490     for (auto& i : status.sync_markers) {
1491       auto& marker = i.second;
1492       // filter out markers from other periods
1493       if (marker.realm_epoch != current_epoch) {
1494         marker.marker.clear();
1495       }
1496       markers.emplace_back(std::move(marker.marker));
1497     }
1498   }
1499
1500   std::swap(sync_status, markers);
1501   return 0;
1502 }
1503
1504 int RGWPeriod::commit(RGWRealm& realm, const RGWPeriod& current_period,
1505                       std::ostream& error_stream, bool force_if_stale)
1506 {
1507   ldout(cct, 20) << __func__ << " realm " << realm.get_id() << " period " << current_period.get_id() << dendl;
1508   // gateway must be in the master zone to commit
1509   if (master_zone != store->get_zone_params().get_id()) {
1510     error_stream << "Cannot commit period on zone "
1511         << store->get_zone_params().get_id() << ", it must be sent to "
1512         "the period's master zone " << master_zone << '.' << std::endl;
1513     return -EINVAL;
1514   }
1515   // period predecessor must match current period
1516   if (predecessor_uuid != current_period.get_id()) {
1517     error_stream << "Period predecessor " << predecessor_uuid
1518         << " does not match current period " << current_period.get_id()
1519         << ". Use 'period pull' to get the latest period from the master, "
1520         "reapply your changes, and try again." << std::endl;
1521     return -EINVAL;
1522   }
1523   // realm epoch must be 1 greater than current period
1524   if (realm_epoch != current_period.get_realm_epoch() + 1) {
1525     error_stream << "Period's realm epoch " << realm_epoch
1526         << " does not come directly after current realm epoch "
1527         << current_period.get_realm_epoch() << ". Use 'realm pull' to get the "
1528         "latest realm and period from the master zone, reapply your changes, "
1529         "and try again." << std::endl;
1530     return -EINVAL;
1531   }
1532   // did the master zone change?
1533   if (master_zone != current_period.get_master_zone()) {
1534     // store the current metadata sync status in the period
1535     int r = update_sync_status(current_period, error_stream, force_if_stale);
1536     if (r < 0) {
1537       ldout(cct, 0) << "failed to update metadata sync status: "
1538           << cpp_strerror(-r) << dendl;
1539       return r;
1540     }
1541     // create an object with a new period id
1542     r = create(true);
1543     if (r < 0) {
1544       ldout(cct, 0) << "failed to create new period: " << cpp_strerror(-r) << dendl;
1545       return r;
1546     }
1547     // set as current period
1548     r = realm.set_current_period(*this);
1549     if (r < 0) {
1550       ldout(cct, 0) << "failed to update realm's current period: "
1551           << cpp_strerror(-r) << dendl;
1552       return r;
1553     }
1554     ldout(cct, 4) << "Promoted to master zone and committed new period "
1555         << id << dendl;
1556     realm.notify_new_period(*this);
1557     return 0;
1558   }
1559   // period must be based on current epoch
1560   if (epoch != current_period.get_epoch()) {
1561     error_stream << "Period epoch " << epoch << " does not match "
1562         "predecessor epoch " << current_period.get_epoch()
1563         << ". Use 'period pull' to get the latest epoch from the master zone, "
1564         "reapply your changes, and try again." << std::endl;
1565     return -EINVAL;
1566   }
1567   // set period as next epoch
1568   set_id(current_period.get_id());
1569   set_epoch(current_period.get_epoch() + 1);
1570   set_predecessor(current_period.get_predecessor());
1571   realm_epoch = current_period.get_realm_epoch();
1572   // write the period to rados
1573   int r = store_info(false);
1574   if (r < 0) {
1575     ldout(cct, 0) << "failed to store period: " << cpp_strerror(-r) << dendl;
1576     return r;
1577   }
1578   // set as latest epoch
1579   r = update_latest_epoch(epoch);
1580   if (r == -EEXIST) {
1581     // already have this epoch (or a more recent one)
1582     return 0;
1583   }
1584   if (r < 0) {
1585     ldout(cct, 0) << "failed to set latest epoch: " << cpp_strerror(-r) << dendl;
1586     return r;
1587   }
1588   r = reflect();
1589   if (r < 0) {
1590     ldout(cct, 0) << "failed to update local objects: " << cpp_strerror(-r) << dendl;
1591     return r;
1592   }
1593   ldout(cct, 4) << "Committed new epoch " << epoch
1594       << " for period " << id << dendl;
1595   realm.notify_new_period(*this);
1596   return 0;
1597 }
1598
1599 int RGWZoneParams::create_default(bool old_format)
1600 {
1601   name = default_zone_name;
1602
1603   int r = create();
1604   if (r < 0) {
1605     return r;
1606   }
1607
1608   if (old_format) {
1609     name = id;
1610   }
1611
1612   return r;
1613 }
1614
1615
1616 int get_zones_pool_set(CephContext* cct,
1617                        RGWRados* store,
1618                        const list<string>& zones,
1619                        const string& my_zone_id,
1620                        set<rgw_pool>& pool_names)
1621 {
1622   for(auto const& iter : zones) {
1623     RGWZoneParams zone(iter);
1624     int r = zone.init(cct, store);
1625     if (r < 0) {
1626       ldout(cct, 0) << "Error: init zone " << iter << ":" << cpp_strerror(-r) << dendl;
1627       return r;
1628     }
1629     if (zone.get_id() != my_zone_id) {
1630       pool_names.insert(zone.domain_root);
1631       pool_names.insert(zone.metadata_heap);
1632       pool_names.insert(zone.control_pool);
1633       pool_names.insert(zone.gc_pool);
1634       pool_names.insert(zone.log_pool);
1635       pool_names.insert(zone.intent_log_pool);
1636       pool_names.insert(zone.usage_log_pool);
1637       pool_names.insert(zone.user_keys_pool);
1638       pool_names.insert(zone.user_email_pool);
1639       pool_names.insert(zone.user_swift_pool);
1640       pool_names.insert(zone.user_uid_pool);
1641       pool_names.insert(zone.roles_pool);
1642       pool_names.insert(zone.reshard_pool);
1643       for(auto& iter : zone.placement_pools) {
1644         pool_names.insert(iter.second.index_pool);
1645         pool_names.insert(iter.second.data_pool);
1646         pool_names.insert(iter.second.data_extra_pool);
1647       }
1648     }
1649   }
1650   return 0;
1651 }
1652
1653 rgw_pool fix_zone_pool_dup(set<rgw_pool> pools,
1654                            const string& default_prefix,
1655                            const string& default_suffix,
1656                            const rgw_pool& suggested_pool)
1657 {
1658   string suggested_name = suggested_pool.to_str();
1659
1660   string prefix = default_prefix;
1661   string suffix = default_suffix;
1662
1663   if (!suggested_pool.empty()) {
1664     prefix = suggested_name.substr(0, suggested_name.find("."));
1665     suffix = suggested_name.substr(prefix.length());
1666   }
1667
1668   rgw_pool pool(prefix + suffix);
1669   
1670   if (pools.find(pool) == pools.end()) {
1671     return pool;
1672   } else {
1673     while(true) {
1674       pool =  prefix + "_" + std::to_string(std::rand()) + suffix;
1675       if (pools.find(pool) == pools.end()) {
1676         return pool;
1677       }
1678     }
1679   }  
1680 }
1681
1682 int RGWZoneParams::fix_pool_names()
1683 {
1684
1685   list<string> zones;
1686   int r = store->list_zones(zones);
1687   if (r < 0) {
1688     ldout(cct, 10) << "WARNING: store->list_zones() returned r=" << r << dendl;
1689   }
1690
1691   set<rgw_pool> pools;
1692   r = get_zones_pool_set(cct, store, zones, id, pools);
1693   if (r < 0) {
1694     ldout(cct, 0) << "Error: get_zones_pool_names" << r << dendl;
1695     return r;
1696   }
1697
1698   domain_root = fix_zone_pool_dup(pools, name, ".rgw.meta:root", domain_root);
1699   if (!metadata_heap.name.empty()) {
1700     metadata_heap = fix_zone_pool_dup(pools, name, ".rgw.meta:heap", metadata_heap);
1701   }
1702   control_pool = fix_zone_pool_dup(pools, name, ".rgw.control", control_pool);
1703   gc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:gc", gc_pool);
1704   lc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:lc", lc_pool);
1705   log_pool = fix_zone_pool_dup(pools, name, ".rgw.log", log_pool);
1706   intent_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:intent", intent_log_pool);
1707   usage_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:usage", usage_log_pool);
1708   user_keys_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.keys", user_keys_pool);
1709   user_email_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.email", user_email_pool);
1710   user_swift_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.swift", user_swift_pool);
1711   user_uid_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.uid", user_uid_pool);
1712   roles_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:roles", roles_pool);
1713   reshard_pool = fix_zone_pool_dup(pools, name, ".rgw.log:reshard", reshard_pool);
1714
1715   for(auto& iter : placement_pools) {
1716     iter.second.index_pool = fix_zone_pool_dup(pools, name, "." + default_bucket_index_pool_suffix,
1717                                                iter.second.index_pool);
1718     iter.second.data_pool = fix_zone_pool_dup(pools, name, "." + default_storage_pool_suffix,
1719                                               iter.second.data_pool);
1720     iter.second.data_extra_pool= fix_zone_pool_dup(pools, name, "." + default_storage_extra_pool_suffix,
1721                                                    iter.second.data_extra_pool);
1722   }
1723
1724   return 0;
1725 }
1726
1727 int RGWZoneParams::create(bool exclusive)
1728 {
1729   /* check for old pools config */
1730   rgw_raw_obj obj(domain_root, avail_pools);
1731   int r = store->raw_obj_stat(obj, NULL, NULL, NULL, NULL, NULL, NULL);
1732   if (r < 0) {
1733     ldout(store->ctx(), 10) << "couldn't find old data placement pools config, setting up new ones for the zone" << dendl;
1734     /* a new system, let's set new placement info */
1735     RGWZonePlacementInfo default_placement;
1736     default_placement.index_pool = name + "." + default_bucket_index_pool_suffix;
1737     default_placement.data_pool =  name + "." + default_storage_pool_suffix;
1738     default_placement.data_extra_pool = name + "." + default_storage_extra_pool_suffix;
1739     placement_pools["default-placement"] = default_placement;
1740   }
1741
1742   r = fix_pool_names();
1743   if (r < 0) {
1744     ldout(cct, 0) << "ERROR: fix_pool_names returned r=" << r << dendl;
1745     return r;
1746   }
1747
1748   r = RGWSystemMetaObj::create(exclusive);
1749   if (r < 0) {
1750     return r;
1751   }
1752
1753   // try to set as default. may race with another create, so pass exclusive=true
1754   // so we don't override an existing default
1755   r = set_as_default(true);
1756   if (r < 0 && r != -EEXIST) {
1757     ldout(cct, 10) << "WARNING: failed to set zone as default, r=" << r << dendl;
1758   }
1759
1760   return 0;
1761 }
1762
1763 rgw_pool RGWZoneParams::get_pool(CephContext *cct)
1764 {
1765   if (cct->_conf->rgw_zone_root_pool.empty()) {
1766     return rgw_pool(RGW_DEFAULT_ZONE_ROOT_POOL);
1767   }
1768
1769   return rgw_pool(cct->_conf->rgw_zone_root_pool);
1770 }
1771
1772 const string RGWZoneParams::get_default_oid(bool old_format)
1773 {
1774   if (old_format) {
1775     return cct->_conf->rgw_default_zone_info_oid;
1776   }
1777
1778   return cct->_conf->rgw_default_zone_info_oid + "." + realm_id;
1779 }
1780
1781 const string& RGWZoneParams::get_names_oid_prefix()
1782 {
1783   return zone_names_oid_prefix;
1784 }
1785
1786 const string& RGWZoneParams::get_info_oid_prefix(bool old_format)
1787 {
1788   return zone_info_oid_prefix;
1789 }
1790
1791 const string& RGWZoneParams::get_predefined_name(CephContext *cct) {
1792   return cct->_conf->rgw_zone;
1793 }
1794
1795 int RGWZoneParams::init(CephContext *cct, RGWRados *store, bool setup_obj, bool old_format)
1796 {
1797   if (name.empty()) {
1798     name = cct->_conf->rgw_zone;
1799   }
1800
1801   return RGWSystemMetaObj::init(cct, store, setup_obj, old_format);
1802 }
1803
1804 int RGWZoneParams::read_default_id(string& default_id, bool old_format)
1805 {
1806   if (realm_id.empty()) {
1807     /* try using default realm */
1808     RGWRealm realm;
1809     int ret = realm.init(cct, store);
1810     if (ret < 0) {
1811       ldout(cct, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
1812       return -ENOENT;
1813     }
1814     realm_id = realm.get_id();
1815   }
1816
1817   return RGWSystemMetaObj::read_default_id(default_id, old_format);
1818 }
1819
1820
1821 int RGWZoneParams::set_as_default(bool exclusive)
1822 {
1823   if (realm_id.empty()) {
1824     /* try using default realm */
1825     RGWRealm realm;
1826     int ret = realm.init(cct, store);
1827     if (ret < 0) {
1828       ldout(cct, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
1829       return -EINVAL;
1830     }
1831     realm_id = realm.get_id();
1832   }
1833
1834   return RGWSystemMetaObj::set_as_default(exclusive);
1835 }
1836
1837 const string& RGWZoneParams::get_compression_type(const string& placement_rule) const
1838 {
1839   static const std::string NONE{"none"};
1840   auto p = placement_pools.find(placement_rule);
1841   if (p == placement_pools.end()) {
1842     return NONE;
1843   }
1844   const auto& type = p->second.compression_type;
1845   return !type.empty() ? type : NONE;
1846 }
1847
1848 void RGWPeriodMap::encode(bufferlist& bl) const {
1849   ENCODE_START(2, 1, bl);
1850   ::encode(id, bl);
1851   ::encode(zonegroups, bl);
1852   ::encode(master_zonegroup, bl);
1853   ::encode(short_zone_ids, bl);
1854   ENCODE_FINISH(bl);
1855 }
1856
1857 void RGWPeriodMap::decode(bufferlist::iterator& bl) {
1858   DECODE_START(2, bl);
1859   ::decode(id, bl);
1860   ::decode(zonegroups, bl);
1861   ::decode(master_zonegroup, bl);
1862   if (struct_v >= 2) {
1863     ::decode(short_zone_ids, bl);
1864   }
1865   DECODE_FINISH(bl);
1866
1867   zonegroups_by_api.clear();
1868   for (map<string, RGWZoneGroup>::iterator iter = zonegroups.begin();
1869        iter != zonegroups.end(); ++iter) {
1870     RGWZoneGroup& zonegroup = iter->second;
1871     zonegroups_by_api[zonegroup.api_name] = zonegroup;
1872     if (zonegroup.is_master_zonegroup()) {
1873       master_zonegroup = zonegroup.get_id();
1874     }
1875   }
1876 }
1877
1878 // run an MD5 hash on the zone_id and return the first 32 bits
1879 static uint32_t gen_short_zone_id(const std::string zone_id)
1880 {
1881   unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE];
1882   MD5 hash;
1883   hash.Update((const byte *)zone_id.c_str(), zone_id.size());
1884   hash.Final(md5);
1885
1886   uint32_t short_id;
1887   memcpy((char *)&short_id, md5, sizeof(short_id));
1888   return std::max(short_id, 1u);
1889 }
1890
1891 int RGWPeriodMap::update(const RGWZoneGroup& zonegroup, CephContext *cct)
1892 {
1893   if (zonegroup.is_master_zonegroup() && (!master_zonegroup.empty() && zonegroup.get_id() != master_zonegroup)) {
1894     ldout(cct,0) << "Error updating periodmap, multiple master zonegroups configured "<< dendl;
1895     ldout(cct,0) << "master zonegroup: " << master_zonegroup << " and  " << zonegroup.get_id() <<dendl;
1896     return -EINVAL;
1897   }
1898   map<string, RGWZoneGroup>::iterator iter = zonegroups.find(zonegroup.get_id());
1899   if (iter != zonegroups.end()) {
1900     RGWZoneGroup& old_zonegroup = iter->second;
1901     if (!old_zonegroup.api_name.empty()) {
1902       zonegroups_by_api.erase(old_zonegroup.api_name);
1903     }
1904   }
1905   zonegroups[zonegroup.get_id()] = zonegroup;
1906
1907   if (!zonegroup.api_name.empty()) {
1908     zonegroups_by_api[zonegroup.api_name] = zonegroup;
1909   }
1910
1911   if (zonegroup.is_master_zonegroup()) {
1912     master_zonegroup = zonegroup.get_id();
1913   } else if (master_zonegroup == zonegroup.get_id()) {
1914     master_zonegroup = "";
1915   }
1916
1917   for (auto& i : zonegroup.zones) {
1918     auto& zone = i.second;
1919     if (short_zone_ids.find(zone.id) != short_zone_ids.end()) {
1920       continue;
1921     }
1922     // calculate the zone's short id
1923     uint32_t short_id = gen_short_zone_id(zone.id);
1924
1925     // search for an existing zone with the same short id
1926     for (auto& s : short_zone_ids) {
1927       if (s.second == short_id) {
1928         ldout(cct, 0) << "New zone '" << zone.name << "' (" << zone.id
1929             << ") generates the same short_zone_id " << short_id
1930             << " as existing zone id " << s.first << dendl;
1931         return -EEXIST;
1932       }
1933     }
1934
1935     short_zone_ids[zone.id] = short_id;
1936   }
1937
1938   return 0;
1939 }
1940
1941 uint32_t RGWPeriodMap::get_zone_short_id(const string& zone_id) const
1942 {
1943   auto i = short_zone_ids.find(zone_id);
1944   if (i == short_zone_ids.end()) {
1945     return 0;
1946   }
1947   return i->second;
1948 }
1949
1950 int RGWZoneGroupMap::read(CephContext *cct, RGWRados *store)
1951 {
1952
1953   RGWPeriod period;
1954   int ret = period.init(cct, store);
1955   if (ret < 0) {
1956     cerr << "failed to read current period info: " << cpp_strerror(ret);
1957     return ret;
1958   }
1959         
1960   bucket_quota = period.get_config().bucket_quota;
1961   user_quota = period.get_config().user_quota;
1962   zonegroups = period.get_map().zonegroups;
1963   zonegroups_by_api = period.get_map().zonegroups_by_api;
1964   master_zonegroup = period.get_map().master_zonegroup;
1965
1966   return 0;
1967 }
1968
1969 void RGWRegionMap::encode(bufferlist& bl) const {
1970   ENCODE_START( 3, 1, bl);
1971   ::encode(regions, bl);
1972   ::encode(master_region, bl);
1973   ::encode(bucket_quota, bl);
1974   ::encode(user_quota, bl);
1975   ENCODE_FINISH(bl);
1976 }
1977
1978 void RGWRegionMap::decode(bufferlist::iterator& bl) {
1979   DECODE_START(3, bl);
1980   ::decode(regions, bl);
1981   ::decode(master_region, bl);
1982   if (struct_v >= 2)
1983     ::decode(bucket_quota, bl);
1984   if (struct_v >= 3)
1985     ::decode(user_quota, bl);
1986   DECODE_FINISH(bl);
1987 }
1988
1989 void RGWZoneGroupMap::encode(bufferlist& bl) const {
1990   ENCODE_START( 3, 1, bl);
1991   ::encode(zonegroups, bl);
1992   ::encode(master_zonegroup, bl);
1993   ::encode(bucket_quota, bl);
1994   ::encode(user_quota, bl);
1995   ENCODE_FINISH(bl);
1996 }
1997
1998 void RGWZoneGroupMap::decode(bufferlist::iterator& bl) {
1999   DECODE_START(3, bl);
2000   ::decode(zonegroups, bl);
2001   ::decode(master_zonegroup, bl);
2002   if (struct_v >= 2)
2003     ::decode(bucket_quota, bl);
2004   if (struct_v >= 3)
2005     ::decode(user_quota, bl);
2006   DECODE_FINISH(bl);
2007
2008   zonegroups_by_api.clear();
2009   for (map<string, RGWZoneGroup>::iterator iter = zonegroups.begin();
2010        iter != zonegroups.end(); ++iter) {
2011     RGWZoneGroup& zonegroup = iter->second;
2012     zonegroups_by_api[zonegroup.api_name] = zonegroup;
2013     if (zonegroup.is_master_zonegroup()) {
2014       master_zonegroup = zonegroup.get_name();
2015     }
2016   }
2017 }
2018
2019 void RGWObjVersionTracker::prepare_op_for_read(ObjectReadOperation *op)
2020 {
2021   obj_version *check_objv = version_for_check();
2022
2023   if (check_objv) {
2024     cls_version_check(*op, *check_objv, VER_COND_EQ);
2025   }
2026
2027   cls_version_read(*op, &read_version);
2028 }
2029
2030 void RGWObjVersionTracker::prepare_op_for_write(ObjectWriteOperation *op)
2031 {
2032   obj_version *check_objv = version_for_check();
2033   obj_version *modify_version = version_for_write();
2034
2035   if (check_objv) {
2036     cls_version_check(*op, *check_objv, VER_COND_EQ);
2037   }
2038
2039   if (modify_version) {
2040     cls_version_set(*op, *modify_version);
2041   } else {
2042     cls_version_inc(*op);
2043   }
2044 }
2045
2046 void RGWObjManifest::obj_iterator::operator++()
2047 {
2048   if (manifest->explicit_objs) {
2049     ++explicit_iter;
2050
2051     if (explicit_iter == manifest->objs.end()) {
2052       ofs = manifest->obj_size;
2053       return;
2054     }
2055
2056     update_explicit_pos();
2057
2058     update_location();
2059     return;
2060   }
2061
2062   uint64_t obj_size = manifest->get_obj_size();
2063   uint64_t head_size = manifest->get_head_size();
2064
2065   if (ofs == obj_size) {
2066     return;
2067   }
2068
2069   if (manifest->rules.empty()) {
2070     return;
2071   }
2072
2073   /* are we still pointing at the head? */
2074   if (ofs < head_size) {
2075     rule_iter = manifest->rules.begin();
2076     RGWObjManifestRule *rule = &rule_iter->second;
2077     ofs = MIN(head_size, obj_size);
2078     stripe_ofs = ofs;
2079     cur_stripe = 1;
2080     stripe_size = MIN(obj_size - ofs, rule->stripe_max_size);
2081     if (rule->part_size > 0) {
2082       stripe_size = MIN(stripe_size, rule->part_size);
2083     }
2084     update_location();
2085     return;
2086   }
2087
2088   RGWObjManifestRule *rule = &rule_iter->second;
2089
2090   stripe_ofs += rule->stripe_max_size;
2091   cur_stripe++;
2092   dout(20) << "RGWObjManifest::operator++(): rule->part_size=" << rule->part_size << " rules.size()=" << manifest->rules.size() << dendl;
2093
2094   if (rule->part_size > 0) {
2095     /* multi part, multi stripes object */
2096
2097     dout(20) << "RGWObjManifest::operator++(): stripe_ofs=" << stripe_ofs << " part_ofs=" << part_ofs << " rule->part_size=" << rule->part_size << dendl;
2098
2099     if (stripe_ofs >= part_ofs + rule->part_size) {
2100       /* moved to the next part */
2101       cur_stripe = 0;
2102       part_ofs += rule->part_size;
2103       stripe_ofs = part_ofs;
2104
2105       bool last_rule = (next_rule_iter == manifest->rules.end());
2106       /* move to the next rule? */
2107       if (!last_rule && stripe_ofs >= next_rule_iter->second.start_ofs) {
2108         rule_iter = next_rule_iter;
2109         last_rule = (next_rule_iter == manifest->rules.end());
2110         if (!last_rule) {
2111           ++next_rule_iter;
2112         }
2113         cur_part_id = rule_iter->second.start_part_num;
2114       } else {
2115         cur_part_id++;
2116       }
2117
2118       rule = &rule_iter->second;
2119     }
2120
2121     stripe_size = MIN(rule->part_size - (stripe_ofs - part_ofs), rule->stripe_max_size);
2122   }
2123
2124   cur_override_prefix = rule->override_prefix;
2125
2126   ofs = stripe_ofs;
2127   if (ofs > obj_size) {
2128     ofs = obj_size;
2129     stripe_ofs = ofs;
2130     stripe_size = 0;
2131   }
2132
2133   dout(20) << "RGWObjManifest::operator++(): result: ofs=" << ofs << " stripe_ofs=" << stripe_ofs << " part_ofs=" << part_ofs << " rule->part_size=" << rule->part_size << dendl;
2134   update_location();
2135 }
2136
2137 int RGWObjManifest::generator::create_begin(CephContext *cct, RGWObjManifest *_m, const string& placement_rule, rgw_bucket& _b, rgw_obj& _obj)
2138 {
2139   manifest = _m;
2140
2141   manifest->set_tail_placement(placement_rule, _b);
2142   manifest->set_head(placement_rule, _obj, 0);
2143   last_ofs = 0;
2144
2145   if (manifest->get_prefix().empty()) {
2146     char buf[33];
2147     gen_rand_alphanumeric(cct, buf, sizeof(buf) - 1);
2148
2149     string oid_prefix = ".";
2150     oid_prefix.append(buf);
2151     oid_prefix.append("_");
2152
2153     manifest->set_prefix(oid_prefix);
2154   }
2155
2156   bool found = manifest->get_rule(0, &rule);
2157   if (!found) {
2158     derr << "ERROR: manifest->get_rule() could not find rule" << dendl;
2159     return -EIO;
2160   }
2161
2162   uint64_t head_size = manifest->get_head_size();
2163
2164   if (head_size > 0) {
2165     cur_stripe_size = head_size;
2166   } else {
2167     cur_stripe_size = rule.stripe_max_size;
2168   }
2169   
2170   cur_part_id = rule.start_part_num;
2171
2172   manifest->get_implicit_location(cur_part_id, cur_stripe, 0, NULL, &cur_obj);
2173
2174   // Normal object which not generated through copy operation 
2175   manifest->set_tail_instance(_obj.key.instance);
2176
2177   manifest->update_iterators();
2178
2179   return 0;
2180 }
2181
2182 int RGWObjManifest::generator::create_next(uint64_t ofs)
2183 {
2184   if (ofs < last_ofs) /* only going forward */
2185     return -EINVAL;
2186
2187   uint64_t max_head_size = manifest->get_max_head_size();
2188
2189   if (ofs < max_head_size) {
2190     manifest->set_head_size(ofs);
2191   }
2192
2193   if (ofs >= max_head_size) {
2194     manifest->set_head_size(max_head_size);
2195     cur_stripe = (ofs - max_head_size) / rule.stripe_max_size;
2196     cur_stripe_size = rule.stripe_max_size;
2197
2198     if (cur_part_id == 0 && max_head_size > 0) {
2199       cur_stripe++;
2200     }
2201   }
2202
2203   last_ofs = ofs;
2204   manifest->set_obj_size(ofs);
2205
2206   manifest->get_implicit_location(cur_part_id, cur_stripe, ofs, NULL, &cur_obj);
2207
2208   manifest->update_iterators();
2209
2210   return 0;
2211 }
2212
2213 const RGWObjManifest::obj_iterator& RGWObjManifest::obj_begin()
2214 {
2215   return begin_iter;
2216 }
2217
2218 const RGWObjManifest::obj_iterator& RGWObjManifest::obj_end()
2219 {
2220   return end_iter;
2221 }
2222
2223 RGWObjManifest::obj_iterator RGWObjManifest::obj_find(uint64_t ofs)
2224 {
2225   if (ofs > obj_size) {
2226     ofs = obj_size;
2227   }
2228   RGWObjManifest::obj_iterator iter(this);
2229   iter.seek(ofs);
2230   return iter;
2231 }
2232
2233 int RGWObjManifest::append(RGWObjManifest& m, RGWZoneGroup& zonegroup, RGWZoneParams& zone_params)
2234 {
2235   if (explicit_objs || m.explicit_objs) {
2236     return append_explicit(m, zonegroup, zone_params);
2237   }
2238
2239   if (rules.empty()) {
2240     *this = m;
2241     return 0;
2242   }
2243
2244   string override_prefix;
2245
2246   if (prefix.empty()) {
2247     prefix = m.prefix;
2248   }
2249
2250   if (prefix != m.prefix) {
2251     override_prefix = m.prefix;
2252   }
2253
2254   map<uint64_t, RGWObjManifestRule>::iterator miter = m.rules.begin();
2255   if (miter == m.rules.end()) {
2256     return append_explicit(m, zonegroup, zone_params);
2257   }
2258
2259   for (; miter != m.rules.end(); ++miter) {
2260     map<uint64_t, RGWObjManifestRule>::reverse_iterator last_rule = rules.rbegin();
2261
2262     RGWObjManifestRule& rule = last_rule->second;
2263
2264     if (rule.part_size == 0) {
2265       rule.part_size = obj_size - rule.start_ofs;
2266     }
2267
2268     RGWObjManifestRule& next_rule = miter->second;
2269     if (!next_rule.part_size) {
2270       next_rule.part_size = m.obj_size - next_rule.start_ofs;
2271     }
2272
2273     string rule_prefix = prefix;
2274     if (!rule.override_prefix.empty()) {
2275       rule_prefix = rule.override_prefix;
2276     }
2277
2278     string next_rule_prefix = m.prefix;
2279     if (!next_rule.override_prefix.empty()) {
2280       next_rule_prefix = next_rule.override_prefix;
2281     }
2282
2283     if (rule.part_size != next_rule.part_size ||
2284         rule.stripe_max_size != next_rule.stripe_max_size ||
2285         rule_prefix != next_rule_prefix) {
2286       if (next_rule_prefix != prefix) {
2287         append_rules(m, miter, &next_rule_prefix);
2288       } else {
2289         append_rules(m, miter, NULL);
2290       }
2291       break;
2292     }
2293
2294     uint64_t expected_part_num = rule.start_part_num + 1;
2295     if (rule.part_size > 0) {
2296       expected_part_num = rule.start_part_num + (obj_size + next_rule.start_ofs - rule.start_ofs) / rule.part_size;
2297     }
2298
2299     if (expected_part_num != next_rule.start_part_num) {
2300       append_rules(m, miter, NULL);
2301       break;
2302     }
2303   }
2304
2305   set_obj_size(obj_size + m.obj_size);
2306
2307   return 0;
2308 }
2309
2310 int RGWObjManifest::append(RGWObjManifest& m, RGWRados *store)
2311 {
2312   return append(m, store->get_zonegroup(), store->get_zone_params());
2313 }
2314
2315 void RGWObjManifest::append_rules(RGWObjManifest& m, map<uint64_t, RGWObjManifestRule>::iterator& miter,
2316                                   string *override_prefix)
2317 {
2318   for (; miter != m.rules.end(); ++miter) {
2319     RGWObjManifestRule rule = miter->second;
2320     rule.start_ofs += obj_size;
2321     if (override_prefix)
2322       rule.override_prefix = *override_prefix;
2323     rules[rule.start_ofs] = rule;
2324   }
2325 }
2326
2327 void RGWObjManifest::convert_to_explicit(const RGWZoneGroup& zonegroup, const RGWZoneParams& zone_params)
2328 {
2329   if (explicit_objs) {
2330     return;
2331   }
2332   obj_iterator iter = obj_begin();
2333
2334   while (iter != obj_end()) {
2335     RGWObjManifestPart& part = objs[iter.get_stripe_ofs()];
2336     const rgw_obj_select& os = iter.get_location();
2337     const rgw_raw_obj& raw_loc = os.get_raw_obj(zonegroup, zone_params);
2338     part.loc_ofs = 0;
2339
2340     uint64_t ofs = iter.get_stripe_ofs();
2341
2342     if (ofs == 0) {
2343       part.loc = obj;
2344     } else {
2345       rgw_raw_obj_to_obj(tail_placement.bucket, raw_loc, &part.loc);
2346     }
2347     ++iter;
2348     uint64_t next_ofs = iter.get_stripe_ofs();
2349
2350     part.size = next_ofs - ofs;
2351   }
2352
2353   explicit_objs = true;
2354   rules.clear();
2355   prefix.clear();
2356 }
2357
2358 int RGWObjManifest::append_explicit(RGWObjManifest& m, const RGWZoneGroup& zonegroup, const RGWZoneParams& zone_params)
2359 {
2360   if (!explicit_objs) {
2361     convert_to_explicit(zonegroup, zone_params);
2362   }
2363   if (!m.explicit_objs) {
2364     m.convert_to_explicit(zonegroup, zone_params);
2365   }
2366   map<uint64_t, RGWObjManifestPart>::iterator iter;
2367   uint64_t base = obj_size;
2368   for (iter = m.objs.begin(); iter != m.objs.end(); ++iter) {
2369     RGWObjManifestPart& part = iter->second;
2370     objs[base + iter->first] = part;
2371   }
2372   obj_size += m.obj_size;
2373
2374   return 0;
2375 }
2376
2377 bool RGWObjManifest::get_rule(uint64_t ofs, RGWObjManifestRule *rule)
2378 {
2379   if (rules.empty()) {
2380     return false;
2381   }
2382
2383   map<uint64_t, RGWObjManifestRule>::iterator iter = rules.upper_bound(ofs);
2384   if (iter != rules.begin()) {
2385     --iter;
2386   }
2387
2388   *rule = iter->second;
2389
2390   return true;
2391 }
2392
2393 void RGWObjVersionTracker::generate_new_write_ver(CephContext *cct)
2394 {
2395   write_version.ver = 1;
2396 #define TAG_LEN 24
2397
2398   write_version.tag.clear();
2399   append_rand_alpha(cct, write_version.tag, write_version.tag, TAG_LEN);
2400 }
2401
2402 int RGWPutObjProcessor::complete(size_t accounted_size, const string& etag,
2403                                  real_time *mtime, real_time set_mtime,
2404                                  map<string, bufferlist>& attrs, real_time delete_at,
2405                                  const char *if_match, const char *if_nomatch, const string *user_data,
2406                                  rgw_zone_set *zones_trace)
2407 {
2408   int r = do_complete(accounted_size, etag, mtime, set_mtime, attrs, delete_at, if_match, if_nomatch, user_data, zones_trace);
2409   if (r < 0)
2410     return r;
2411
2412   is_complete = !canceled;
2413   return 0;
2414 }
2415
2416 CephContext *RGWPutObjProcessor::ctx()
2417 {
2418   return store->ctx();
2419 }
2420
2421 RGWPutObjProcessor_Aio::~RGWPutObjProcessor_Aio()
2422 {
2423   drain_pending();
2424
2425   if (is_complete)
2426     return;
2427
2428   set<rgw_raw_obj>::iterator iter;
2429   bool need_to_remove_head = false;
2430   rgw_raw_obj raw_head;
2431
2432   if (!head_obj.empty()) {
2433     store->obj_to_raw(bucket_info.placement_rule, head_obj, &raw_head);
2434   }
2435
2436   /** 
2437    * We should delete the object in the "multipart" namespace to avoid race condition. 
2438    * Such race condition is caused by the fact that the multipart object is the gatekeeper of a multipart 
2439    * upload, when it is deleted, a second upload would start with the same suffix("2/"), therefore, objects
2440    * written by the second upload may be deleted by the first upload.
2441    * details is describled on #11749
2442    *
2443    * The above comment still stands, but instead of searching for a specific object in the multipart
2444    * namespace, we just make sure that we remove the object that is marked as the head object after
2445    * we remove all the other raw objects. Note that we use different call to remove the head object,
2446    * as this one needs to go via the bucket index prepare/complete 2-phase commit scheme.
2447    */ 
2448   for (iter = written_objs.begin(); iter != written_objs.end(); ++iter) {
2449     const rgw_raw_obj& obj = *iter;
2450     if (!head_obj.empty() && obj == raw_head) {
2451       ldout(store->ctx(), 5) << "NOTE: we should not process the head object (" << obj << ") here" << dendl;
2452       need_to_remove_head = true;
2453       continue;
2454     }
2455
2456     int r = store->delete_raw_obj(obj);
2457     if (r < 0 && r != -ENOENT) {
2458       ldout(store->ctx(), 5) << "WARNING: failed to remove obj (" << obj << "), leaked" << dendl;
2459     }
2460   }
2461
2462   if (need_to_remove_head) {
2463     ldout(store->ctx(), 5) << "NOTE: we are going to process the head obj (" << raw_head << ")" << dendl;
2464     int r = store->delete_obj(obj_ctx, bucket_info, head_obj, 0, 0);
2465     if (r < 0 && r != -ENOENT) {
2466       ldout(store->ctx(), 0) << "WARNING: failed to remove obj (" << raw_head << "), leaked" << dendl;
2467     }
2468   }
2469 }
2470
2471 int RGWPutObjProcessor_Aio::handle_obj_data(rgw_raw_obj& obj, bufferlist& bl, off_t ofs, off_t abs_ofs, void **phandle, bool exclusive)
2472 {
2473   if ((uint64_t)abs_ofs + bl.length() > obj_len)
2474     obj_len = abs_ofs + bl.length();
2475
2476   if (!(obj == last_written_obj)) {
2477     last_written_obj = obj;
2478   }
2479
2480   // For the first call pass -1 as the offset to
2481   // do a write_full.
2482   return store->aio_put_obj_data(NULL, obj, bl, ((ofs != 0) ? ofs : -1), exclusive, phandle);
2483 }
2484
2485 struct put_obj_aio_info RGWPutObjProcessor_Aio::pop_pending()
2486 {
2487   struct put_obj_aio_info info;
2488   info = pending.front();
2489   pending.pop_front();
2490   pending_size -= info.size;
2491   return info;
2492 }
2493
2494 int RGWPutObjProcessor_Aio::wait_pending_front()
2495 {
2496   if (pending.empty()) {
2497     return 0;
2498   }
2499   struct put_obj_aio_info info = pop_pending();
2500   int ret = store->aio_wait(info.handle);
2501
2502   if (ret >= 0) {
2503     add_written_obj(info.obj);
2504   }
2505
2506   return ret;
2507 }
2508
2509 bool RGWPutObjProcessor_Aio::pending_has_completed()
2510 {
2511   if (pending.empty())
2512     return false;
2513
2514   struct put_obj_aio_info& info = pending.front();
2515   return store->aio_completed(info.handle);
2516 }
2517
2518 int RGWPutObjProcessor_Aio::drain_pending()
2519 {
2520   int ret = 0;
2521   while (!pending.empty()) {
2522     int r = wait_pending_front();
2523     if (r < 0)
2524       ret = r;
2525   }
2526   return ret;
2527 }
2528
2529 int RGWPutObjProcessor_Aio::throttle_data(void *handle, const rgw_raw_obj& obj, uint64_t size, bool need_to_wait)
2530 {
2531   bool _wait = need_to_wait;
2532
2533   if (handle) {
2534     struct put_obj_aio_info info;
2535     info.handle = handle;
2536     info.obj = obj;
2537     info.size = size;
2538     pending_size += size;
2539     pending.push_back(info);
2540   }
2541   size_t orig_size = pending_size;
2542
2543   /* first drain complete IOs */
2544   while (pending_has_completed()) {
2545     int r = wait_pending_front();
2546     if (r < 0)
2547       return r;
2548
2549     _wait = false;
2550   }
2551
2552   /* resize window in case messages are draining too fast */
2553   if (orig_size - pending_size >= window_size) {
2554     window_size += store->ctx()->_conf->rgw_max_chunk_size;
2555     uint64_t max_window_size = store->ctx()->_conf->rgw_put_obj_max_window_size;
2556     if (window_size > max_window_size) {
2557       window_size = max_window_size;
2558     }
2559   }
2560
2561   /* now throttle. Note that need_to_wait should only affect the first IO operation */
2562   if (pending_size > window_size || _wait) {
2563     int r = wait_pending_front();
2564     if (r < 0)
2565       return r;
2566   }
2567   return 0;
2568 }
2569
2570 int RGWPutObjProcessor_Atomic::write_data(bufferlist& bl, off_t ofs, void **phandle, rgw_raw_obj *pobj, bool exclusive)
2571 {
2572   if (ofs >= next_part_ofs) {
2573     int r = prepare_next_part(ofs);
2574     if (r < 0) {
2575       return r;
2576     }
2577   }
2578
2579   *pobj = cur_obj;
2580
2581   if (!bl.length()) {
2582     *phandle = nullptr;
2583     return 0;
2584   }
2585
2586   return RGWPutObjProcessor_Aio::handle_obj_data(cur_obj, bl, ofs - cur_part_ofs, ofs, phandle, exclusive);
2587 }
2588
2589 int RGWPutObjProcessor_Aio::prepare(RGWRados *store, string *oid_rand)
2590 {
2591   RGWPutObjProcessor::prepare(store, oid_rand);
2592
2593   window_size = store->ctx()->_conf->rgw_put_obj_min_window_size;
2594
2595   return 0;
2596 }
2597
2598 int RGWPutObjProcessor_Atomic::handle_data(bufferlist& bl, off_t ofs, void **phandle, rgw_raw_obj *pobj, bool *again)
2599 {
2600   *phandle = NULL;
2601   uint64_t max_write_size = MIN(max_chunk_size, (uint64_t)next_part_ofs - data_ofs);
2602
2603   pending_data_bl.claim_append(bl);
2604   if (pending_data_bl.length() < max_write_size) {
2605     *again = false;
2606     return 0;
2607   }
2608
2609   pending_data_bl.splice(0, max_write_size, &bl);
2610
2611   /* do we have enough data pending accumulated that needs to be written? */
2612   *again = (pending_data_bl.length() >= max_chunk_size);
2613
2614   if (!data_ofs && !immutable_head()) {
2615     first_chunk.claim(bl);
2616     obj_len = (uint64_t)first_chunk.length();
2617     int r = prepare_next_part(obj_len);
2618     if (r < 0) {
2619       return r;
2620     }
2621     data_ofs = obj_len;
2622     return 0;
2623   }
2624   off_t write_ofs = data_ofs;
2625   data_ofs = write_ofs + bl.length();
2626   bool exclusive = (!write_ofs && immutable_head()); /* immutable head object, need to verify nothing exists there
2627                                                         we could be racing with another upload, to the same
2628                                                         object and cleanup can be messy */
2629   int ret = write_data(bl, write_ofs, phandle, pobj, exclusive);
2630   if (ret >= 0) { /* we might return, need to clear bl as it was already sent */
2631     bl.clear();
2632   }
2633   return ret;
2634 }
2635
2636
2637 int RGWPutObjProcessor_Atomic::prepare_init(RGWRados *store, string *oid_rand)
2638 {
2639   RGWPutObjProcessor_Aio::prepare(store, oid_rand);
2640
2641   int r = store->get_max_chunk_size(bucket_info.placement_rule, head_obj, &max_chunk_size);
2642   if (r < 0) {
2643     return r;
2644   }
2645
2646   return 0;
2647 }
2648
2649 int RGWPutObjProcessor_Atomic::prepare(RGWRados *store, string *oid_rand)
2650 {
2651   head_obj.init(bucket, obj_str);
2652
2653   int r = prepare_init(store, oid_rand);
2654   if (r < 0) {
2655     return r;
2656   }
2657
2658   if (!version_id.empty()) {
2659     head_obj.key.set_instance(version_id);
2660   } else if (versioned_object) {
2661     store->gen_rand_obj_instance_name(&head_obj);
2662   }
2663
2664   manifest.set_trivial_rule(max_chunk_size, store->ctx()->_conf->rgw_obj_stripe_size);
2665
2666   r = manifest_gen.create_begin(store->ctx(), &manifest, bucket_info.placement_rule, head_obj.bucket, head_obj);
2667   if (r < 0) {
2668     return r;
2669   }
2670
2671   return 0;
2672 }
2673
2674 int RGWPutObjProcessor_Atomic::prepare_next_part(off_t ofs) {
2675
2676   int ret = manifest_gen.create_next(ofs);
2677   if (ret < 0) {
2678     lderr(store->ctx()) << "ERROR: manifest_gen.create_next() returned ret=" << ret << dendl;
2679     return ret;
2680   }
2681   cur_part_ofs = ofs;
2682   next_part_ofs = ofs + manifest_gen.cur_stripe_max_size();
2683   cur_obj = manifest_gen.get_cur_obj(store);
2684
2685   return 0;
2686 }
2687
2688 int RGWPutObjProcessor_Atomic::complete_parts()
2689 {
2690   if (obj_len > (uint64_t)cur_part_ofs) {
2691     return prepare_next_part(obj_len);
2692   }
2693   return 0;
2694 }
2695
2696 int RGWPutObjProcessor_Atomic::complete_writing_data()
2697 {
2698   if (!data_ofs && !immutable_head()) {
2699     /* only claim if pending_data_bl() is not empty. This is needed because we might be called twice
2700      * (e.g., when a retry due to race happens). So a second call to first_chunk.claim() would
2701      * clobber first_chunk
2702      */
2703     if (pending_data_bl.length() > 0) {
2704       first_chunk.claim(pending_data_bl);
2705     }
2706     obj_len = (uint64_t)first_chunk.length();
2707   }
2708   while (pending_data_bl.length()) {
2709     void *handle = nullptr;
2710     rgw_raw_obj obj;
2711     uint64_t max_write_size = MIN(max_chunk_size, (uint64_t)next_part_ofs - data_ofs);
2712     if (max_write_size > pending_data_bl.length()) {
2713       max_write_size = pending_data_bl.length();
2714     }
2715     bufferlist bl;
2716     pending_data_bl.splice(0, max_write_size, &bl);
2717     uint64_t write_len = bl.length();
2718     int r = write_data(bl, data_ofs, &handle, &obj, false);
2719     if (r < 0) {
2720       ldout(store->ctx(), 0) << "ERROR: write_data() returned " << r << dendl;
2721       return r;
2722     }
2723     data_ofs += write_len;
2724     r = throttle_data(handle, obj, write_len, false);
2725     if (r < 0) {
2726       ldout(store->ctx(), 0) << "ERROR: throttle_data() returned " << r << dendl;
2727       return r;
2728     }
2729
2730     if (data_ofs >= next_part_ofs) {
2731       r = prepare_next_part(data_ofs);
2732       if (r < 0) {
2733         ldout(store->ctx(), 0) << "ERROR: prepare_next_part() returned " << r << dendl;
2734         return r;
2735       }
2736     }
2737   }
2738   int r = complete_parts();
2739   if (r < 0) {
2740     return r;
2741   }
2742
2743   r = drain_pending();
2744   if (r < 0)
2745     return r;
2746
2747   return 0;
2748 }
2749
2750 int RGWPutObjProcessor_Atomic::do_complete(size_t accounted_size, const string& etag,
2751                                            real_time *mtime, real_time set_mtime,
2752                                            map<string, bufferlist>& attrs,
2753                                            real_time delete_at,
2754                                            const char *if_match,
2755                                            const char *if_nomatch, const string *user_data,
2756                                            rgw_zone_set *zones_trace) {
2757   int r = complete_writing_data();
2758   if (r < 0)
2759     return r;
2760
2761   obj_ctx.obj.set_atomic(head_obj);
2762
2763   RGWRados::Object op_target(store, bucket_info, obj_ctx, head_obj);
2764
2765   /* some object types shouldn't be versioned, e.g., multipart parts */
2766   op_target.set_versioning_disabled(!versioned_object);
2767
2768   RGWRados::Object::Write obj_op(&op_target);
2769
2770   obj_op.meta.data = &first_chunk;
2771   obj_op.meta.manifest = &manifest;
2772   obj_op.meta.ptag = &unique_tag; /* use req_id as operation tag */
2773   obj_op.meta.if_match = if_match;
2774   obj_op.meta.if_nomatch = if_nomatch;
2775   obj_op.meta.mtime = mtime;
2776   obj_op.meta.set_mtime = set_mtime;
2777   obj_op.meta.owner = bucket_info.owner;
2778   obj_op.meta.flags = PUT_OBJ_CREATE;
2779   obj_op.meta.olh_epoch = olh_epoch;
2780   obj_op.meta.delete_at = delete_at;
2781   obj_op.meta.user_data = user_data;
2782   obj_op.meta.zones_trace = zones_trace;
2783   obj_op.meta.modify_tail = true;
2784
2785   r = obj_op.write_meta(obj_len, accounted_size, attrs);
2786   if (r < 0) {
2787     return r;
2788   }
2789
2790   canceled = obj_op.meta.canceled;
2791
2792   return 0;
2793 }
2794
2795 int RGWRados::watch(const string& oid, uint64_t *watch_handle, librados::WatchCtx2 *ctx) {
2796   int r = control_pool_ctx.watch2(oid, watch_handle, ctx);
2797   if (r < 0)
2798     return r;
2799   return 0;
2800 }
2801
2802 int RGWRados::unwatch(uint64_t watch_handle)
2803 {
2804   int r = control_pool_ctx.unwatch2(watch_handle);
2805   if (r < 0) {
2806     ldout(cct, 0) << "ERROR: rados->unwatch2() returned r=" << r << dendl;
2807     return r;
2808   }
2809   r = rados[0].watch_flush();
2810   if (r < 0) {
2811     ldout(cct, 0) << "ERROR: rados->watch_flush() returned r=" << r << dendl;
2812     return r;
2813   }
2814   return 0;
2815 }
2816
2817 void RGWRados::add_watcher(int i)
2818 {
2819   ldout(cct, 20) << "add_watcher() i=" << i << dendl;
2820   Mutex::Locker l(watchers_lock);
2821   watchers_set.insert(i);
2822   if (watchers_set.size() ==  (size_t)num_watchers) {
2823     ldout(cct, 2) << "all " << num_watchers << " watchers are set, enabling cache" << dendl;
2824     set_cache_enabled(true);
2825   }
2826 }
2827
2828 void RGWRados::remove_watcher(int i)
2829 {
2830   ldout(cct, 20) << "remove_watcher() i=" << i << dendl;
2831   Mutex::Locker l(watchers_lock);
2832   size_t orig_size = watchers_set.size();
2833   watchers_set.erase(i);
2834   if (orig_size == (size_t)num_watchers &&
2835       watchers_set.size() < orig_size) { /* actually removed */
2836     ldout(cct, 2) << "removed watcher, disabling cache" << dendl;
2837     set_cache_enabled(false);
2838   }
2839 }
2840
2841 class RGWWatcher : public librados::WatchCtx2 {
2842   RGWRados *rados;
2843   int index;
2844   string oid;
2845   uint64_t watch_handle;
2846
2847   class C_ReinitWatch : public Context {
2848     RGWWatcher *watcher;
2849     public:
2850       explicit C_ReinitWatch(RGWWatcher *_watcher) : watcher(_watcher) {}
2851       void finish(int r) override {
2852         watcher->reinit();
2853       }
2854   };
2855 public:
2856   RGWWatcher(RGWRados *r, int i, const string& o) : rados(r), index(i), oid(o), watch_handle(0) {}
2857   void handle_notify(uint64_t notify_id,
2858                      uint64_t cookie,
2859                      uint64_t notifier_id,
2860                      bufferlist& bl) override {
2861     ldout(rados->ctx(), 10) << "RGWWatcher::handle_notify() "
2862                             << " notify_id " << notify_id
2863                             << " cookie " << cookie
2864                             << " notifier " << notifier_id
2865                             << " bl.length()=" << bl.length() << dendl;
2866     rados->watch_cb(notify_id, cookie, notifier_id, bl);
2867
2868     bufferlist reply_bl; // empty reply payload
2869     rados->control_pool_ctx.notify_ack(oid, notify_id, cookie, reply_bl);
2870   }
2871   void handle_error(uint64_t cookie, int err) override {
2872     lderr(rados->ctx()) << "RGWWatcher::handle_error cookie " << cookie
2873                         << " err " << cpp_strerror(err) << dendl;
2874     rados->remove_watcher(index);
2875     rados->schedule_context(new C_ReinitWatch(this));
2876   }
2877
2878   void reinit() {
2879     int ret = unregister_watch();
2880     if (ret < 0) {
2881       ldout(rados->ctx(), 0) << "ERROR: unregister_watch() returned ret=" << ret << dendl;
2882       return;
2883     }
2884     ret = register_watch();
2885     if (ret < 0) {
2886       ldout(rados->ctx(), 0) << "ERROR: register_watch() returned ret=" << ret << dendl;
2887       return;
2888     }
2889   }
2890
2891   int unregister_watch() {
2892     int r = rados->unwatch(watch_handle);
2893     if (r < 0) {
2894       return r;
2895     }
2896     rados->remove_watcher(index);
2897     return 0;
2898   }
2899
2900   int register_watch() {
2901     int r = rados->watch(oid, &watch_handle, this);
2902     if (r < 0) {
2903       return r;
2904     }
2905     rados->add_watcher(index);
2906     return 0;
2907   }
2908 };
2909
2910 class RGWMetaNotifierManager : public RGWCoroutinesManager {
2911   RGWRados *store;
2912   RGWHTTPManager http_manager;
2913
2914 public:
2915   RGWMetaNotifierManager(RGWRados *_store) : RGWCoroutinesManager(_store->ctx(), _store->get_cr_registry()), store(_store),
2916                                              http_manager(store->ctx(), completion_mgr) {
2917     http_manager.set_threaded();
2918   }
2919
2920   int notify_all(map<string, RGWRESTConn *>& conn_map, set<int>& shards) {
2921     rgw_http_param_pair pairs[] = { { "type", "metadata" },
2922                                     { "notify", NULL },
2923                                     { NULL, NULL } };
2924
2925     list<RGWCoroutinesStack *> stacks;
2926     for (map<string, RGWRESTConn *>::iterator iter = conn_map.begin(); iter != conn_map.end(); ++iter) {
2927       RGWRESTConn *conn = iter->second;
2928       RGWCoroutinesStack *stack = new RGWCoroutinesStack(store->ctx(), this);
2929       stack->call(new RGWPostRESTResourceCR<set<int>, int>(store->ctx(), conn, &http_manager, "/admin/log", pairs, shards, NULL));
2930
2931       stacks.push_back(stack);
2932     }
2933     return run(stacks);
2934   }
2935 };
2936
2937 class RGWDataNotifierManager : public RGWCoroutinesManager {
2938   RGWRados *store;
2939   RGWHTTPManager http_manager;
2940
2941 public:
2942   RGWDataNotifierManager(RGWRados *_store) : RGWCoroutinesManager(_store->ctx(), _store->get_cr_registry()), store(_store),
2943                                              http_manager(store->ctx(), completion_mgr) {
2944     http_manager.set_threaded();
2945   }
2946
2947   int notify_all(map<string, RGWRESTConn *>& conn_map, map<int, set<string> >& shards) {
2948     rgw_http_param_pair pairs[] = { { "type", "data" },
2949                                     { "notify", NULL },
2950                                     { "source-zone", store->get_zone_params().get_id().c_str() },
2951                                     { NULL, NULL } };
2952
2953     list<RGWCoroutinesStack *> stacks;
2954     for (map<string, RGWRESTConn *>::iterator iter = conn_map.begin(); iter != conn_map.end(); ++iter) {
2955       RGWRESTConn *conn = iter->second;
2956       RGWCoroutinesStack *stack = new RGWCoroutinesStack(store->ctx(), this);
2957       stack->call(new RGWPostRESTResourceCR<map<int, set<string> >, int>(store->ctx(), conn, &http_manager, "/admin/log", pairs, shards, NULL));
2958
2959       stacks.push_back(stack);
2960     }
2961     return run(stacks);
2962   }
2963 };
2964
2965 class RGWRadosThread {
2966   class Worker : public Thread {
2967     CephContext *cct;
2968     RGWRadosThread *processor;
2969     Mutex lock;
2970     Cond cond;
2971
2972     void wait() {
2973       Mutex::Locker l(lock);
2974       cond.Wait(lock);
2975     };
2976
2977     void wait_interval(const utime_t& wait_time) {
2978       Mutex::Locker l(lock);
2979       cond.WaitInterval(lock, wait_time);
2980     }
2981
2982   public:
2983     Worker(CephContext *_cct, RGWRadosThread *_p) : cct(_cct), processor(_p), lock("RGWRadosThread::Worker") {}
2984     void *entry() override;
2985     void signal() {
2986       Mutex::Locker l(lock);
2987       cond.Signal();
2988     }
2989   };
2990
2991   Worker *worker;
2992
2993 protected:
2994   CephContext *cct;
2995   RGWRados *store;
2996
2997   std::atomic<bool> down_flag = { false };
2998
2999   string thread_name;
3000
3001   virtual uint64_t interval_msec() = 0;
3002   virtual void stop_process() {}
3003 public:
3004   RGWRadosThread(RGWRados *_store, const string& thread_name = "radosgw") 
3005     : worker(NULL), cct(_store->ctx()), store(_store), thread_name(thread_name) {}
3006   virtual ~RGWRadosThread() {
3007     stop();
3008   }
3009
3010   virtual int init() { return 0; }
3011   virtual int process() = 0;
3012
3013   bool going_down() { return down_flag; }
3014
3015   void start();
3016   void stop();
3017
3018   void signal() {
3019     if (worker) {
3020       worker->signal();
3021     }
3022   }
3023 };
3024
3025 void RGWRadosThread::start()
3026 {
3027   worker = new Worker(cct, this);
3028   worker->create(thread_name.c_str());
3029 }
3030
3031 void RGWRadosThread::stop()
3032 {
3033   down_flag = true;
3034   stop_process();
3035   if (worker) {
3036     worker->signal();
3037     worker->join();
3038   }
3039   delete worker;
3040   worker = NULL;
3041 }
3042
3043 void *RGWRadosThread::Worker::entry() {
3044   uint64_t msec = processor->interval_msec();
3045   utime_t interval = utime_t(msec / 1000, (msec % 1000) * 1000000);
3046
3047   do {
3048     utime_t start = ceph_clock_now();
3049     int r = processor->process();
3050     if (r < 0) {
3051       dout(0) << "ERROR: processor->process() returned error r=" << r << dendl;
3052     }
3053
3054     if (processor->going_down())
3055       break;
3056
3057     utime_t end = ceph_clock_now();
3058     end -= start;
3059
3060     uint64_t cur_msec = processor->interval_msec();
3061     if (cur_msec != msec) { /* was it reconfigured? */
3062       msec = cur_msec;
3063       interval = utime_t(msec / 1000, (msec % 1000) * 1000000);
3064     }
3065
3066     if (cur_msec > 0) {
3067       if (interval <= end)
3068         continue; // next round
3069
3070       utime_t wait_time = interval;
3071       wait_time -= end;
3072
3073       wait_interval(wait_time);
3074     } else {
3075       wait();
3076     }
3077   } while (!processor->going_down());
3078
3079   return NULL;
3080 }
3081
3082 class RGWMetaNotifier : public RGWRadosThread {
3083   RGWMetaNotifierManager notify_mgr;
3084   RGWMetadataLog *const log;
3085
3086   uint64_t interval_msec() override {
3087     return cct->_conf->rgw_md_notify_interval_msec;
3088   }
3089 public:
3090   RGWMetaNotifier(RGWRados *_store, RGWMetadataLog* log)
3091     : RGWRadosThread(_store, "meta-notifier"), notify_mgr(_store), log(log) {}
3092
3093   int process() override;
3094 };
3095
3096 int RGWMetaNotifier::process()
3097 {
3098   set<int> shards;
3099
3100   log->read_clear_modified(shards);
3101
3102   if (shards.empty()) {
3103     return 0;
3104   }
3105
3106   for (set<int>::iterator iter = shards.begin(); iter != shards.end(); ++iter) {
3107     ldout(cct, 20) << __func__ << "(): notifying mdlog change, shard_id=" << *iter << dendl;
3108   }
3109
3110   notify_mgr.notify_all(store->zone_conn_map, shards);
3111
3112   return 0;
3113 }
3114
3115 class RGWDataNotifier : public RGWRadosThread {
3116   RGWDataNotifierManager notify_mgr;
3117
3118   uint64_t interval_msec() override {
3119     return cct->_conf->get_val<int64_t>("rgw_data_notify_interval_msec");
3120   }
3121 public:
3122   RGWDataNotifier(RGWRados *_store) : RGWRadosThread(_store, "data-notifier"), notify_mgr(_store) {}
3123
3124   int process() override;
3125 };
3126
3127 int RGWDataNotifier::process()
3128 {
3129   if (!store->data_log) {
3130     return 0;
3131   }
3132
3133   map<int, set<string> > shards;
3134
3135   store->data_log->read_clear_modified(shards);
3136
3137   if (shards.empty()) {
3138     return 0;
3139   }
3140
3141   for (map<int, set<string> >::iterator iter = shards.begin(); iter != shards.end(); ++iter) {
3142     ldout(cct, 20) << __func__ << "(): notifying datalog change, shard_id=" << iter->first << ": " << iter->second << dendl;
3143   }
3144
3145   notify_mgr.notify_all(store->zone_data_notify_to_map, shards);
3146
3147   return 0;
3148 }
3149
3150 class RGWSyncProcessorThread : public RGWRadosThread {
3151 public:
3152   RGWSyncProcessorThread(RGWRados *_store, const string& thread_name = "radosgw") : RGWRadosThread(_store, thread_name) {}
3153   RGWSyncProcessorThread(RGWRados *_store) : RGWRadosThread(_store) {}
3154   ~RGWSyncProcessorThread() override {}
3155   int init() override = 0 ;
3156   int process() override = 0;
3157 };
3158
3159 class RGWMetaSyncProcessorThread : public RGWSyncProcessorThread
3160 {
3161   RGWMetaSyncStatusManager sync;
3162
3163   uint64_t interval_msec() override {
3164     return 0; /* no interval associated, it'll run once until stopped */
3165   }
3166   void stop_process() override {
3167     sync.stop();
3168   }
3169 public:
3170   RGWMetaSyncProcessorThread(RGWRados *_store, RGWAsyncRadosProcessor *async_rados)
3171     : RGWSyncProcessorThread(_store, "meta-sync"), sync(_store, async_rados) {}
3172
3173   void wakeup_sync_shards(set<int>& shard_ids) {
3174     for (set<int>::iterator iter = shard_ids.begin(); iter != shard_ids.end(); ++iter) {
3175       sync.wakeup(*iter);
3176     }
3177   }
3178   RGWMetaSyncStatusManager* get_manager() { return &sync; }
3179
3180   int init() override {
3181     int ret = sync.init();
3182     if (ret < 0) {
3183       ldout(store->ctx(), 0) << "ERROR: sync.init() returned " << ret << dendl;
3184       return ret;
3185     }
3186     return 0;
3187   }
3188
3189   int process() override {
3190     sync.run();
3191     return 0;
3192   }
3193 };
3194
3195 class RGWDataSyncProcessorThread : public RGWSyncProcessorThread
3196 {
3197   RGWDataSyncStatusManager sync;
3198   bool initialized;
3199
3200   uint64_t interval_msec() override {
3201     if (initialized) {
3202       return 0; /* no interval associated, it'll run once until stopped */
3203     } else {
3204 #define DATA_SYNC_INIT_WAIT_SEC 20
3205       return DATA_SYNC_INIT_WAIT_SEC * 1000;
3206     }
3207   }
3208   void stop_process() override {
3209     sync.stop();
3210   }
3211 public:
3212   RGWDataSyncProcessorThread(RGWRados *_store, RGWAsyncRadosProcessor *async_rados,
3213                              const string& _source_zone)
3214     : RGWSyncProcessorThread(_store, "data-sync"), sync(_store, async_rados, _source_zone),
3215       initialized(false) {}
3216
3217   void wakeup_sync_shards(map<int, set<string> >& shard_ids) {
3218     for (map<int, set<string> >::iterator iter = shard_ids.begin(); iter != shard_ids.end(); ++iter) {
3219       sync.wakeup(iter->first, iter->second);
3220     }
3221   }
3222   RGWDataSyncStatusManager* get_manager() { return &sync; }
3223
3224   int init() override {
3225     return 0;
3226   }
3227
3228   int process() override {
3229     while (!initialized) {
3230       if (going_down()) {
3231         return 0;
3232       }
3233       int ret = sync.init();
3234       if (ret >= 0) {
3235         initialized = true;
3236         break;
3237       }
3238       /* we'll be back! */
3239       return 0;
3240     }
3241     sync.run();
3242     return 0;
3243   }
3244 };
3245
3246 class RGWSyncLogTrimThread : public RGWSyncProcessorThread
3247 {
3248   RGWCoroutinesManager crs;
3249   RGWRados *store;
3250   RGWHTTPManager http;
3251   const utime_t trim_interval;
3252
3253   uint64_t interval_msec() override { return 0; }
3254   void stop_process() override { crs.stop(); }
3255 public:
3256   RGWSyncLogTrimThread(RGWRados *store, int interval)
3257     : RGWSyncProcessorThread(store, "sync-log-trim"),
3258       crs(store->ctx(), store->get_cr_registry()), store(store),
3259       http(store->ctx(), crs.get_completion_mgr()),
3260       trim_interval(interval, 0)
3261   {}
3262
3263   int init() override {
3264     return http.set_threaded();
3265   }
3266   int process() override {
3267     list<RGWCoroutinesStack*> stacks;
3268     auto meta = new RGWCoroutinesStack(store->ctx(), &crs);
3269     meta->call(create_meta_log_trim_cr(store, &http,
3270                                        cct->_conf->rgw_md_log_max_shards,
3271                                        trim_interval));
3272     stacks.push_back(meta);
3273
3274     auto data = new RGWCoroutinesStack(store->ctx(), &crs);
3275     data->call(create_data_log_trim_cr(store, &http,
3276                                        cct->_conf->rgw_data_log_num_shards,
3277                                        trim_interval));
3278     stacks.push_back(data);
3279
3280     crs.run(stacks);
3281     return 0;
3282   }
3283 };
3284
3285 void RGWRados::wakeup_meta_sync_shards(set<int>& shard_ids)
3286 {
3287   Mutex::Locker l(meta_sync_thread_lock);
3288   if (meta_sync_processor_thread) {
3289     meta_sync_processor_thread->wakeup_sync_shards(shard_ids);
3290   }
3291 }
3292
3293 void RGWRados::wakeup_data_sync_shards(const string& source_zone, map<int, set<string> >& shard_ids)
3294 {
3295   ldout(ctx(), 20) << __func__ << ": source_zone=" << source_zone << ", shard_ids=" << shard_ids << dendl;
3296   Mutex::Locker l(data_sync_thread_lock);
3297   map<string, RGWDataSyncProcessorThread *>::iterator iter = data_sync_processor_threads.find(source_zone);
3298   if (iter == data_sync_processor_threads.end()) {
3299     ldout(ctx(), 10) << __func__ << ": couldn't find sync thread for zone " << source_zone << ", skipping async data sync processing" << dendl;
3300     return;
3301   }
3302
3303   RGWDataSyncProcessorThread *thread = iter->second;
3304   assert(thread);
3305   thread->wakeup_sync_shards(shard_ids);
3306 }
3307
3308 RGWMetaSyncStatusManager* RGWRados::get_meta_sync_manager()
3309 {
3310   Mutex::Locker l(meta_sync_thread_lock);
3311   if (meta_sync_processor_thread) {
3312     return meta_sync_processor_thread->get_manager();
3313   }
3314   return nullptr;
3315 }
3316
3317 RGWDataSyncStatusManager* RGWRados::get_data_sync_manager(const std::string& source_zone)
3318 {
3319   Mutex::Locker l(data_sync_thread_lock);
3320   auto thread = data_sync_processor_threads.find(source_zone);
3321   if (thread == data_sync_processor_threads.end()) {
3322     return nullptr;
3323   }
3324   return thread->second->get_manager();
3325 }
3326
3327 int RGWRados::get_required_alignment(const rgw_pool& pool, uint64_t *alignment)
3328 {
3329   IoCtx ioctx;
3330   int r = open_pool_ctx(pool, ioctx);
3331   if (r < 0) {
3332     ldout(cct, 0) << "ERROR: open_pool_ctx() returned " << r << dendl;
3333     return r;
3334   }
3335
3336   bool requires;
3337   r = ioctx.pool_requires_alignment2(&requires);
3338   if (r < 0) {
3339     ldout(cct, 0) << "ERROR: ioctx.pool_requires_alignment2() returned " 
3340       << r << dendl;
3341     return r;
3342   }
3343
3344   if (!requires) {
3345     *alignment = 0;
3346     return 0;
3347   }
3348
3349   uint64_t align;
3350   r = ioctx.pool_required_alignment2(&align);
3351   if (r < 0) {
3352     ldout(cct, 0) << "ERROR: ioctx.pool_required_alignment2() returned " 
3353       << r << dendl;
3354     return r;
3355   }
3356   if (align != 0) {
3357     ldout(cct, 20) << "required alignment=" << align << dendl;
3358   }
3359   *alignment = align;
3360   return 0;
3361 }
3362
3363 int RGWRados::get_max_chunk_size(const rgw_pool& pool, uint64_t *max_chunk_size)
3364 {
3365   uint64_t alignment = 0;
3366   int r = get_required_alignment(pool, &alignment);
3367   if (r < 0) {
3368     return r;
3369   }
3370
3371   uint64_t config_chunk_size = cct->_conf->rgw_max_chunk_size;
3372
3373   if (alignment == 0) {
3374     *max_chunk_size = config_chunk_size;
3375     return 0;
3376   }
3377
3378   if (config_chunk_size <= alignment) {
3379     *max_chunk_size = alignment;
3380     return 0;
3381   }
3382
3383   *max_chunk_size = config_chunk_size - (config_chunk_size % alignment);
3384
3385   ldout(cct, 20) << "max_chunk_size=" << *max_chunk_size << dendl;
3386
3387   return 0;
3388 }
3389
3390 int RGWRados::get_max_chunk_size(const string& placement_rule, const rgw_obj& obj, uint64_t *max_chunk_size)
3391 {
3392   rgw_pool pool;
3393   if (!get_obj_data_pool(placement_rule, obj, &pool)) {
3394     ldout(cct, 0) << "ERROR: failed to get data pool for object " << obj << dendl;
3395     return -EIO;
3396   }
3397   return get_max_chunk_size(pool, max_chunk_size);
3398 }
3399
3400 class RGWIndexCompletionManager;
3401
3402 struct complete_op_data {
3403   Mutex lock{"complete_op_data"};
3404   AioCompletion *rados_completion{nullptr};
3405   int manager_shard_id{-1};
3406   RGWIndexCompletionManager *manager{nullptr};
3407   rgw_obj obj;
3408   RGWModifyOp op;
3409   string tag;
3410   rgw_bucket_entry_ver ver;
3411   cls_rgw_obj_key key;
3412   rgw_bucket_dir_entry_meta dir_meta;
3413   list<cls_rgw_obj_key> remove_objs;
3414   bool log_op;
3415   uint16_t bilog_op;
3416   rgw_zone_set zones_trace;
3417
3418   bool stopped{false};
3419
3420   void stop() {
3421     Mutex::Locker l(lock);
3422     stopped = true;
3423   }
3424 };
3425
3426 class RGWIndexCompletionThread : public RGWRadosThread {
3427   RGWRados *store;
3428
3429   uint64_t interval_msec() override {
3430     return 0;
3431   }
3432
3433   list<complete_op_data *> completions;
3434
3435   Mutex completions_lock;
3436 public:
3437   RGWIndexCompletionThread(RGWRados *_store)
3438     : RGWRadosThread(_store, "index-complete"), store(_store), completions_lock("RGWIndexCompletionThread::completions_lock") {}
3439
3440   int process() override;
3441
3442   void add_completion(complete_op_data *completion) {
3443     {
3444       Mutex::Locker l(completions_lock);
3445       completions.push_back(completion);
3446     }
3447
3448     signal();
3449   }
3450 };
3451
3452 int RGWIndexCompletionThread::process()
3453 {
3454   list<complete_op_data *> comps;
3455
3456   {
3457     Mutex::Locker l(completions_lock);
3458     completions.swap(comps);
3459   }
3460
3461   for (auto c : comps) {
3462     std::unique_ptr<complete_op_data> up{c};
3463
3464     if (going_down()) {
3465       continue;
3466     }
3467     ldout(store->ctx(), 20) << __func__ << "(): handling completion for key=" << c->key << dendl;
3468
3469     RGWRados::BucketShard bs(store);
3470
3471     int r = bs.init(c->obj.bucket, c->obj);
3472     if (r < 0) {
3473       ldout(cct, 0) << "ERROR: " << __func__ << "(): failed to initialize BucketShard, obj=" << c->obj << " r=" << r << dendl;
3474       /* not much to do */
3475       continue;
3476     }
3477
3478     r = store->guard_reshard(&bs, c->obj, [&](RGWRados::BucketShard *bs) -> int { 
3479                              librados::ObjectWriteOperation o;
3480                              cls_rgw_guard_bucket_resharding(o, -ERR_BUSY_RESHARDING);
3481                              cls_rgw_bucket_complete_op(o, c->op, c->tag, c->ver, c->key, c->dir_meta, &c->remove_objs,
3482                                                         c->log_op, c->bilog_op, &c->zones_trace);
3483
3484                              return bs->index_ctx.operate(bs->bucket_obj, &o);
3485                              });
3486     if (r < 0) {
3487       ldout(cct, 0) << "ERROR: " << __func__ << "(): bucket index completion failed, obj=" << c->obj << " r=" << r << dendl;
3488       /* ignoring error, can't do anything about it */
3489       continue;
3490     }
3491     r = store->data_log->add_entry(bs.bucket, bs.shard_id);
3492     if (r < 0) {
3493       lderr(store->ctx()) << "ERROR: failed writing data log" << dendl;
3494     }
3495   }
3496
3497   return 0;
3498 }
3499
3500 class RGWIndexCompletionManager {
3501   RGWRados *store{nullptr};
3502   vector<Mutex *> locks;
3503   vector<set<complete_op_data *> > completions;
3504
3505   RGWIndexCompletionThread *completion_thread{nullptr};
3506
3507   int num_shards;
3508
3509   std::atomic<int> cur_shard {0};
3510
3511
3512 public:
3513   RGWIndexCompletionManager(RGWRados *_store) : store(_store) {
3514     num_shards = store->ctx()->_conf->rgw_thread_pool_size;
3515
3516     for (int i = 0; i < num_shards; i++) {
3517       char buf[64];
3518       snprintf(buf, sizeof(buf), "RGWIndexCompletionManager::lock::%d", i);
3519       locks.push_back(new Mutex(buf));
3520     }
3521
3522     completions.resize(num_shards);
3523   }
3524   ~RGWIndexCompletionManager() {
3525     stop();
3526
3527     for (auto l : locks) {
3528       delete l;
3529     }
3530   }
3531
3532   int next_shard() {
3533     int result = cur_shard % num_shards;
3534     cur_shard++;
3535     return result;
3536   }
3537
3538   void create_completion(const rgw_obj& obj,
3539                          RGWModifyOp op, string& tag,
3540                          rgw_bucket_entry_ver& ver,
3541                          const cls_rgw_obj_key& key,
3542                          rgw_bucket_dir_entry_meta& dir_meta,
3543                          list<cls_rgw_obj_key> *remove_objs, bool log_op,
3544                          uint16_t bilog_op,
3545                          rgw_zone_set *zones_trace,
3546                          complete_op_data **result);
3547   bool handle_completion(completion_t cb, complete_op_data *arg);
3548
3549   int start() {
3550     completion_thread = new RGWIndexCompletionThread(store);
3551     int ret = completion_thread->init();
3552     if (ret < 0) {
3553       return ret;
3554     }
3555     completion_thread->start();
3556     return 0;
3557   }
3558   void stop() {
3559     if (completion_thread) {
3560       completion_thread->stop();
3561       delete completion_thread;
3562     }
3563
3564     for (int i = 0; i < num_shards; ++i) {
3565       Mutex::Locker l(*locks[i]);
3566       for (auto c : completions[i]) {
3567         Mutex::Locker cl(c->lock);
3568         c->stop();
3569       }
3570     }
3571     completions.clear();
3572   }
3573 };
3574
3575 static void obj_complete_cb(completion_t cb, void *arg)
3576 {
3577   complete_op_data *completion = (complete_op_data *)arg;
3578   completion->lock.Lock();
3579   if (completion->stopped) {
3580     completion->lock.Unlock(); /* can drop lock, no one else is referencing us */
3581     delete completion;
3582     return;
3583   }
3584   bool need_delete = completion->manager->handle_completion(cb, completion);
3585   completion->lock.Unlock();
3586   if (need_delete) {
3587     delete completion;
3588   }
3589 }
3590
3591
3592 void RGWIndexCompletionManager::create_completion(const rgw_obj& obj,
3593                                                   RGWModifyOp op, string& tag,
3594                                                   rgw_bucket_entry_ver& ver,
3595                                                   const cls_rgw_obj_key& key,
3596                                                   rgw_bucket_dir_entry_meta& dir_meta,
3597                                                   list<cls_rgw_obj_key> *remove_objs, bool log_op,
3598                                                   uint16_t bilog_op,
3599                                                   rgw_zone_set *zones_trace,
3600                                                   complete_op_data **result)
3601 {
3602   complete_op_data *entry = new complete_op_data;
3603
3604   int shard_id = next_shard();
3605
3606   entry->manager_shard_id = shard_id;
3607   entry->manager = this;
3608   entry->obj = obj;
3609   entry->op = op;
3610   entry->tag = tag;
3611   entry->ver = ver;
3612   entry->key = key;
3613   entry->dir_meta = dir_meta;
3614   entry->log_op = log_op;
3615   entry->bilog_op = bilog_op;
3616
3617   if (remove_objs) {
3618     for (auto iter = remove_objs->begin(); iter != remove_objs->end(); ++iter) {
3619       entry->remove_objs.push_back(*iter);
3620     }
3621   }
3622
3623   if (zones_trace) {
3624     entry->zones_trace = *zones_trace;
3625   } else {
3626     entry->zones_trace.insert(store->get_zone().id);
3627   }
3628
3629   *result = entry;
3630
3631   entry->rados_completion = librados::Rados::aio_create_completion(entry, NULL, obj_complete_cb);
3632
3633   Mutex::Locker l(*locks[shard_id]);
3634   completions[shard_id].insert(entry);
3635 }
3636
3637 bool RGWIndexCompletionManager::handle_completion(completion_t cb, complete_op_data *arg)
3638 {
3639   int shard_id = arg->manager_shard_id;
3640   {
3641     Mutex::Locker l(*locks[shard_id]);
3642
3643     auto& comps = completions[shard_id];
3644
3645     auto iter = comps.find(arg);
3646     if (iter == comps.end()) {
3647       return true;
3648     }
3649
3650     comps.erase(iter);
3651   }
3652
3653   int r = rados_aio_get_return_value(cb);
3654   if (r != -ERR_BUSY_RESHARDING) {
3655     return true;
3656   }
3657   completion_thread->add_completion(arg);
3658   return false;
3659 }
3660
3661 void RGWRados::finalize()
3662 {
3663   if (run_sync_thread) {
3664     Mutex::Locker l(meta_sync_thread_lock);
3665     meta_sync_processor_thread->stop();
3666
3667     Mutex::Locker dl(data_sync_thread_lock);
3668     for (auto iter : data_sync_processor_threads) {
3669       RGWDataSyncProcessorThread *thread = iter.second;
3670       thread->stop();
3671     }
3672     if (sync_log_trimmer) {
3673       sync_log_trimmer->stop();
3674     }
3675   }
3676   if (async_rados) {
3677     async_rados->stop();
3678   }
3679   if (run_sync_thread) {
3680     delete meta_sync_processor_thread;
3681     meta_sync_processor_thread = NULL;
3682     Mutex::Locker dl(data_sync_thread_lock);
3683     for (auto iter : data_sync_processor_threads) {
3684       RGWDataSyncProcessorThread *thread = iter.second;
3685       delete thread;
3686     }
3687     data_sync_processor_threads.clear();
3688     delete sync_log_trimmer;
3689     sync_log_trimmer = nullptr;
3690   }
3691   if (finisher) {
3692     finisher->stop();
3693   }
3694   if (need_watch_notify()) {
3695     finalize_watch();
3696   }
3697   if (finisher) {
3698     /* delete finisher only after cleaning up watches, as watch error path might call
3699      * into finisher. We stop finisher before finalizing watch to make sure we don't
3700      * actually handle any racing work
3701      */
3702     delete finisher;
3703   }
3704   if (meta_notifier) {
3705     meta_notifier->stop();
3706     delete meta_notifier;
3707   }
3708   if (data_notifier) {
3709     data_notifier->stop();
3710     delete data_notifier;
3711   }
3712   delete data_log;
3713   if (async_rados) {
3714     delete async_rados;
3715   }
3716   
3717   delete lc;
3718   lc = NULL; 
3719
3720   delete gc;
3721   gc = NULL;
3722
3723   delete obj_expirer;
3724   obj_expirer = NULL;
3725
3726   delete rest_master_conn;
3727
3728   map<string, RGWRESTConn *>::iterator iter;
3729   for (iter = zone_conn_map.begin(); iter != zone_conn_map.end(); ++iter) {
3730     RGWRESTConn *conn = iter->second;
3731     delete conn;
3732   }
3733
3734   for (iter = zonegroup_conn_map.begin(); iter != zonegroup_conn_map.end(); ++iter) {
3735     RGWRESTConn *conn = iter->second;
3736     delete conn;
3737   }
3738   RGWQuotaHandler::free_handler(quota_handler);
3739   if (cr_registry) {
3740     cr_registry->put();
3741   }
3742   delete meta_mgr;
3743   delete binfo_cache;
3744   delete obj_tombstone_cache;
3745   delete sync_modules_manager;
3746
3747   if (reshard_wait.get()) {
3748     reshard_wait->stop();
3749     reshard_wait.reset();
3750   }
3751
3752   if (run_reshard_thread) {
3753     reshard->stop_processor();
3754   }
3755   delete reshard;
3756   delete index_completion_manager;
3757 }
3758
3759 /** 
3760  * Initialize the RADOS instance and prepare to do other ops
3761  * Returns 0 on success, -ERR# on failure.
3762  */
3763 int RGWRados::init_rados()
3764 {
3765   int ret = 0;
3766   auto handles = std::vector<librados::Rados>{cct->_conf->rgw_num_rados_handles};
3767
3768   for (auto& r : handles) {
3769     ret = r.init_with_context(cct);
3770     if (ret < 0) {
3771       return ret;
3772     }
3773     ret = r.connect();
3774     if (ret < 0) {
3775       return ret;
3776     }
3777   }
3778
3779   sync_modules_manager = new RGWSyncModulesManager();
3780
3781   rgw_register_sync_modules(sync_modules_manager);
3782
3783   auto crs = std::unique_ptr<RGWCoroutinesManagerRegistry>{
3784     new RGWCoroutinesManagerRegistry(cct)};
3785   ret = crs->hook_to_admin_command("cr dump");
3786   if (ret < 0) {
3787     return ret;
3788   }
3789
3790   meta_mgr = new RGWMetadataManager(cct, this);
3791   data_log = new RGWDataChangesLog(cct, this);
3792   cr_registry = crs.release();
3793
3794   std::swap(handles, rados);
3795   return ret;
3796 }
3797
3798
3799 int RGWRados::register_to_service_map(const string& daemon_type, const map<string, string>& meta)
3800 {
3801   map<string,string> metadata = meta;
3802   metadata["num_handles"] = stringify(rados.size());
3803   metadata["zonegroup_id"] = zonegroup.get_id();
3804   metadata["zonegroup_name"] = zonegroup.get_name();
3805   metadata["zone_name"] = zone_name();
3806   metadata["zone_id"] = zone_id();;
3807   string name = cct->_conf->name.get_id();
3808   if (name.find("rgw.") == 0) {
3809     name = name.substr(4);
3810   }
3811   int ret = rados[0].service_daemon_register(daemon_type, name, metadata);
3812   if (ret < 0) {
3813     ldout(cct, 0) << "ERROR: service_daemon_register() returned ret=" << ret << ": " << cpp_strerror(-ret) << dendl;
3814     return ret;
3815   }
3816
3817   return 0;
3818 }
3819
3820 /**
3821  * Add new connection to connections map
3822  * @param zonegroup_conn_map map which new connection will be added to
3823  * @param zonegroup zonegroup which new connection will connect to
3824  * @param new_connection pointer to new connection instance
3825  */
3826 static void add_new_connection_to_map(map<string, RGWRESTConn *> &zonegroup_conn_map,
3827                                       const RGWZoneGroup &zonegroup, RGWRESTConn *new_connection)
3828 {
3829   // Delete if connection is already exists
3830   map<string, RGWRESTConn *>::iterator iterZoneGroup = zonegroup_conn_map.find(zonegroup.get_id());
3831   if (iterZoneGroup != zonegroup_conn_map.end()) {
3832     delete iterZoneGroup->second;
3833   }
3834     
3835   // Add new connection to connections map
3836   zonegroup_conn_map[zonegroup.get_id()] = new_connection;
3837 }
3838
3839 int RGWRados::convert_regionmap()
3840 {
3841   RGWZoneGroupMap zonegroupmap;
3842
3843   string pool_name = cct->_conf->rgw_zone_root_pool;
3844   if (pool_name.empty()) {
3845     pool_name = RGW_DEFAULT_ZONE_ROOT_POOL;
3846   }
3847   string oid = region_map_oid; 
3848
3849   rgw_pool pool(pool_name);
3850   bufferlist bl;
3851   RGWObjectCtx obj_ctx(this);
3852   int ret = rgw_get_system_obj(this, obj_ctx, pool, oid, bl, NULL, NULL);
3853   if (ret < 0 && ret != -ENOENT) {
3854     return ret;
3855   } else if (ret == -ENOENT) {
3856     return 0;
3857   }
3858
3859   try {
3860     bufferlist::iterator iter = bl.begin();
3861     ::decode(zonegroupmap, iter);
3862   } catch (buffer::error& err) {
3863     ldout(cct, 0) << "error decoding regionmap from " << pool << ":" << oid << dendl;
3864     return -EIO;
3865   }
3866   
3867   for (map<string, RGWZoneGroup>::iterator iter = zonegroupmap.zonegroups.begin();
3868        iter != zonegroupmap.zonegroups.end(); ++iter) {
3869     RGWZoneGroup& zonegroup = iter->second;
3870     ret = zonegroup.init(cct, this, false);
3871     ret = zonegroup.update();
3872     if (ret < 0 && ret != -ENOENT) {
3873       ldout(cct, 0) << "Error could not update zonegroup " << zonegroup.get_name() << ": " <<
3874         cpp_strerror(-ret) << dendl;
3875       return ret;
3876     } else if (ret == -ENOENT) {
3877       ret = zonegroup.create();
3878       if (ret < 0) {
3879         ldout(cct, 0) << "Error could not create " << zonegroup.get_name() << ": " <<
3880           cpp_strerror(-ret) << dendl;
3881         return ret;
3882       }
3883     }
3884   }
3885
3886   current_period.set_user_quota(zonegroupmap.user_quota);
3887   current_period.set_bucket_quota(zonegroupmap.bucket_quota);
3888
3889   // remove the region_map so we don't try to convert again
3890   rgw_raw_obj obj(pool, oid);
3891   ret = delete_system_obj(obj);
3892   if (ret < 0) {
3893     ldout(cct, 0) << "Error could not remove " << obj
3894         << " after upgrading to zonegroup map: " << cpp_strerror(ret) << dendl;
3895     return ret;
3896   }
3897
3898   return 0;
3899 }
3900
3901 /** 
3902  * Replace all region configuration with zonegroup for
3903  * backward compatability
3904  * Returns 0 on success, -ERR# on failure.
3905  */
3906 int RGWRados::replace_region_with_zonegroup()
3907 {
3908   /* copy default region */
3909   /* convert default region to default zonegroup */
3910   string default_oid = cct->_conf->rgw_default_region_info_oid;
3911   if (default_oid.empty()) {
3912     default_oid = default_region_info_oid;
3913   }
3914
3915
3916   RGWZoneGroup default_zonegroup;
3917   rgw_pool pool{default_zonegroup.get_pool(cct)};
3918   string oid  = "converted";
3919   bufferlist bl;
3920   RGWObjectCtx obj_ctx(this);
3921
3922   int ret = rgw_get_system_obj(this, obj_ctx, pool ,oid, bl, NULL,  NULL);
3923   if (ret < 0 && ret !=  -ENOENT) {
3924     ldout(cct, 0) << __func__ << " failed to read converted: ret "<< ret << " " << cpp_strerror(-ret)
3925                   << dendl;
3926     return ret;
3927   } else if (ret != -ENOENT) {
3928     ldout(cct, 20) << "System already converted " << dendl;
3929     return 0;
3930   }
3931
3932   string default_region;
3933   ret = default_zonegroup.init(cct, this, false, true);
3934   if (ret < 0) {
3935     ldout(cct, 0) <<  __func__ << " failed init default region: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
3936     return ret;
3937   }    
3938   ret  = default_zonegroup.read_default_id(default_region, true);
3939   if (ret < 0 && ret != -ENOENT) {
3940     ldout(cct, 0) <<  __func__ << " failed reading old default region: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
3941     return ret;
3942   }
3943
3944   /* convert regions to zonegroups */
3945   list<string> regions;
3946   ret = list_regions(regions);
3947   if (ret < 0 && ret != -ENOENT) {
3948     ldout(cct, 0) <<  __func__ << " failed to list regions: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
3949     return ret;
3950   } else if (ret == -ENOENT || regions.empty()) {
3951     RGWZoneParams zoneparams(default_zone_name);
3952     int ret = zoneparams.init(cct, this);
3953     if (ret < 0 && ret != -ENOENT) {
3954       ldout(cct, 0) << __func__ << ": error initializing default zone params: " << cpp_strerror(-ret) << dendl;
3955       return ret;
3956     }
3957     /* update master zone */
3958     RGWZoneGroup default_zg(default_zonegroup_name);
3959     ret = default_zg.init(cct, this);
3960     if (ret < 0 && ret != -ENOENT) {
3961       ldout(cct, 0) << __func__ << ": error in initializing default zonegroup: " << cpp_strerror(-ret) << dendl;
3962       return ret;
3963     }
3964     if (ret != -ENOENT && default_zg.master_zone.empty()) {
3965       default_zg.master_zone = zoneparams.get_id();
3966       return default_zg.update();
3967     }
3968     return 0;
3969   }
3970
3971   string master_region, master_zone;
3972   for (list<string>::iterator iter = regions.begin(); iter != regions.end(); ++iter) {
3973     if (*iter != default_zonegroup_name){
3974       RGWZoneGroup region(*iter);
3975       int ret = region.init(cct, this, true, true);
3976       if (ret < 0) {
3977           ldout(cct, 0) <<  __func__ << " failed init region "<< *iter << ": " << cpp_strerror(-ret) << dendl;
3978           return ret;
3979       }
3980       if (region.is_master_zonegroup()) {
3981         master_region = region.get_id();
3982         master_zone = region.master_zone;
3983       }
3984     }
3985   }
3986
3987   /* create realm if there is none.
3988      The realm name will be the region and zone concatenated
3989      realm id will be mds of its name */
3990   if (realm.get_id().empty() && !master_region.empty() && !master_zone.empty()) {
3991     string new_realm_name = master_region + "." + master_zone;
3992     unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE];
3993     char md5_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
3994     MD5 hash;
3995     hash.Update((const byte *)new_realm_name.c_str(), new_realm_name.length());
3996     hash.Final(md5);
3997     buf_to_hex(md5, CEPH_CRYPTO_MD5_DIGESTSIZE, md5_str);
3998     string new_realm_id(md5_str);
3999     RGWRealm new_realm(new_realm_id,new_realm_name);
4000     ret = new_realm.init(cct, this, false);
4001     if (ret < 0) {
4002       ldout(cct, 0) <<  __func__ << " Error initing new realm: " << cpp_strerror(-ret)  << dendl;
4003       return ret;
4004     }
4005     ret = new_realm.create();
4006     if (ret < 0 && ret != -EEXIST) {
4007       ldout(cct, 0) <<  __func__ << " Error creating new realm: " << cpp_strerror(-ret)  << dendl;
4008       return ret;
4009     }
4010     ret = new_realm.set_as_default();
4011     if (ret < 0) {
4012       ldout(cct, 0) << __func__ << " Error setting realm as default: " << cpp_strerror(-ret)  << dendl;
4013       return ret;
4014     }
4015     ret = realm.init(cct, this);
4016     if (ret < 0) {
4017       ldout(cct, 0) << __func__ << " Error initing realm: " << cpp_strerror(-ret)  << dendl;
4018       return ret;
4019     }
4020     ret = current_period.init(cct, this, realm.get_id(), realm.get_name());
4021     if (ret < 0) {
4022       ldout(cct, 0) << __func__ << " Error initing current period: " << cpp_strerror(-ret)  << dendl;
4023       return ret;
4024     }
4025   }
4026
4027   list<string>::iterator iter;
4028   /* create zonegroups */
4029   for (iter = regions.begin(); iter != regions.end(); ++iter)
4030   {
4031     ldout(cct, 0) << __func__ << "Converting  " << *iter << dendl;
4032     /* check to see if we don't have already a zonegroup with this name */
4033     RGWZoneGroup new_zonegroup(*iter);
4034     ret = new_zonegroup.init(cct , this);
4035     if (ret == 0 && new_zonegroup.get_id() != *iter) {
4036       ldout(cct, 0) << __func__ << " zonegroup  "<< *iter << " already exists id " << new_zonegroup.get_id () <<
4037         " skipping conversion " << dendl;
4038       continue;
4039     }
4040     RGWZoneGroup zonegroup(*iter);
4041     zonegroup.set_id(*iter);
4042     int ret = zonegroup.init(cct, this, true, true);
4043     if (ret < 0) {
4044       ldout(cct, 0) << __func__ << " failed init zonegroup: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
4045       return ret;
4046     }
4047     zonegroup.realm_id = realm.get_id();
4048     /* fix default region master zone */
4049     if (*iter == default_zonegroup_name && zonegroup.master_zone.empty()) {
4050       ldout(cct, 0) << __func__ << " Setting default zone as master for default region" << dendl;
4051       zonegroup.master_zone = default_zone_name;
4052     }
4053     ret = zonegroup.update();
4054     if (ret < 0 && ret != -EEXIST) {
4055       ldout(cct, 0) << __func__ << " failed to update zonegroup " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret)
4056         << dendl;
4057       return ret;
4058     }
4059     ret = zonegroup.update_name();
4060     if (ret < 0 && ret != -EEXIST) {
4061       ldout(cct, 0) << __func__ << " failed to update_name for zonegroup " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret)
4062         << dendl;
4063       return ret;
4064     }
4065     if (zonegroup.get_name() == default_region) {
4066       ret = zonegroup.set_as_default();
4067       if (ret < 0) {
4068         ldout(cct, 0) << __func__ << " failed to set_as_default " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret)
4069           << dendl;
4070         return ret;
4071       }
4072     }
4073     for (map<string, RGWZone>::const_iterator iter = zonegroup.zones.begin(); iter != zonegroup.zones.end();
4074          ++iter) {
4075       ldout(cct, 0) << __func__ << " Converting zone" << iter->first << dendl;
4076       RGWZoneParams zoneparams(iter->first, iter->first);
4077       zoneparams.set_id(iter->first);
4078       zoneparams.realm_id = realm.get_id();
4079       ret = zoneparams.init(cct, this);
4080       if (ret < 0 && ret != -ENOENT) {
4081         ldout(cct, 0) << __func__ << " failed to init zoneparams  " << iter->first <<  ": " << cpp_strerror(-ret) << dendl;
4082         return ret;
4083       } else if (ret == -ENOENT) {
4084         ldout(cct, 0) << __func__ << " zone is part of another cluster " << iter->first <<  " skipping " << dendl;
4085         continue;
4086       }
4087       zonegroup.realm_id = realm.get_id();
4088       ret = zoneparams.update();
4089       if (ret < 0 && ret != -EEXIST) {
4090         ldout(cct, 0) << __func__ << " failed to update zoneparams " << iter->first <<  ": " << cpp_strerror(-ret) << dendl;
4091         return ret;
4092       }
4093       ret = zoneparams.update_name();
4094       if (ret < 0 && ret != -EEXIST) {
4095         ldout(cct, 0) << __func__ << " failed to init zoneparams " << iter->first <<  ": " << cpp_strerror(-ret) << dendl;
4096         return ret;
4097       }
4098     }
4099
4100     if (!current_period.get_id().empty()) {
4101       ret = current_period.add_zonegroup(zonegroup);
4102       if (ret < 0) {
4103         ldout(cct, 0) << __func__ << " failed to add zonegroup to current_period: " << cpp_strerror(-ret) << dendl;
4104         return ret;
4105       }
4106     }
4107   }
4108
4109   if (!current_period.get_id().empty()) {
4110     ret = current_period.update();
4111     if (ret < 0) {
4112       ldout(cct, 0) << __func__ << " failed to update new period: " << cpp_strerror(-ret) << dendl;
4113       return ret;
4114     }
4115     ret = current_period.store_info(false);
4116     if (ret < 0) {
4117       ldout(cct, 0) << __func__ << " failed to store new period: " << cpp_strerror(-ret) << dendl;
4118       return ret;
4119     }
4120     ret = current_period.reflect();
4121     if (ret < 0) {
4122       ldout(cct, 0) << __func__ << " failed to update local objects: " << cpp_strerror(-ret) << dendl;
4123       return ret;
4124     }
4125   }
4126
4127   for (auto const& iter : regions) {
4128     RGWZoneGroup zonegroup(iter);
4129     int ret = zonegroup.init(cct, this, true, true);
4130     if (ret < 0) {
4131       ldout(cct, 0) << __func__ << " failed init zonegroup" << iter << ": ret "<< ret << " " << cpp_strerror(-ret) << dendl;
4132       return ret;
4133     }
4134     ret = zonegroup.delete_obj(true);
4135     if (ret < 0 && ret != -ENOENT) {
4136       ldout(cct, 0) << __func__ << " failed to delete region " << iter << ": ret "<< ret << " " << cpp_strerror(-ret)
4137         << dendl;
4138       return ret;
4139     }
4140   }
4141
4142   /* mark as converted */
4143   ret = rgw_put_system_obj(this, pool, oid, bl.c_str(), bl.length(),
4144                            true, NULL, real_time(), NULL);
4145   if (ret < 0 ) {
4146     ldout(cct, 0) << __func__ << " failed to mark cluster as converted: ret "<< ret << " " << cpp_strerror(-ret)
4147                   << dendl;
4148     return ret;
4149   }
4150
4151   return 0;
4152 }
4153
4154 int RGWRados::init_zg_from_period(bool *initialized)
4155 {
4156   *initialized = false;
4157
4158   if (current_period.get_id().empty()) {
4159     return 0;
4160   }
4161
4162   int ret = zonegroup.init(cct, this);
4163   ldout(cct, 20) << "period zonegroup init ret " << ret << dendl;
4164   if (ret == -ENOENT) {
4165     return 0;
4166   }
4167   if (ret < 0) {
4168     ldout(cct, 0) << "failed reading zonegroup info: " << cpp_strerror(-ret) << dendl;
4169     return ret;
4170   }
4171   ldout(cct, 20) << "period zonegroup name " << zonegroup.get_name() << dendl;
4172
4173   map<string, RGWZoneGroup>::const_iterator iter =
4174     current_period.get_map().zonegroups.find(zonegroup.get_id());
4175
4176   if (iter != current_period.get_map().zonegroups.end()) {
4177     ldout(cct, 20) << "using current period zonegroup " << zonegroup.get_name() << dendl;
4178     zonegroup = iter->second;
4179     ret = zonegroup.init(cct, this, false);
4180     if (ret < 0) {
4181       ldout(cct, 0) << "failed init zonegroup: " << " " << cpp_strerror(-ret) << dendl;
4182       return ret;
4183     }
4184     ret = zone_params.init(cct, this);
4185     if (ret < 0 && ret != -ENOENT) {
4186       ldout(cct, 0) << "failed reading zone params info: " << " " << cpp_strerror(-ret) << dendl;
4187       return ret;
4188     } if (ret ==-ENOENT && zonegroup.get_name() == default_zonegroup_name) {
4189       ldout(cct, 10) << " Using default name "<< default_zone_name << dendl;
4190       zone_params.set_name(default_zone_name);
4191       ret = zone_params.init(cct, this);
4192       if (ret < 0 && ret != -ENOENT) {
4193        ldout(cct, 0) << "failed reading zone params info: " << " " << cpp_strerror(-ret) << dendl;
4194        return ret;
4195       }
4196     }
4197   }
4198   for (iter = current_period.get_map().zonegroups.begin();
4199        iter != current_period.get_map().zonegroups.end(); ++iter){
4200     const RGWZoneGroup& zg = iter->second;
4201     // use endpoints from the zonegroup's master zone
4202     auto master = zg.zones.find(zg.master_zone);
4203     if (master == zg.zones.end()) {
4204       // fix missing master zone for a single zone zonegroup
4205       if (zg.master_zone.empty() && zg.zones.size() == 1) {
4206         master = zg.zones.begin();
4207         ldout(cct, 0) << "zonegroup " << zg.get_name() << " missing master_zone, setting zone " <<
4208           master->second.name << " id:" << master->second.id << " as master" << dendl;
4209         if (zonegroup.get_id() == zg.get_id()) {
4210           zonegroup.master_zone = master->second.id;
4211           ret = zonegroup.update();
4212           if (ret < 0) {
4213             ldout(cct, 0) << "error updating zonegroup : " << cpp_strerror(-ret) << dendl;
4214             return ret;
4215           }
4216         } else {
4217           RGWZoneGroup fixed_zg(zg.get_id(),zg.get_name());
4218           ret = fixed_zg.init(cct, this);
4219           if (ret < 0) {
4220             ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl;
4221             return ret;
4222           }
4223           fixed_zg.master_zone = master->second.id;
4224           ret = fixed_zg.update();
4225           if (ret < 0) {
4226             ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl;
4227             return ret;
4228           }
4229         }
4230       } else {
4231         ldout(cct, 0) << "zonegroup " << zg.get_name() << " missing zone for master_zone=" <<
4232           zg.master_zone << dendl;
4233         return -EINVAL;
4234       }
4235     }
4236     const auto& endpoints = master->second.endpoints;
4237     add_new_connection_to_map(zonegroup_conn_map, zg, new RGWRESTConn(cct, this, zg.get_id(), endpoints));
4238     if (!current_period.get_master_zonegroup().empty() &&
4239         zg.get_id() == current_period.get_master_zonegroup()) {
4240       rest_master_conn = new RGWRESTConn(cct, this, zg.get_id(), endpoints);
4241     }
4242   }
4243
4244   *initialized = true;
4245
4246   return 0;
4247 }
4248
4249 int RGWRados::init_zg_from_local(bool *creating_defaults)
4250 {
4251   int ret = zonegroup.init(cct, this);
4252   if ( (ret < 0 && ret != -ENOENT) || (ret == -ENOENT && !cct->_conf->rgw_zonegroup.empty())) {
4253     ldout(cct, 0) << "failed reading zonegroup info: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
4254     return ret;
4255   } else if (ret == -ENOENT) {
4256     *creating_defaults = true;
4257     ldout(cct, 10) << "Creating default zonegroup " << dendl;
4258     ret = zonegroup.create_default();
4259     if (ret < 0) {
4260       ldout(cct, 0) << "failure in zonegroup create_default: ret "<< ret << " " << cpp_strerror(-ret)
4261         << dendl;
4262       return ret;
4263     }
4264     ret = zonegroup.init(cct, this);
4265     if (ret < 0) {
4266       ldout(cct, 0) << "failure in zonegroup create_default: ret "<< ret << " " << cpp_strerror(-ret)
4267         << dendl;
4268       return ret;
4269     }
4270   }
4271   ldout(cct, 20) << "zonegroup " << zonegroup.get_name() << dendl;
4272   if (zonegroup.is_master_zonegroup()) {
4273     // use endpoints from the zonegroup's master zone
4274     auto master = zonegroup.zones.find(zonegroup.master_zone);
4275     if (master == zonegroup.zones.end()) {
4276       // fix missing master zone for a single zone zonegroup
4277       if (zonegroup.master_zone.empty() && zonegroup.zones.size() == 1) {
4278         master = zonegroup.zones.begin();
4279         ldout(cct, 0) << "zonegroup " << zonegroup.get_name() << " missing master_zone, setting zone " <<
4280           master->second.name << " id:" << master->second.id << " as master" << dendl;
4281         zonegroup.master_zone = master->second.id;
4282         ret = zonegroup.update();
4283         if (ret < 0) {
4284           ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl;
4285           return ret;
4286         }
4287       } else {
4288         ldout(cct, 0) << "zonegroup " << zonegroup.get_name() << " missing zone for "
4289           "master_zone=" << zonegroup.master_zone << dendl;
4290         return -EINVAL;
4291       }
4292     }
4293     const auto& endpoints = master->second.endpoints;
4294     rest_master_conn = new RGWRESTConn(cct, this, zonegroup.get_id(), endpoints);
4295   }
4296
4297   return 0;
4298 }
4299
4300
4301 bool RGWRados::zone_syncs_from(RGWZone& target_zone, RGWZone& source_zone)
4302 {
4303   return target_zone.syncs_from(source_zone.name) &&
4304          sync_modules_manager->supports_data_export(source_zone.tier_type);
4305 }
4306
4307 /** 
4308  * Initialize the RADOS instance and prepare to do other ops
4309  * Returns 0 on success, -ERR# on failure.
4310  */
4311 int RGWRados::init_complete()
4312 {
4313   int ret = realm.init(cct, this);
4314   if (ret < 0 && ret != -ENOENT) {
4315     ldout(cct, 0) << "failed reading realm info: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
4316     return ret;
4317   } else if (ret != -ENOENT) {
4318     ldout(cct, 20) << "realm  " << realm.get_name() << " " << realm.get_id() << dendl;
4319     ret = current_period.init(cct, this, realm.get_id(), realm.get_name());
4320     if (ret < 0 && ret != -ENOENT) {
4321       ldout(cct, 0) << "failed reading current period info: " << " " << cpp_strerror(-ret) << dendl;
4322       return ret;
4323     }
4324     ldout(cct, 20) << "current period " << current_period.get_id() << dendl;  
4325   }
4326
4327   ret = replace_region_with_zonegroup();
4328   if (ret < 0) {
4329     lderr(cct) << "failed converting region to zonegroup : ret "<< ret << " " << cpp_strerror(-ret) << dendl;
4330     return ret;
4331   }
4332
4333   ret = convert_regionmap();
4334   if (ret < 0) {
4335     lderr(cct) << "failed converting regionmap: " << cpp_strerror(-ret) << dendl;
4336     return ret;
4337   }
4338
4339   bool zg_initialized = false;
4340
4341   if (!current_period.get_id().empty()) {
4342     ret = init_zg_from_period(&zg_initialized);
4343     if (ret < 0) {
4344       return ret;
4345     }
4346   }
4347
4348   bool creating_defaults = false;
4349   bool using_local = (!zg_initialized);
4350   if (using_local) {
4351     ldout(cct, 10) << " cannot find current period zonegroup using local zonegroup" << dendl;
4352     ret = init_zg_from_local(&creating_defaults);
4353     if (ret < 0) {
4354       return ret;
4355     }
4356     // read period_config into current_period
4357     auto& period_config = current_period.get_config();
4358     ret = period_config.read(this, zonegroup.realm_id);
4359     if (ret < 0 && ret != -ENOENT) {
4360       ldout(cct, 0) << "ERROR: failed to read period config: "
4361           << cpp_strerror(ret) << dendl;
4362       return ret;
4363     }
4364   }
4365
4366   ldout(cct, 10) << "Cannot find current period zone using local zone" << dendl;
4367   if (creating_defaults && cct->_conf->rgw_zone.empty()) {
4368     ldout(cct, 10) << " Using default name "<< default_zone_name << dendl;
4369     zone_params.set_name(default_zone_name);
4370   }
4371
4372   ret = zone_params.init(cct, this);
4373   if (ret < 0 && ret != -ENOENT) {
4374     lderr(cct) << "failed reading zone info: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
4375     return ret;
4376   }
4377   map<string, RGWZone>::iterator zone_iter = get_zonegroup().zones.find(zone_params.get_id());
4378   if (zone_iter == get_zonegroup().zones.end()) {
4379     if (using_local) {
4380       lderr(cct) << "Cannot find zone id=" << zone_params.get_id() << " (name=" << zone_params.get_name() << ")" << dendl;
4381       return -EINVAL;
4382     }
4383     ldout(cct, 1) << "Cannot find zone id=" << zone_params.get_id() << " (name=" << zone_params.get_name() << "), switching to local zonegroup configuration" << dendl;
4384     ret = init_zg_from_local(&creating_defaults);
4385     if (ret < 0) {
4386       return ret;
4387     }
4388     zone_iter = get_zonegroup().zones.find(zone_params.get_id());
4389   }
4390   if (zone_iter != get_zonegroup().zones.end()) {
4391     zone_public_config = zone_iter->second;
4392     ldout(cct, 20) << "zone " << zone_params.get_name() << dendl;
4393   } else {
4394     lderr(cct) << "Cannot find zone id=" << zone_params.get_id() << " (name=" << zone_params.get_name() << ")" << dendl;
4395     return -EINVAL;
4396   }
4397
4398   zone_short_id = current_period.get_map().get_zone_short_id(zone_params.get_id());
4399
4400   if (run_sync_thread) {
4401     ret = sync_modules_manager->create_instance(cct, zone_public_config.tier_type, zone_params.tier_config, &sync_module);
4402     if (ret < 0) {
4403       lderr(cct) << "ERROR: failed to init sync module instance, ret=" << ret << dendl;
4404       return ret;
4405     }
4406   }
4407
4408   writeable_zone = (zone_public_config.tier_type.empty() || zone_public_config.tier_type == "rgw");
4409
4410   init_unique_trans_id_deps();
4411
4412   finisher = new Finisher(cct);
4413   finisher->start();
4414
4415   period_puller.reset(new RGWPeriodPuller(this));
4416   period_history.reset(new RGWPeriodHistory(cct, period_puller.get(),
4417                                             current_period));
4418
4419   if (need_watch_notify()) {
4420     ret = init_watch();
4421     if (ret < 0) {
4422       lderr(cct) << "ERROR: failed to initialize watch: " << cpp_strerror(-ret) << dendl;
4423       return ret;
4424     }
4425   }
4426
4427   /* first build all zones index */
4428   for (auto ziter : get_zonegroup().zones) {
4429     const string& id = ziter.first;
4430     RGWZone& z = ziter.second;
4431     zone_id_by_name[z.name] = id;
4432     zone_by_id[id] = z;
4433   }
4434
4435   if (zone_by_id.find(zone_id()) == zone_by_id.end()) {
4436     ldout(cct, 0) << "WARNING: could not find zone config in zonegroup for local zone (" << zone_id() << "), will use defaults" << dendl;
4437   }
4438   zone_public_config = zone_by_id[zone_id()];
4439   for (auto ziter : get_zonegroup().zones) {
4440     const string& id = ziter.first;
4441     RGWZone& z = ziter.second;
4442     if (id == zone_id()) {
4443       continue;
4444     }
4445     if (z.endpoints.empty()) {
4446       ldout(cct, 0) << "WARNING: can't generate connection for zone " << z.id << " id " << z.name << ": no endpoints defined" << dendl;
4447       continue;
4448     }
4449     ldout(cct, 20) << "generating connection object for zone " << z.name << " id " << z.id << dendl;
4450     RGWRESTConn *conn = new RGWRESTConn(cct, this, z.id, z.endpoints);
4451     zone_conn_map[id] = conn;
4452     if (zone_syncs_from(zone_public_config, z) ||
4453         zone_syncs_from(z, zone_public_config)) {
4454       if (zone_syncs_from(zone_public_config, z)) {
4455         zone_data_sync_from_map[id] = conn;
4456       }
4457       if (zone_syncs_from(z, zone_public_config)) {
4458         zone_data_notify_to_map[id] = conn;
4459       }
4460     } else {
4461       ldout(cct, 20) << "NOTICE: not syncing to/from zone " << z.name << " id " << z.id << dendl;
4462     }
4463   }
4464
4465   ret = open_root_pool_ctx();
4466   if (ret < 0)
4467     return ret;
4468
4469   ret = open_gc_pool_ctx();
4470   if (ret < 0)
4471     return ret;
4472
4473   ret = open_lc_pool_ctx();
4474   if (ret < 0)
4475     return ret;
4476
4477   ret = open_objexp_pool_ctx();
4478   if (ret < 0)
4479     return ret;
4480
4481   ret = open_reshard_pool_ctx();
4482   if (ret < 0)
4483     return ret;
4484
4485   pools_initialized = true;
4486
4487   gc = new RGWGC();
4488   gc->initialize(cct, this);
4489
4490   obj_expirer = new RGWObjectExpirer(this);
4491
4492   if (use_gc_thread) {
4493     gc->start_processor();
4494     obj_expirer->start_processor();
4495   }
4496
4497   if (run_sync_thread) {
4498     // initialize the log period history. we want to do this any time we're not
4499     // running under radosgw-admin, so we check run_sync_thread here before
4500     // disabling it based on the zone/zonegroup setup
4501     meta_mgr->init_oldest_log_period();
4502   }
4503
4504   /* no point of running sync thread if we don't have a master zone configured
4505     or there is no rest_master_conn */
4506   if (get_zonegroup().master_zone.empty() || !rest_master_conn
4507       || current_period.get_id().empty()) {
4508     run_sync_thread = false;
4509   }
4510
4511   async_rados = new RGWAsyncRadosProcessor(this, cct->_conf->rgw_num_async_rados_threads);
4512   async_rados->start();
4513
4514   ret = meta_mgr->init(current_period.get_id());
4515   if (ret < 0) {
4516     lderr(cct) << "ERROR: failed to initialize metadata log: "
4517         << cpp_strerror(-ret) << dendl;
4518     return ret;
4519   }
4520
4521   if (is_meta_master()) {
4522     auto md_log = meta_mgr->get_log(current_period.get_id());
4523     meta_notifier = new RGWMetaNotifier(this, md_log);
4524     meta_notifier->start();
4525   }
4526
4527   if (run_sync_thread) {
4528     Mutex::Locker l(meta_sync_thread_lock);
4529     meta_sync_processor_thread = new RGWMetaSyncProcessorThread(this, async_rados);
4530     ret = meta_sync_processor_thread->init();
4531     if (ret < 0) {
4532       ldout(cct, 0) << "ERROR: failed to initialize meta sync thread" << dendl;
4533       return ret;
4534     }
4535     meta_sync_processor_thread->start();
4536
4537     Mutex::Locker dl(data_sync_thread_lock);
4538     for (auto iter : zone_data_sync_from_map) {
4539       ldout(cct, 5) << "starting data sync thread for zone " << iter.first << dendl;
4540       RGWDataSyncProcessorThread *thread = new RGWDataSyncProcessorThread(this, async_rados, iter.first);
4541       ret = thread->init();
4542       if (ret < 0) {
4543         ldout(cct, 0) << "ERROR: failed to initialize data sync thread" << dendl;
4544         return ret;
4545       }
4546       thread->start();
4547       data_sync_processor_threads[iter.first] = thread;
4548     }
4549     auto interval = cct->_conf->rgw_sync_log_trim_interval;
4550     if (interval > 0) {
4551       sync_log_trimmer = new RGWSyncLogTrimThread(this, interval);
4552       ret = sync_log_trimmer->init();
4553       if (ret < 0) {
4554         ldout(cct, 0) << "ERROR: failed to initialize sync log trim thread" << dendl;
4555         return ret;
4556       }
4557       sync_log_trimmer->start();
4558     }
4559   }
4560   data_notifier = new RGWDataNotifier(this);
4561   data_notifier->start();
4562
4563   lc = new RGWLC();
4564   lc->initialize(cct, this);
4565
4566   if (use_lc_thread)
4567     lc->start_processor();
4568
4569   quota_handler = RGWQuotaHandler::generate_handler(this, quota_threads);
4570
4571   bucket_index_max_shards = (cct->_conf->rgw_override_bucket_index_max_shards ? cct->_conf->rgw_override_bucket_index_max_shards :
4572                              get_zone().bucket_index_max_shards);
4573   if (bucket_index_max_shards > get_max_bucket_shards()) {
4574     bucket_index_max_shards = get_max_bucket_shards();
4575     ldout(cct, 1) << __func__ << " bucket index max shards is too large, reset to value: "
4576       << get_max_bucket_shards() << dendl;
4577   }
4578   ldout(cct, 20) << __func__ << " bucket index max shards: " << bucket_index_max_shards << dendl;
4579
4580   binfo_cache = new RGWChainedCacheImpl<bucket_info_entry>;
4581   binfo_cache->init(this);
4582
4583   bool need_tombstone_cache = !zone_data_notify_to_map.empty(); /* have zones syncing from us */
4584
4585   if (need_tombstone_cache) {
4586     obj_tombstone_cache = new tombstone_cache_t(cct->_conf->rgw_obj_tombstone_cache_size);
4587   }
4588
4589   reshard_wait = std::make_shared<RGWReshardWait>(this);
4590
4591   reshard = new RGWReshard(this);
4592
4593   /* only the master zone in the zonegroup reshards buckets */
4594   run_reshard_thread = run_reshard_thread && (get_zonegroup().master_zone == zone_public_config.id);
4595   if (run_reshard_thread)  {
4596     reshard->start_processor();
4597   }
4598
4599   index_completion_manager = new RGWIndexCompletionManager(this);
4600   ret = index_completion_manager->start();
4601
4602   return ret;
4603 }
4604
4605 /** 
4606  * Initialize the RADOS instance and prepare to do other ops
4607  * Returns 0 on success, -ERR# on failure.
4608  */
4609 int RGWRados::initialize()
4610 {
4611   int ret;
4612
4613   ret = init_rados();
4614   if (ret < 0)
4615     return ret;
4616
4617   return init_complete();
4618 }
4619
4620 void RGWRados::finalize_watch()
4621 {
4622   for (int i = 0; i < num_watchers; i++) {
4623     RGWWatcher *watcher = watchers[i];
4624     watcher->unregister_watch();
4625     delete watcher;
4626   }
4627
4628   delete[] notify_oids;
4629   delete[] watchers;
4630 }
4631
4632 void RGWRados::schedule_context(Context *c) {
4633   finisher->queue(c);
4634 }
4635
4636 int RGWRados::list_raw_prefixed_objs(const rgw_pool& pool, const string& prefix, list<string>& result)
4637 {
4638   bool is_truncated;
4639   RGWListRawObjsCtx ctx;
4640   do {
4641     list<string> oids;
4642     int r = list_raw_objects(pool, prefix, 1000,
4643                              ctx, oids, &is_truncated);
4644     if (r < 0) {
4645       return r;
4646     }
4647     list<string>::iterator iter;
4648     for (iter = oids.begin(); iter != oids.end(); ++iter) {
4649       string& val = *iter;
4650       if (val.size() > prefix.size())
4651         result.push_back(val.substr(prefix.size()));
4652     }
4653   } while (is_truncated);
4654
4655   return 0;
4656 }
4657
4658 int RGWRados::list_regions(list<string>& regions)
4659 {
4660   RGWZoneGroup zonegroup;
4661
4662   return list_raw_prefixed_objs(zonegroup.get_pool(cct), region_info_oid_prefix, regions);
4663 }
4664
4665 int RGWRados::list_zonegroups(list<string>& zonegroups)
4666 {
4667   RGWZoneGroup zonegroup;
4668
4669   return list_raw_prefixed_objs(zonegroup.get_pool(cct), zonegroup_names_oid_prefix, zonegroups);
4670 }
4671
4672 int RGWRados::list_zones(list<string>& zones)
4673 {
4674   RGWZoneParams zoneparams;
4675
4676   return list_raw_prefixed_objs(zoneparams.get_pool(cct), zone_names_oid_prefix, zones);
4677 }
4678
4679 int RGWRados::list_realms(list<string>& realms)
4680 {
4681   RGWRealm realm(cct, this);
4682   return list_raw_prefixed_objs(realm.get_pool(cct), realm_names_oid_prefix, realms);
4683 }
4684
4685 int RGWRados::list_periods(list<string>& periods)
4686 {
4687   RGWPeriod period;
4688   list<string> raw_periods;
4689   int ret = list_raw_prefixed_objs(period.get_pool(cct), period.get_info_oid_prefix(), raw_periods);
4690   if (ret < 0) {
4691     return ret;
4692   }
4693   for (const auto& oid : raw_periods) {
4694     size_t pos = oid.find(".");
4695     if (pos != std::string::npos) {
4696       periods.push_back(oid.substr(0, pos));
4697     } else {
4698       periods.push_back(oid);
4699     }
4700   }
4701   periods.sort(); // unique() only detects duplicates if they're adjacent
4702   periods.unique();
4703   return 0;
4704 }
4705
4706
4707 int RGWRados::list_periods(const string& current_period, list<string>& periods)
4708 {
4709   int ret = 0;
4710   string period_id = current_period;
4711   while(!period_id.empty()) {
4712     RGWPeriod period(period_id);
4713     ret = period.init(cct, this);
4714     if (ret < 0) {
4715       return ret;
4716     }
4717     periods.push_back(period.get_id());
4718     period_id = period.get_predecessor();
4719   }
4720   
4721   return ret;
4722 }
4723
4724 /**
4725  * Open the pool used as root for this gateway
4726  * Returns: 0 on success, -ERR# otherwise.
4727  */
4728 int RGWRados::open_root_pool_ctx()
4729 {
4730   return rgw_init_ioctx(get_rados_handle(), get_zone_params().domain_root, root_pool_ctx, true);
4731 }
4732
4733 int RGWRados::open_gc_pool_ctx()
4734 {
4735   return rgw_init_ioctx(get_rados_handle(), get_zone_params().gc_pool, gc_pool_ctx, true);
4736 }
4737
4738 int RGWRados::open_lc_pool_ctx()
4739 {
4740   return rgw_init_ioctx(get_rados_handle(), get_zone_params().lc_pool, lc_pool_ctx, true);
4741 }
4742
4743 int RGWRados::open_objexp_pool_ctx()
4744 {
4745   return rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, objexp_pool_ctx, true);
4746 }
4747
4748 int RGWRados::open_reshard_pool_ctx()
4749 {
4750   return rgw_init_ioctx(get_rados_handle(), get_zone_params().reshard_pool, reshard_pool_ctx, true);
4751 }
4752
4753 int RGWRados::init_watch()
4754 {
4755   int r = rgw_init_ioctx(&rados[0], get_zone_params().control_pool, control_pool_ctx, true);
4756   if (r < 0) {
4757     return r;
4758   }
4759
4760   num_watchers = cct->_conf->rgw_num_control_oids;
4761
4762   bool compat_oid = (num_watchers == 0);
4763
4764   if (num_watchers <= 0)
4765     num_watchers = 1;
4766
4767   notify_oids = new string[num_watchers];
4768   watchers = new RGWWatcher *[num_watchers];
4769
4770   for (int i=0; i < num_watchers; i++) {
4771     string& notify_oid = notify_oids[i];
4772     notify_oid = notify_oid_prefix;
4773     if (!compat_oid) {
4774       char buf[16];
4775       snprintf(buf, sizeof(buf), ".%d", i);
4776       notify_oid.append(buf);
4777     }
4778     r = control_pool_ctx.create(notify_oid, false);
4779     if (r < 0 && r != -EEXIST)
4780       return r;
4781
4782     RGWWatcher *watcher = new RGWWatcher(this, i, notify_oid);
4783     watchers[i] = watcher;
4784
4785     r = watcher->register_watch();
4786     if (r < 0)
4787       return r;
4788   }
4789
4790   watch_initialized = true;
4791
4792   set_cache_enabled(true);
4793
4794   return 0;
4795 }
4796
4797 void RGWRados::pick_control_oid(const string& key, string& notify_oid)
4798 {
4799   uint32_t r = ceph_str_hash_linux(key.c_str(), key.size());
4800
4801   int i = r % num_watchers;
4802   char buf[16];
4803   snprintf(buf, sizeof(buf), ".%d", i);
4804
4805   notify_oid = notify_oid_prefix;
4806   notify_oid.append(buf);
4807 }
4808
4809 int RGWRados::open_pool_ctx(const rgw_pool& pool, librados::IoCtx&  io_ctx)
4810 {
4811   librados::Rados *rad = get_rados_handle();
4812   int r = rgw_init_ioctx(rad, pool, io_ctx);
4813   if (r != -ENOENT)
4814     return r;
4815
4816   if (!pools_initialized)
4817     return r;
4818
4819   r = rad->pool_create(pool.name.c_str());
4820   if (r < 0 && r != -EEXIST)
4821     return r;
4822
4823   r = rgw_init_ioctx(rad, pool, io_ctx);
4824   if (r < 0)
4825     return r;
4826
4827   r = io_ctx.application_enable(pg_pool_t::APPLICATION_NAME_RGW, false);
4828   if (r < 0 && r != -EOPNOTSUPP)
4829     return r;
4830   return 0;
4831 }
4832
4833 void RGWRados::build_bucket_index_marker(const string& shard_id_str, const string& shard_marker,
4834       string *marker) {
4835   if (marker) {
4836     *marker = shard_id_str;
4837     marker->append(BucketIndexShardsManager::KEY_VALUE_SEPARATOR);
4838     marker->append(shard_marker);
4839   }
4840 }
4841
4842 int RGWRados::open_bucket_index_ctx(const RGWBucketInfo& bucket_info, librados::IoCtx& index_ctx)
4843 {
4844   const string *rule = &bucket_info.placement_rule;
4845   if (rule->empty()) {
4846     rule = &zonegroup.default_placement;
4847   }
4848   auto iter = zone_params.placement_pools.find(*rule);
4849   if (iter == zone_params.placement_pools.end()) {
4850     ldout(cct, 0) << "could not find placement rule " << *rule << " within zonegroup " << dendl;
4851     return -EINVAL;
4852   }
4853
4854   int r = open_pool_ctx(iter->second.index_pool, index_ctx);
4855   if (r < 0)
4856     return r;
4857
4858   return 0;
4859 }
4860
4861 /**
4862  * set up a bucket listing.
4863  * handle is filled in.
4864  * Returns 0 on success, -ERR# otherwise.
4865  */
4866 int RGWRados::list_buckets_init(RGWAccessHandle *handle)
4867 {
4868   librados::NObjectIterator *state = new librados::NObjectIterator(root_pool_ctx.nobjects_begin());
4869   *handle = (RGWAccessHandle)state;
4870   return 0;
4871 }
4872
4873 /** 
4874  * get the next bucket in the listing.
4875  * obj is filled in,
4876  * handle is updated.
4877  * returns 0 on success, -ERR# otherwise.
4878  */
4879 int RGWRados::list_buckets_next(rgw_bucket_dir_entry& obj, RGWAccessHandle *handle)
4880 {
4881   librados::NObjectIterator *state = (librados::NObjectIterator *)*handle;
4882
4883   do {
4884     if (*state == root_pool_ctx.nobjects_end()) {
4885       delete state;
4886       return -ENOENT;
4887     }
4888
4889     obj.key.name = (*state)->get_oid();
4890     if (obj.key.name[0] == '_') {
4891       obj.key.name = obj.key.name.substr(1);
4892     }
4893
4894     (*state)++;
4895   } while (obj.key.name[0] == '.'); /* skip all entries starting with '.' */
4896
4897   return 0;
4898 }
4899
4900
4901 /**** logs ****/
4902
4903 struct log_list_state {
4904   string prefix;
4905   librados::IoCtx io_ctx;
4906   librados::NObjectIterator obit;
4907 };
4908
4909 int RGWRados::log_list_init(const string& prefix, RGWAccessHandle *handle)
4910 {
4911   log_list_state *state = new log_list_state;
4912   int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, state->io_ctx);
4913   if (r < 0) {
4914     delete state;
4915     return r;
4916   }
4917   state->prefix = prefix;
4918   state->obit = state->io_ctx.nobjects_begin();
4919   *handle = (RGWAccessHandle)state;
4920   return 0;
4921 }
4922
4923 int RGWRados::log_list_next(RGWAccessHandle handle, string *name)
4924 {
4925   log_list_state *state = static_cast<log_list_state *>(handle);
4926   while (true) {
4927     if (state->obit == state->io_ctx.nobjects_end()) {
4928       delete state;
4929       return -ENOENT;
4930     }
4931     if (state->prefix.length() &&
4932         state->obit->get_oid().find(state->prefix) != 0) {
4933       state->obit++;
4934       continue;
4935     }
4936     *name = state->obit->get_oid();
4937     state->obit++;
4938     break;
4939   }
4940   return 0;
4941 }
4942
4943 int RGWRados::log_remove(const string& name)
4944 {
4945   librados::IoCtx io_ctx;
4946   int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx);
4947   if (r < 0)
4948     return r;
4949   return io_ctx.remove(name);
4950 }
4951
4952 struct log_show_state {
4953   librados::IoCtx io_ctx;
4954   bufferlist bl;
4955   bufferlist::iterator p;
4956   string name;
4957   uint64_t pos;
4958   bool eof;
4959   log_show_state() : pos(0), eof(false) {}
4960 };
4961
4962 int RGWRados::log_show_init(const string& name, RGWAccessHandle *handle)
4963 {
4964   log_show_state *state = new log_show_state;
4965   int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, state->io_ctx);
4966   if (r < 0) {
4967     delete state;
4968     return r;
4969   }
4970   state->name = name;
4971   *handle = (RGWAccessHandle)state;
4972   return 0;
4973 }
4974
4975 int RGWRados::log_show_next(RGWAccessHandle handle, rgw_log_entry *entry)
4976 {
4977   log_show_state *state = static_cast<log_show_state *>(handle);
4978   off_t off = state->p.get_off();
4979
4980   ldout(cct, 10) << "log_show_next pos " << state->pos << " bl " << state->bl.length()
4981            << " off " << off
4982            << " eof " << (int)state->eof
4983            << dendl;
4984   // read some?
4985   unsigned chunk = 1024*1024;
4986   if ((state->bl.length() - off) < chunk/2 && !state->eof) {
4987     bufferlist more;
4988     int r = state->io_ctx.read(state->name, more, chunk, state->pos);
4989     if (r < 0)
4990       return r;
4991     state->pos += r;
4992     bufferlist old;
4993     try {
4994       old.substr_of(state->bl, off, state->bl.length() - off);
4995     } catch (buffer::error& err) {
4996       return -EINVAL;
4997     }
4998     state->bl.clear();
4999     state->bl.claim(old);
5000     state->bl.claim_append(more);
5001     state->p = state->bl.begin();
5002     if ((unsigned)r < chunk)
5003       state->eof = true;
5004     ldout(cct, 10) << " read " << r << dendl;
5005   }
5006
5007   if (state->p.end())
5008     return 0;  // end of file
5009   try {
5010     ::decode(*entry, state->p);
5011   }
5012   catch (const buffer::error &e) {
5013     return -EINVAL;
5014   }
5015   return 1;
5016 }
5017
5018 /**
5019  * usage_log_hash: get usage log key hash, based on name and index
5020  *
5021  * Get the usage object name. Since a user may have more than 1
5022  * object holding that info (multiple shards), we use index to
5023  * specify that shard number. Once index exceeds max shards it
5024  * wraps.
5025  * If name is not being set, results for all users will be returned
5026  * and index will wrap only after total shards number.
5027  *
5028  * @param cct [in] ceph context
5029  * @param name [in] user name
5030  * @param hash [out] hash value
5031  * @param index [in] shard index number 
5032  */
5033 static void usage_log_hash(CephContext *cct, const string& name, string& hash, uint32_t index)
5034 {
5035   uint32_t val = index;
5036
5037   if (!name.empty()) {
5038     int max_user_shards = cct->_conf->rgw_usage_max_user_shards;
5039     val %= max_user_shards;
5040     val += ceph_str_hash_linux(name.c_str(), name.size());
5041   }
5042   char buf[17];
5043   int max_shards = cct->_conf->rgw_usage_max_shards;
5044   snprintf(buf, sizeof(buf), RGW_USAGE_OBJ_PREFIX "%u", (unsigned)(val % max_shards));
5045   hash = buf;
5046 }
5047
5048 int RGWRados::log_usage(map<rgw_user_bucket, RGWUsageBatch>& usage_info)
5049 {
5050   uint32_t index = 0;
5051
5052   map<string, rgw_usage_log_info> log_objs;
5053
5054   string hash;
5055   string last_user;
5056
5057   /* restructure usage map, zone by object hash */
5058   map<rgw_user_bucket, RGWUsageBatch>::iterator iter;
5059   for (iter = usage_info.begin(); iter != usage_info.end(); ++iter) {
5060     const rgw_user_bucket& ub = iter->first;
5061     RGWUsageBatch& info = iter->second;
5062
5063     if (ub.user.empty()) {
5064       ldout(cct, 0) << "WARNING: RGWRados::log_usage(): user name empty (bucket=" << ub.bucket << "), skipping" << dendl;
5065       continue;
5066     }
5067
5068     if (ub.user != last_user) {
5069       /* index *should* be random, but why waste extra cycles
5070          in most cases max user shards is not going to exceed 1,
5071          so just incrementing it */
5072       usage_log_hash(cct, ub.user, hash, index++);
5073     }
5074     last_user = ub.user;
5075     vector<rgw_usage_log_entry>& v = log_objs[hash].entries;
5076
5077     for (auto miter = info.m.begin(); miter != info.m.end(); ++miter) {
5078       v.push_back(miter->second);
5079     }
5080   }
5081
5082   map<string, rgw_usage_log_info>::iterator liter;
5083
5084   for (liter = log_objs.begin(); liter != log_objs.end(); ++liter) {
5085     int r = cls_obj_usage_log_add(liter->first, liter->second);
5086     if (r < 0)
5087       return r;
5088   }
5089   return 0;
5090 }
5091
5092 int RGWRados::read_usage(const rgw_user& user, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries,
5093                          bool *is_truncated, RGWUsageIter& usage_iter, map<rgw_user_bucket, rgw_usage_log_entry>& usage)
5094 {
5095   uint32_t num = max_entries;
5096   string hash, first_hash;
5097   string user_str = user.to_str();
5098   usage_log_hash(cct, user_str, first_hash, 0);
5099
5100   if (usage_iter.index) {
5101     usage_log_hash(cct, user_str, hash, usage_iter.index);
5102   } else {
5103     hash = first_hash;
5104   }
5105
5106   usage.clear();
5107
5108   do {
5109     map<rgw_user_bucket, rgw_usage_log_entry> ret_usage;
5110     map<rgw_user_bucket, rgw_usage_log_entry>::iterator iter;
5111
5112     int ret =  cls_obj_usage_log_read(hash, user_str, start_epoch, end_epoch, num,
5113                                     usage_iter.read_iter, ret_usage, is_truncated);
5114     if (ret == -ENOENT)
5115       goto next;
5116
5117     if (ret < 0)
5118       return ret;
5119
5120     num -= ret_usage.size();
5121
5122     for (iter = ret_usage.begin(); iter != ret_usage.end(); ++iter) {
5123       usage[iter->first].aggregate(iter->second);
5124     }
5125
5126 next:
5127     if (!*is_truncated) {
5128       usage_iter.read_iter.clear();
5129       usage_log_hash(cct, user_str, hash, ++usage_iter.index);
5130     }
5131   } while (num && !*is_truncated && hash != first_hash);
5132   return 0;
5133 }
5134
5135 int RGWRados::trim_usage(rgw_user& user, uint64_t start_epoch, uint64_t end_epoch)
5136 {
5137   uint32_t index = 0;
5138   string hash, first_hash;
5139   string user_str = user.to_str();
5140   usage_log_hash(cct, user_str, first_hash, index);
5141
5142   hash = first_hash;
5143
5144   do {
5145     int ret =  cls_obj_usage_log_trim(hash, user_str, start_epoch, end_epoch);
5146     if (ret == -ENOENT)
5147       goto next;
5148
5149     if (ret < 0)
5150       return ret;
5151
5152 next:
5153     usage_log_hash(cct, user_str, hash, ++index);
5154   } while (hash != first_hash);
5155
5156   return 0;
5157 }
5158
5159 int RGWRados::key_to_shard_id(const string& key, int max_shards)
5160 {
5161   return rgw_shards_hash(key, max_shards);
5162 }
5163
5164 void RGWRados::shard_name(const string& prefix, unsigned max_shards, const string& key, string& name, int *shard_id)
5165 {
5166   uint32_t val = ceph_str_hash_linux(key.c_str(), key.size());
5167   char buf[16];
5168   if (shard_id) {
5169     *shard_id = val % max_shards;
5170   }
5171   snprintf(buf, sizeof(buf), "%u", (unsigned)(val % max_shards));
5172   name = prefix + buf;
5173 }
5174
5175 void RGWRados::shard_name(const string& prefix, unsigned max_shards, const string& section, const string& key, string& name)
5176 {
5177   uint32_t val = ceph_str_hash_linux(key.c_str(), key.size());
5178   val ^= ceph_str_hash_linux(section.c_str(), section.size());
5179   char buf[16];
5180   snprintf(buf, sizeof(buf), "%u", (unsigned)(val % max_shards));
5181   name = prefix + buf;
5182 }
5183
5184 void RGWRados::shard_name(const string& prefix, unsigned shard_id, string& name)
5185 {
5186   char buf[16];
5187   snprintf(buf, sizeof(buf), "%u", shard_id);
5188   name = prefix + buf;
5189
5190 }
5191
5192 void RGWRados::time_log_prepare_entry(cls_log_entry& entry, const real_time& ut, const string& section, const string& key, bufferlist& bl)
5193 {
5194   cls_log_add_prepare_entry(entry, utime_t(ut), section, key, bl);
5195 }
5196
5197 int RGWRados::time_log_add_init(librados::IoCtx& io_ctx)
5198 {
5199   return rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx, true);
5200
5201 }
5202
5203 int RGWRados::time_log_add(const string& oid, const real_time& ut, const string& section, const string& key, bufferlist& bl)
5204 {
5205   librados::IoCtx io_ctx;
5206
5207   int r = time_log_add_init(io_ctx);
5208   if (r < 0) {
5209     return r;
5210   }
5211
5212   ObjectWriteOperation op;
5213   utime_t t(ut);
5214   cls_log_add(op, t, section, key, bl);
5215
5216   return io_ctx.operate(oid, &op);
5217 }
5218
5219 int RGWRados::time_log_add(const string& oid, list<cls_log_entry>& entries,
5220                            librados::AioCompletion *completion, bool monotonic_inc)
5221 {
5222   librados::IoCtx io_ctx;
5223
5224   int r = time_log_add_init(io_ctx);
5225   if (r < 0) {
5226     return r;
5227   }
5228
5229   ObjectWriteOperation op;
5230   cls_log_add(op, entries, monotonic_inc);
5231
5232   if (!completion) {
5233     r = io_ctx.operate(oid, &op);
5234   } else {
5235     r = io_ctx.aio_operate(oid, completion, &op);
5236   }
5237   return r;
5238 }
5239
5240 int RGWRados::time_log_list(const string& oid, const real_time& start_time, const real_time& end_time,
5241                             int max_entries, list<cls_log_entry>& entries,
5242                             const string& marker,
5243                             string *out_marker,
5244                             bool *truncated)
5245 {
5246   librados::IoCtx io_ctx;
5247
5248   int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx);
5249   if (r < 0)
5250     return r;
5251   librados::ObjectReadOperation op;
5252
5253   utime_t st(start_time);
5254   utime_t et(end_time);
5255
5256   cls_log_list(op, st, et, marker, max_entries, entries,
5257                out_marker, truncated);
5258
5259   bufferlist obl;
5260
5261   int ret = io_ctx.operate(oid, &op, &obl);
5262   if (ret < 0)
5263     return ret;
5264
5265   return 0;
5266 }
5267
5268 int RGWRados::time_log_info(const string& oid, cls_log_header *header)
5269 {
5270   librados::IoCtx io_ctx;
5271
5272   int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx);
5273   if (r < 0)
5274     return r;
5275   librados::ObjectReadOperation op;
5276
5277   cls_log_info(op, header);
5278
5279   bufferlist obl;
5280
5281   int ret = io_ctx.operate(oid, &op, &obl);
5282   if (ret < 0)
5283     return ret;
5284
5285   return 0;
5286 }
5287
5288 int RGWRados::time_log_info_async(librados::IoCtx& io_ctx, const string& oid, cls_log_header *header, librados::AioCompletion *completion)
5289 {
5290   int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx);
5291   if (r < 0)
5292     return r;
5293
5294   librados::ObjectReadOperation op;
5295
5296   cls_log_info(op, header);
5297
5298   int ret = io_ctx.aio_operate(oid, completion, &op, NULL);
5299   if (ret < 0)
5300     return ret;
5301
5302   return 0;
5303 }
5304
5305 int RGWRados::time_log_trim(const string& oid, const real_time& start_time, const real_time& end_time,
5306                             const string& from_marker, const string& to_marker,
5307                             librados::AioCompletion *completion)
5308 {
5309   librados::IoCtx io_ctx;
5310
5311   int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx);
5312   if (r < 0)
5313     return r;
5314
5315   utime_t st(start_time);
5316   utime_t et(end_time);
5317
5318   ObjectWriteOperation op;
5319   cls_log_trim(op, st, et, from_marker, to_marker);
5320
5321   if (!completion) {
5322     r = io_ctx.operate(oid, &op);
5323   } else {
5324     r = io_ctx.aio_operate(oid, completion, &op);
5325   }
5326   return r;
5327 }
5328
5329 string RGWRados::objexp_hint_get_shardname(int shard_num)
5330 {
5331   char buf[32];
5332   snprintf(buf, sizeof(buf), "%010u", (unsigned)shard_num);
5333
5334   string objname("obj_delete_at_hint.");
5335   return objname + buf;
5336 }
5337
5338 int RGWRados::objexp_key_shard(const rgw_obj_index_key& key)
5339 {
5340   string obj_key = key.name + key.instance;
5341   int num_shards = cct->_conf->rgw_objexp_hints_num_shards;
5342   uint32_t sid = ceph_str_hash_linux(obj_key.c_str(), obj_key.size());
5343   uint32_t sid2 = sid ^ ((sid & 0xFF) << 24);
5344   sid = rgw_shards_mod(sid2, num_shards);
5345   return sid;
5346 }
5347
5348 static string objexp_hint_get_keyext(const string& tenant_name,
5349                                      const string& bucket_name,
5350                                      const string& bucket_id,
5351                                      const rgw_obj_key& obj_key)
5352 {
5353   return tenant_name + (tenant_name.empty() ? "" : ":") + bucket_name + ":" + bucket_id +
5354       ":" + obj_key.name + ":" + obj_key.instance;
5355 }
5356
5357 int RGWRados::objexp_hint_add(const ceph::real_time& delete_at,
5358                               const string& tenant_name,
5359                               const string& bucket_name,
5360                               const string& bucket_id,
5361                               const rgw_obj_index_key& obj_key)
5362 {
5363   const string keyext = objexp_hint_get_keyext(tenant_name, bucket_name,
5364           bucket_id, obj_key);
5365   objexp_hint_entry he = {
5366       .tenant = tenant_name,
5367       .bucket_name = bucket_name,
5368       .bucket_id = bucket_id,
5369       .obj_key = obj_key,
5370       .exp_time = delete_at };
5371   bufferlist hebl;
5372   ::encode(he, hebl);
5373   ObjectWriteOperation op;
5374   cls_timeindex_add(op, utime_t(delete_at), keyext, hebl);
5375
5376   string shard_name = objexp_hint_get_shardname(objexp_key_shard(obj_key));
5377   return objexp_pool_ctx.operate(shard_name, &op);
5378 }
5379
5380 void  RGWRados::objexp_get_shard(int shard_num,
5381                                  string& shard)                       /* out */
5382 {
5383   shard = objexp_hint_get_shardname(shard_num);
5384 }
5385
5386 int RGWRados::objexp_hint_list(const string& oid,
5387                                const ceph::real_time& start_time,
5388                                const ceph::real_time& end_time,
5389                                const int max_entries,
5390                                const string& marker,
5391                                list<cls_timeindex_entry>& entries, /* out */
5392                                string *out_marker,                 /* out */
5393                                bool *truncated)                    /* out */
5394 {
5395   librados::ObjectReadOperation op;
5396   cls_timeindex_list(op, utime_t(start_time), utime_t(end_time), marker, max_entries, entries,
5397         out_marker, truncated);
5398
5399   bufferlist obl;
5400   int ret = objexp_pool_ctx.operate(oid, &op, &obl);
5401
5402   if ((ret < 0 ) && (ret != -ENOENT)) {
5403     return ret;
5404   }
5405
5406   if ((ret == -ENOENT) && truncated) {
5407     *truncated = false;
5408   }
5409
5410   return 0;
5411 }
5412
5413 int RGWRados::objexp_hint_parse(cls_timeindex_entry &ti_entry,  /* in */
5414                                 objexp_hint_entry& hint_entry)  /* out */
5415 {
5416   try {
5417     bufferlist::iterator iter = ti_entry.value.begin();
5418     ::decode(hint_entry, iter);
5419   } catch (buffer::error& err) {
5420     ldout(cct, 0) << "ERROR: couldn't decode avail_pools" << dendl;
5421   }
5422
5423   return 0;
5424 }
5425
5426 int RGWRados::objexp_hint_trim(const string& oid,
5427                                const ceph::real_time& start_time,
5428                                const ceph::real_time& end_time,
5429                                const string& from_marker,
5430                                const string& to_marker)
5431 {
5432   int ret = cls_timeindex_trim(objexp_pool_ctx, oid, utime_t(start_time), utime_t(end_time),
5433           from_marker, to_marker);
5434   if ((ret < 0 ) && (ret != -ENOENT)) {
5435     return ret;
5436   }
5437
5438   return 0;
5439 }
5440
5441 int RGWRados::lock_exclusive(rgw_pool& pool, const string& oid, timespan& duration, 
5442                              string& zone_id, string& owner_id) {
5443   librados::IoCtx io_ctx;
5444
5445   int r = rgw_init_ioctx(get_rados_handle(), pool, io_ctx);
5446   if (r < 0) {
5447     return r;
5448   }
5449   uint64_t msec = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
5450   utime_t ut(msec / 1000, msec % 1000);
5451   
5452   rados::cls::lock::Lock l(log_lock_name);
5453   l.set_duration(ut);
5454   l.set_cookie(owner_id);
5455   l.set_tag(zone_id);
5456   l.set_renew(true);
5457   
5458   return l.lock_exclusive(&io_ctx, oid);
5459 }
5460
5461 int RGWRados::unlock(rgw_pool& pool, const string& oid, string& zone_id, string& owner_id) {
5462   librados::IoCtx io_ctx;
5463
5464   int r = rgw_init_ioctx(get_rados_handle(), pool, io_ctx);
5465   if (r < 0) {
5466     return r;
5467   }
5468   
5469   rados::cls::lock::Lock l(log_lock_name);
5470   l.set_tag(zone_id);
5471   l.set_cookie(owner_id);
5472   
5473   return l.unlock(&io_ctx, oid);
5474 }
5475
5476 int RGWRados::decode_policy(bufferlist& bl, ACLOwner *owner)
5477 {
5478   bufferlist::iterator i = bl.begin();
5479   RGWAccessControlPolicy policy(cct);
5480   try {
5481     policy.decode_owner(i);
5482   } catch (buffer::error& err) {
5483     ldout(cct, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl;
5484     return -EIO;
5485   }
5486   *owner = policy.get_owner();
5487   return 0;
5488 }
5489
5490 int rgw_policy_from_attrset(CephContext *cct, map<string, bufferlist>& attrset, RGWAccessControlPolicy *policy)
5491 {
5492   map<string, bufferlist>::iterator aiter = attrset.find(RGW_ATTR_ACL);
5493   if (aiter == attrset.end())
5494     return -EIO;
5495
5496   bufferlist& bl = aiter->second;
5497   bufferlist::iterator iter = bl.begin();
5498   try {
5499     policy->decode(iter);
5500   } catch (buffer::error& err) {
5501     ldout(cct, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl;
5502     return -EIO;
5503   }
5504   if (cct->_conf->subsys.should_gather(ceph_subsys_rgw, 15)) {
5505     RGWAccessControlPolicy_S3 *s3policy = static_cast<RGWAccessControlPolicy_S3 *>(policy);
5506     ldout(cct, 15) << __func__ << " Read AccessControlPolicy";
5507     s3policy->to_xml(*_dout);
5508     *_dout << dendl;
5509   }
5510   return 0;
5511 }
5512
5513
5514 int RGWRados::Bucket::update_bucket_id(const string& new_bucket_id)
5515 {
5516   rgw_bucket bucket = bucket_info.bucket;
5517   bucket.update_bucket_id(new_bucket_id);
5518
5519   RGWObjectCtx obj_ctx(store);
5520
5521   int ret = store->get_bucket_instance_info(obj_ctx, bucket, bucket_info, nullptr, nullptr);
5522   if (ret < 0) {
5523     return ret;
5524   }
5525
5526   return 0;
5527 }
5528
5529 /** 
5530  * get listing of the objects in a bucket.
5531  *
5532  * max: maximum number of results to return
5533  * bucket: bucket to list contents of
5534  * prefix: only return results that match this prefix
5535  * delim: do not include results that match this string.
5536  *     Any skipped results will have the matching portion of their name
5537  *     inserted in common_prefixes with a "true" mark.
5538  * marker: if filled in, begin the listing with this object.
5539  * end_marker: if filled in, end the listing with this object.
5540  * result: the objects are put in here.
5541  * common_prefixes: if delim is filled in, any matching prefixes are placed here.
5542  * is_truncated: if number of objects in the bucket is bigger than max, then truncated.
5543  */
5544 int RGWRados::Bucket::List::list_objects(int64_t max,
5545                                          vector<rgw_bucket_dir_entry> *result,
5546                                          map<string, bool> *common_prefixes,
5547                                          bool *is_truncated)
5548 {
5549   RGWRados *store = target->get_store();
5550   CephContext *cct = store->ctx();
5551   int shard_id = target->get_shard_id();
5552
5553   int count = 0;
5554   bool truncated = true;
5555   int read_ahead = std::max(cct->_conf->rgw_list_bucket_min_readahead,max);
5556
5557   result->clear();
5558
5559   rgw_obj_key marker_obj(params.marker.name, params.marker.instance, params.ns);
5560   rgw_obj_index_key cur_marker;
5561   marker_obj.get_index_key(&cur_marker);
5562
5563   rgw_obj_key end_marker_obj(params.end_marker.name, params.end_marker.instance,
5564                              params.ns);
5565   rgw_obj_index_key cur_end_marker;
5566   end_marker_obj.get_index_key(&cur_end_marker);
5567   const bool cur_end_marker_valid = !params.end_marker.empty();
5568
5569   rgw_obj_key prefix_obj(params.prefix);
5570   prefix_obj.ns = params.ns;
5571   string cur_prefix = prefix_obj.get_index_key_name();
5572
5573   string bigger_than_delim;
5574
5575   if (!params.delim.empty()) {
5576     unsigned long val = decode_utf8((unsigned char *)params.delim.c_str(), params.delim.size());
5577     char buf[params.delim.size() + 16];
5578     int r = encode_utf8(val + 1, (unsigned char *)buf);
5579     if (r < 0) {
5580       ldout(cct,0) << "ERROR: encode_utf8() failed" << dendl;
5581       return -EINVAL;
5582     }
5583     buf[r] = '\0';
5584
5585     bigger_than_delim = buf;
5586
5587     /* if marker points at a common prefix, fast forward it into its upperbound string */
5588     int delim_pos = cur_marker.name.find(params.delim, cur_prefix.size());
5589     if (delim_pos >= 0) {
5590       string s = cur_marker.name.substr(0, delim_pos);
5591       s.append(bigger_than_delim);
5592       cur_marker = s;
5593     }
5594   }
5595   
5596   string skip_after_delim;
5597   while (truncated && count <= max) {
5598     if (skip_after_delim > cur_marker.name) {
5599       cur_marker = skip_after_delim;
5600       ldout(cct, 20) << "setting cur_marker=" << cur_marker.name << "[" << cur_marker.instance << "]" << dendl;
5601     }
5602     std::map<string, rgw_bucket_dir_entry> ent_map;
5603     int r = store->cls_bucket_list(target->get_bucket_info(), shard_id, cur_marker, cur_prefix,
5604                                    read_ahead + 1 - count, params.list_versions, ent_map,
5605                                    &truncated, &cur_marker);
5606     if (r < 0)
5607       return r;
5608
5609     std::map<string, rgw_bucket_dir_entry>::iterator eiter;
5610     for (eiter = ent_map.begin(); eiter != ent_map.end(); ++eiter) {
5611       rgw_bucket_dir_entry& entry = eiter->second;
5612       rgw_obj_index_key index_key = entry.key;
5613
5614       rgw_obj_key obj(index_key);
5615
5616       /* note that parse_raw_oid() here will not set the correct object's instance, as
5617        * rgw_obj_index_key encodes that separately. We don't need to set the instance because it's
5618        * not needed for the checks here and we end up using the raw entry for the return vector
5619        */
5620       bool valid = rgw_obj_key::parse_raw_oid(index_key.name, &obj);
5621       if (!valid) {
5622         ldout(cct, 0) << "ERROR: could not parse object name: " << obj.name << dendl;
5623         continue;
5624       }
5625       bool check_ns = (obj.ns == params.ns);
5626       if (!params.list_versions && !entry.is_visible()) {
5627         continue;
5628       }
5629
5630       if (params.enforce_ns && !check_ns) {
5631         if (!params.ns.empty()) {
5632           /* we've iterated past the namespace we're searching -- done now */
5633           truncated = false;
5634           goto done;
5635         }
5636
5637         /* we're not looking at the namespace this object is in, next! */
5638         continue;
5639       }
5640
5641       if (cur_end_marker_valid && cur_end_marker <= index_key) {
5642         truncated = false;
5643         goto done;
5644       }
5645
5646       if (count < max) {
5647         params.marker = index_key;
5648         next_marker = index_key;
5649       }
5650
5651       if (params.filter && !params.filter->filter(obj.name, index_key.name))
5652         continue;
5653
5654       if (params.prefix.size() &&  (obj.name.compare(0, params.prefix.size(), params.prefix) != 0))
5655         continue;
5656
5657       if (!params.delim.empty()) {
5658         int delim_pos = obj.name.find(params.delim, params.prefix.size());
5659
5660         if (delim_pos >= 0) {
5661           string prefix_key = obj.name.substr(0, delim_pos + 1);
5662
5663           if (common_prefixes &&
5664               common_prefixes->find(prefix_key) == common_prefixes->end()) {
5665             if (count >= max) {
5666               truncated = true;
5667               goto done;
5668             }
5669             next_marker = prefix_key;
5670             (*common_prefixes)[prefix_key] = true;
5671
5672             int marker_delim_pos = cur_marker.name.find(params.delim, cur_prefix.size());
5673
5674             skip_after_delim = cur_marker.name.substr(0, marker_delim_pos);
5675             skip_after_delim.append(bigger_than_delim);
5676
5677             ldout(cct, 20) << "skip_after_delim=" << skip_after_delim << dendl;
5678
5679             count++;
5680           }
5681
5682           continue;
5683         }
5684       }
5685
5686       if (count >= max) {
5687         truncated = true;
5688         goto done;
5689       }
5690
5691       result->emplace_back(std::move(entry));
5692       count++;
5693     }
5694
5695     // Either the back-end telling us truncated, or we don't consume all
5696     // items returned per the amount caller request
5697     truncated = (truncated || eiter != ent_map.end());
5698   }
5699
5700 done:
5701   if (is_truncated)
5702     *is_truncated = truncated;
5703
5704   return 0;
5705 }
5706
5707 /**
5708  * create a rados pool, associated meta info
5709  * returns 0 on success, -ERR# otherwise.
5710  */
5711 int RGWRados::create_pool(const rgw_pool& pool)
5712 {
5713   int ret = 0;
5714
5715   librados::Rados *rad = get_rados_handle();
5716   ret = rad->pool_create(pool.name.c_str(), 0);
5717   if (ret == -EEXIST)
5718     ret = 0;
5719   else if (ret == -ERANGE) {
5720     ldout(cct, 0)
5721       << __func__
5722       << " ERROR: librados::Rados::pool_create returned " << cpp_strerror(-ret)
5723       << " (this can be due to a pool or placement group misconfiguration, e.g., pg_num < pgp_num)"
5724       << dendl;
5725   }
5726   if (ret < 0)
5727     return ret;
5728
5729   librados::IoCtx io_ctx;
5730   ret = rad->ioctx_create(pool.name.c_str(), io_ctx);
5731   if (ret < 0)
5732     return ret;
5733
5734   ret = io_ctx.application_enable(pg_pool_t::APPLICATION_NAME_RGW, false);
5735   if (ret < 0 && ret != -EOPNOTSUPP)
5736     return ret;
5737   return 0;
5738 }
5739
5740 int RGWRados::init_bucket_index(RGWBucketInfo& bucket_info, int num_shards)
5741 {
5742   librados::IoCtx index_ctx; // context for new bucket
5743
5744   string dir_oid =  dir_oid_prefix;
5745   int r = open_bucket_index_ctx(bucket_info, index_ctx);
5746   if (r < 0) {
5747     return r;
5748   }
5749
5750   dir_oid.append(bucket_info.bucket.bucket_id);
5751
5752   map<int, string> bucket_objs;
5753   get_bucket_index_objects(dir_oid, num_shards, bucket_objs);
5754
5755   return CLSRGWIssueBucketIndexInit(index_ctx, bucket_objs, cct->_conf->rgw_bucket_index_max_aio)();
5756 }
5757
5758 void RGWRados::create_bucket_id(string *bucket_id)
5759 {
5760   uint64_t iid = instance_id();
5761   uint64_t bid = next_bucket_id();
5762   char buf[get_zone_params().get_id().size() + 48];
5763   snprintf(buf, sizeof(buf), "%s.%llu.%llu", get_zone_params().get_id().c_str(), (long long)iid, (long long)bid);
5764   *bucket_id = buf;
5765 }
5766
5767 int RGWRados::create_bucket(RGWUserInfo& owner, rgw_bucket& bucket,
5768                             const string& zonegroup_id,
5769                             const string& placement_rule,
5770                             const string& swift_ver_location,
5771                             const RGWQuotaInfo * pquota_info,
5772                             map<std::string, bufferlist>& attrs,
5773                             RGWBucketInfo& info,
5774                             obj_version *pobjv,
5775                             obj_version *pep_objv,
5776                             real_time creation_time,
5777                             rgw_bucket *pmaster_bucket,
5778                             uint32_t *pmaster_num_shards,
5779                             bool exclusive)
5780 {
5781 #define MAX_CREATE_RETRIES 20 /* need to bound retries */
5782   string selected_placement_rule_name;
5783   RGWZonePlacementInfo rule_info;
5784
5785   for (int i = 0; i < MAX_CREATE_RETRIES; i++) {
5786     int ret = 0;
5787     ret = select_bucket_placement(owner, zonegroup_id, placement_rule,
5788                                   &selected_placement_rule_name, &rule_info);
5789     if (ret < 0)
5790       return ret;
5791
5792     if (!pmaster_bucket) {
5793       create_bucket_id(&bucket.marker);
5794       bucket.bucket_id = bucket.marker;
5795     } else {
5796       bucket.marker = pmaster_bucket->marker;
5797       bucket.bucket_id = pmaster_bucket->bucket_id;
5798     }
5799
5800     RGWObjVersionTracker& objv_tracker = info.objv_tracker;
5801
5802     if (pobjv) {
5803       objv_tracker.write_version = *pobjv;
5804     } else {
5805       objv_tracker.generate_new_write_ver(cct);
5806     }
5807
5808     info.bucket = bucket;
5809     info.owner = owner.user_id;
5810     info.zonegroup = zonegroup_id;
5811     info.placement_rule = selected_placement_rule_name;
5812     info.index_type = rule_info.index_type;
5813     info.swift_ver_location = swift_ver_location;
5814     info.swift_versioning = (!swift_ver_location.empty());
5815     if (pmaster_num_shards) {
5816       info.num_shards = *pmaster_num_shards;
5817     } else {
5818       info.num_shards = bucket_index_max_shards;
5819     }
5820     info.bucket_index_shard_hash_type = RGWBucketInfo::MOD;
5821     info.requester_pays = false;
5822     if (real_clock::is_zero(creation_time)) {
5823       info.creation_time = ceph::real_clock::now();
5824     } else {
5825       info.creation_time = creation_time;
5826     }
5827     if (pquota_info) {
5828       info.quota = *pquota_info;
5829     }
5830
5831     int r = init_bucket_index(info, info.num_shards);
5832     if (r < 0) {
5833       return r;
5834     }
5835
5836     ret = put_linked_bucket_info(info, exclusive, ceph::real_time(), pep_objv, &attrs, true);
5837     if (ret == -EEXIST) {
5838       librados::IoCtx index_ctx;
5839       map<int, string> bucket_objs;
5840       int r = open_bucket_index(info, index_ctx, bucket_objs);
5841       if (r < 0)
5842         return r;
5843
5844        /* we need to reread the info and return it, caller will have a use for it */
5845       RGWObjVersionTracker instance_ver = info.objv_tracker;
5846       info.objv_tracker.clear();
5847       RGWObjectCtx obj_ctx(this);
5848       r = get_bucket_info(obj_ctx, bucket.tenant, bucket.name, info, NULL, NULL);
5849       if (r < 0) {
5850         if (r == -ENOENT) {
5851           continue;
5852         }
5853         ldout(cct, 0) << "get_bucket_info returned " << r << dendl;
5854         return r;
5855       }
5856
5857       /* only remove it if it's a different bucket instance */
5858       if (info.bucket.bucket_id != bucket.bucket_id) {
5859         /* remove bucket meta instance */
5860         string entry = bucket.get_key();
5861         r = rgw_bucket_instance_remove_entry(this, entry, &instance_ver);
5862         if (r < 0)
5863           return r;
5864
5865         map<int, string>::const_iterator biter;
5866         for (biter = bucket_objs.begin(); biter != bucket_objs.end(); ++biter) {
5867           // Do best effort removal
5868           index_ctx.remove(biter->second);
5869         }
5870       }
5871       /* ret == -ENOENT here */
5872     }
5873     return ret;
5874   }
5875
5876   /* this is highly unlikely */
5877   ldout(cct, 0) << "ERROR: could not create bucket, continuously raced with bucket creation and removal" << dendl;
5878   return -ENOENT;
5879 }
5880
5881 int RGWRados::select_new_bucket_location(RGWUserInfo& user_info, const string& zonegroup_id, const string& request_rule,
5882                                          string *pselected_rule_name, RGWZonePlacementInfo *rule_info)
5883
5884 {
5885   /* first check that zonegroup exists within current period. */
5886   RGWZoneGroup zonegroup;
5887   int ret = get_zonegroup(zonegroup_id, zonegroup);
5888   if (ret < 0) {
5889     ldout(cct, 0) << "could not find zonegroup " << zonegroup_id << " in current period" << dendl;
5890     return ret;
5891   }
5892
5893   /* find placement rule. Hierarchy: request rule > user default rule > zonegroup default rule */
5894   std::map<std::string, RGWZoneGroupPlacementTarget>::const_iterator titer;
5895
5896   if (!request_rule.empty()) {
5897     titer = zonegroup.placement_targets.find(request_rule);
5898     if (titer == zonegroup.placement_targets.end()) {
5899       ldout(cct, 0) << "could not find requested placement id " << request_rule 
5900                     << " within zonegroup " << dendl;
5901       return -ERR_INVALID_LOCATION_CONSTRAINT;
5902     }
5903   } else if (!user_info.default_placement.empty()) {
5904     titer = zonegroup.placement_targets.find(user_info.default_placement);
5905     if (titer == zonegroup.placement_targets.end()) {
5906       ldout(cct, 0) << "could not find user default placement id " << user_info.default_placement
5907                     << " within zonegroup " << dendl;
5908       return -ERR_INVALID_LOCATION_CONSTRAINT;
5909     }
5910   } else {
5911     if (zonegroup.default_placement.empty()) { // zonegroup default rule as fallback, it should not be empty.
5912       ldout(cct, 0) << "misconfiguration, zonegroup default placement id should not be empty." << dendl;
5913       return -ERR_ZONEGROUP_DEFAULT_PLACEMENT_MISCONFIGURATION;
5914     } else {
5915       titer = zonegroup.placement_targets.find(zonegroup.default_placement);
5916       if (titer == zonegroup.placement_targets.end()) {
5917         ldout(cct, 0) << "could not find zonegroup default placement id " << zonegroup.default_placement
5918                       << " within zonegroup " << dendl;
5919         return -ERR_INVALID_LOCATION_CONSTRAINT;
5920       }
5921     }
5922   }
5923
5924   /* now check tag for the rule, whether user is permitted to use rule */
5925   const auto& target_rule = titer->second;
5926   if (!target_rule.user_permitted(user_info.placement_tags)) {
5927     ldout(cct, 0) << "user not permitted to use placement rule " << titer->first  << dendl;
5928     return -EPERM;
5929   }
5930
5931   if (pselected_rule_name)
5932     *pselected_rule_name = titer->first;
5933
5934   return select_bucket_location_by_rule(titer->first, rule_info);
5935 }
5936
5937 int RGWRados::select_bucket_location_by_rule(const string& location_rule, RGWZonePlacementInfo *rule_info)
5938 {
5939   if (location_rule.empty()) {
5940     /* we can only reach here if we're trying to set a bucket location from a bucket
5941      * created on a different zone, using a legacy / default pool configuration
5942      */
5943     return select_legacy_bucket_placement(rule_info);
5944   }
5945
5946   /*
5947    * make sure that zone has this rule configured. We're
5948    * checking it for the local zone, because that's where this bucket object is going to
5949    * reside.
5950    */
5951   map<string, RGWZonePlacementInfo>::iterator piter = get_zone_params().placement_pools.find(location_rule);
5952   if (piter == get_zone_params().placement_pools.end()) {
5953     /* couldn't find, means we cannot really place data for this bucket in this zone */
5954     if (get_zonegroup().equals(zonegroup.get_id())) {
5955       /* that's a configuration error, zone should have that rule, as we're within the requested
5956        * zonegroup */
5957       return -EINVAL;
5958     } else {
5959       /* oh, well, data is not going to be placed here, bucket object is just a placeholder */
5960       return 0;
5961     }
5962   }
5963
5964   RGWZonePlacementInfo& placement_info = piter->second;
5965
5966   if (rule_info) {
5967     *rule_info = placement_info;
5968   }
5969
5970   return 0;
5971 }
5972
5973 int RGWRados::select_bucket_placement(RGWUserInfo& user_info, const string& zonegroup_id, const string& placement_rule,
5974                                       string *pselected_rule_name, RGWZonePlacementInfo *rule_info)
5975 {
5976   if (!get_zone_params().placement_pools.empty()) {
5977     return select_new_bucket_location(user_info, zonegroup_id, placement_rule,
5978                                       pselected_rule_name, rule_info);
5979   }
5980
5981   if (pselected_rule_name) {
5982     pselected_rule_name->clear();
5983   }
5984
5985   return select_legacy_bucket_placement(rule_info);
5986 }
5987
5988 int RGWRados::select_legacy_bucket_placement(RGWZonePlacementInfo *rule_info)
5989 {
5990   bufferlist map_bl;
5991   map<string, bufferlist> m;
5992   string pool_name;
5993   bool write_map = false;
5994
5995   rgw_raw_obj obj(get_zone_params().domain_root, avail_pools);
5996
5997   RGWObjectCtx obj_ctx(this);
5998   int ret = rgw_get_system_obj(this, obj_ctx, get_zone_params().domain_root, avail_pools, map_bl, NULL, NULL);
5999   if (ret < 0) {
6000     goto read_omap;
6001   }
6002
6003   try {
6004     bufferlist::iterator iter = map_bl.begin();
6005     ::decode(m, iter);
6006   } catch (buffer::error& err) {
6007     ldout(cct, 0) << "ERROR: couldn't decode avail_pools" << dendl;
6008   }
6009
6010 read_omap:
6011   if (m.empty()) {
6012     bufferlist header;
6013     ret = omap_get_all(obj, header, m);
6014
6015     write_map = true;
6016   }
6017
6018   if (ret < 0 || m.empty()) {
6019     vector<rgw_pool> pools;
6020     string s = string("default.") + default_storage_pool_suffix;
6021     pools.push_back(rgw_pool(s));
6022     vector<int> retcodes;
6023     bufferlist bl;
6024     ret = create_pools(pools, retcodes);
6025     if (ret < 0)
6026       return ret;
6027     ret = omap_set(obj, s, bl);
6028     if (ret < 0)
6029       return ret;
6030     m[s] = bl;
6031   }
6032
6033   if (write_map) {
6034     bufferlist new_bl;
6035     ::encode(m, new_bl);
6036     ret = put_system_obj_data(NULL, obj, new_bl, -1, false);
6037     if (ret < 0) {
6038       ldout(cct, 0) << "WARNING: could not save avail pools map info ret=" << ret << dendl;
6039     }
6040   }
6041
6042   map<string, bufferlist>::iterator miter;
6043   if (m.size() > 1) {
6044     vector<string> v;
6045     for (miter = m.begin(); miter != m.end(); ++miter) {
6046       v.push_back(miter->first);
6047     }
6048
6049     uint32_t r;
6050     ret = get_random_bytes((char *)&r, sizeof(r));
6051     if (ret < 0)
6052       return ret;
6053
6054     int i = r % v.size();
6055     pool_name = v[i];
6056   } else {
6057     miter = m.begin();
6058     pool_name = miter->first;
6059   }
6060
6061   rule_info->data_pool = pool_name;
6062   rule_info->data_extra_pool = pool_name;
6063   rule_info->index_pool = pool_name;
6064   rule_info->index_type = RGWBIType_Normal;
6065
6066   return 0;
6067 }
6068
6069 bool RGWRados::get_obj_data_pool(const string& placement_rule, const rgw_obj& obj, rgw_pool *pool)
6070 {
6071   return rgw_get_obj_data_pool(zonegroup, zone_params, placement_rule, obj, pool);
6072 }
6073
6074 bool RGWRados::obj_to_raw(const string& placement_rule, const rgw_obj& obj, rgw_raw_obj *raw_obj)
6075 {
6076   get_obj_bucket_and_oid_loc(obj, raw_obj->oid, raw_obj->loc);
6077
6078   return get_obj_data_pool(placement_rule, obj, &raw_obj->pool);
6079 }
6080
6081 int RGWRados::update_placement_map()
6082 {
6083   bufferlist header;
6084   map<string, bufferlist> m;
6085   rgw_raw_obj obj(get_zone_params().domain_root, avail_pools);
6086   int ret = omap_get_all(obj, header, m);
6087   if (ret < 0)
6088     return ret;
6089
6090   bufferlist new_bl;
6091   ::encode(m, new_bl);
6092   ret = put_system_obj_data(NULL, obj, new_bl, -1, false);
6093   if (ret < 0) {
6094     ldout(cct, 0) << "WARNING: could not save avail pools map info ret=" << ret << dendl;
6095   }
6096
6097   return ret;
6098 }
6099
6100 int RGWRados::add_bucket_placement(const rgw_pool& new_pool)
6101 {
6102   librados::Rados *rad = get_rados_handle();
6103   int ret = rad->pool_lookup(new_pool.name.c_str());
6104   if (ret < 0) // DNE, or something
6105     return ret;
6106
6107   rgw_raw_obj obj(get_zone_params().domain_root, avail_pools);
6108   bufferlist empty_bl;
6109   ret = omap_set(obj, new_pool.to_str(), empty_bl);
6110
6111   // don't care about return value
6112   update_placement_map();
6113
6114   return ret;
6115 }
6116
6117 int RGWRados::remove_bucket_placement(const rgw_pool& old_pool)
6118 {
6119   rgw_raw_obj obj(get_zone_params().domain_root, avail_pools);
6120   int ret = omap_del(obj, old_pool.to_str());
6121
6122   // don't care about return value
6123   update_placement_map();
6124
6125   return ret;
6126 }
6127
6128 int RGWRados::list_placement_set(set<rgw_pool>& names)
6129 {
6130   bufferlist header;
6131   map<string, bufferlist> m;
6132
6133   rgw_raw_obj obj(get_zone_params().domain_root, avail_pools);
6134   int ret = omap_get_all(obj, header, m);
6135   if (ret < 0)
6136     return ret;
6137
6138   names.clear();
6139   map<string, bufferlist>::iterator miter;
6140   for (miter = m.begin(); miter != m.end(); ++miter) {
6141     names.insert(rgw_pool(miter->first));
6142   }
6143
6144   return names.size();
6145 }
6146
6147 int RGWRados::create_pools(vector<rgw_pool>& pools, vector<int>& retcodes)
6148 {
6149   vector<librados::PoolAsyncCompletion *> completions;
6150   vector<int> rets;
6151
6152   librados::Rados *rad = get_rados_handle();
6153   for (auto iter = pools.begin(); iter != pools.end(); ++iter) {
6154     librados::PoolAsyncCompletion *c = librados::Rados::pool_async_create_completion();
6155     completions.push_back(c);
6156     rgw_pool& pool = *iter;
6157     int ret = rad->pool_create_async(pool.name.c_str(), c);
6158     rets.push_back(ret);
6159   }
6160
6161   vector<int>::iterator riter;
6162   vector<librados::PoolAsyncCompletion *>::iterator citer;
6163
6164   bool error = false;
6165   assert(rets.size() == completions.size());
6166   for (riter = rets.begin(), citer = completions.begin(); riter != rets.end(); ++riter, ++citer) {
6167     int r = *riter;
6168     PoolAsyncCompletion *c = *citer;
6169     if (r == 0) {
6170       c->wait();
6171       r = c->get_return_value();
6172       if (r < 0) {
6173         ldout(cct, 0) << "WARNING: async pool_create returned " << r << dendl;
6174         error = true;
6175       }
6176     }
6177     c->release();
6178     retcodes.push_back(r);
6179   }
6180   if (error) {
6181     return 0;
6182   }
6183
6184   std::vector<librados::IoCtx> io_ctxs;
6185   retcodes.clear();
6186   for (auto pool : pools) {
6187     io_ctxs.emplace_back();
6188     int ret = rad->ioctx_create(pool.name.c_str(), io_ctxs.back());
6189     if (ret < 0) {
6190       ldout(cct, 0) << "WARNING: ioctx_create returned " << ret << dendl;
6191       error = true;
6192     }
6193     retcodes.push_back(ret);
6194   }
6195   if (error) {
6196     return 0;
6197   }
6198
6199   completions.clear();
6200   for (auto &io_ctx : io_ctxs) {
6201     librados::PoolAsyncCompletion *c =
6202       librados::Rados::pool_async_create_completion();
6203     completions.push_back(c);
6204     int ret = io_ctx.application_enable_async(pg_pool_t::APPLICATION_NAME_RGW,
6205                                               false, c);
6206     assert(ret == 0);
6207   }
6208
6209   retcodes.clear();
6210   for (auto c : completions) {
6211     c->wait();
6212     int ret = c->get_return_value();
6213     if (ret == -EOPNOTSUPP) {
6214       ret = 0;
6215     } else if (ret < 0) {
6216       ldout(cct, 0) << "WARNING: async application_enable returned " << ret
6217                     << dendl;
6218       error = true;
6219     }
6220     c->release();
6221     retcodes.push_back(ret);
6222   }
6223   return 0;
6224 }
6225
6226 int RGWRados::get_obj_head_ioctx(const RGWBucketInfo& bucket_info, const rgw_obj& obj, librados::IoCtx *ioctx)
6227 {
6228   string oid, key;
6229   get_obj_bucket_and_oid_loc(obj, oid, key);
6230
6231   rgw_pool pool;
6232   if (!get_obj_data_pool(bucket_info.placement_rule, obj, &pool)) {
6233     ldout(cct, 0) << "ERROR: cannot get data pool for obj=" << obj << ", probably misconfiguration" << dendl;
6234     return -EIO;
6235   }
6236
6237   int r = open_pool_ctx(pool, *ioctx);
6238   if (r < 0) {
6239     return r;
6240   }
6241
6242   ioctx->locator_set_key(key);
6243
6244   return 0;
6245 }
6246
6247 int RGWRados::get_obj_head_ref(const RGWBucketInfo& bucket_info, const rgw_obj& obj, rgw_rados_ref *ref)
6248 {
6249   get_obj_bucket_and_oid_loc(obj, ref->oid, ref->key);
6250
6251   rgw_pool pool;
6252   if (!get_obj_data_pool(bucket_info.placement_rule, obj, &pool)) {
6253     ldout(cct, 0) << "ERROR: cannot get data pool for obj=" << obj << ", probably misconfiguration" << dendl;
6254     return -EIO;
6255   }
6256
6257   int r = open_pool_ctx(pool, ref->ioctx);
6258   if (r < 0) {
6259     return r;
6260   }
6261
6262   ref->ioctx.locator_set_key(ref->key);
6263
6264   return 0;
6265 }
6266
6267 int RGWRados::get_raw_obj_ref(const rgw_raw_obj& obj, rgw_rados_ref *ref)
6268 {
6269   ref->oid = obj.oid;
6270   ref->key = obj.loc;
6271
6272   int r;
6273
6274   if (ref->oid.empty()) {
6275     ref->oid = obj.pool.to_str();
6276     ref->pool = get_zone_params().domain_root;
6277   } else {
6278     ref->pool = obj.pool;
6279   }
6280   r = open_pool_ctx(ref->pool, ref->ioctx);
6281   if (r < 0)
6282     return r;
6283
6284   ref->ioctx.locator_set_key(ref->key);
6285
6286   return 0;
6287 }
6288
6289 int RGWRados::get_system_obj_ref(const rgw_raw_obj& obj, rgw_rados_ref *ref)
6290 {
6291   return get_raw_obj_ref(obj, ref);
6292 }
6293
6294 /*
6295  * fixes an issue where head objects were supposed to have a locator created, but ended
6296  * up without one
6297  */
6298 int RGWRados::fix_head_obj_locator(const RGWBucketInfo& bucket_info, bool copy_obj, bool remove_bad, rgw_obj_key& key)
6299 {
6300   const rgw_bucket& bucket = bucket_info.bucket;
6301   string oid;
6302   string locator;
6303
6304   rgw_obj obj(bucket, key);
6305
6306   get_obj_bucket_and_oid_loc(obj, oid, locator);
6307
6308   if (locator.empty()) {
6309     ldout(cct, 20) << "object does not have a locator, nothing to fix" << dendl;
6310     return 0;
6311   }
6312
6313   librados::IoCtx ioctx;
6314
6315   int ret = get_obj_head_ioctx(bucket_info, obj, &ioctx);
6316   if (ret < 0) {
6317     cerr << "ERROR: get_obj_head_ioctx() returned ret=" << ret << std::endl;
6318     return ret;
6319   }
6320   ioctx.locator_set_key(string()); /* override locator for this object, use empty locator */
6321
6322   uint64_t size;
6323   bufferlist data;
6324
6325   struct timespec mtime_ts;
6326   map<string, bufferlist> attrs;
6327   librados::ObjectReadOperation op;
6328   op.getxattrs(&attrs, NULL);
6329   op.stat2(&size, &mtime_ts, NULL);
6330 #define HEAD_SIZE 512 * 1024
6331   op.read(0, HEAD_SIZE, &data, NULL);
6332
6333   ret = ioctx.operate(oid, &op, NULL);
6334   if (ret < 0) {
6335     lderr(cct) << "ERROR: ioctx.operate(oid=" << oid << ") returned ret=" << ret << dendl;
6336     return ret;
6337   }
6338
6339   if (size > HEAD_SIZE) {
6340     lderr(cct) << "ERROR: returned object size (" << size << ") > HEAD_SIZE (" << HEAD_SIZE << ")" << dendl;
6341     return -EIO;
6342   }
6343
6344   if (size != data.length()) {
6345     lderr(cct) << "ERROR: returned object size (" << size << ") != data.length() (" << data.length() << ")" << dendl;
6346     return -EIO;
6347   }
6348
6349   if (copy_obj) {
6350     librados::ObjectWriteOperation wop;
6351
6352     wop.mtime2(&mtime_ts);
6353
6354     map<string, bufferlist>::iterator iter;
6355     for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
6356       wop.setxattr(iter->first.c_str(), iter->second);
6357     }
6358
6359     wop.write(0, data);
6360
6361     ioctx.locator_set_key(locator);
6362     ioctx.operate(oid, &wop);
6363   }
6364
6365   if (remove_bad) {
6366     ioctx.locator_set_key(string());
6367
6368     ret = ioctx.remove(oid);
6369     if (ret < 0) {
6370       lderr(cct) << "ERROR: failed to remove original bad object" << dendl;
6371       return ret;
6372     }
6373   }
6374
6375   return 0;
6376 }
6377
6378 int RGWRados::move_rados_obj(librados::IoCtx& src_ioctx,
6379                              const string& src_oid, const string& src_locator,
6380                              librados::IoCtx& dst_ioctx,
6381                              const string& dst_oid, const string& dst_locator)
6382 {
6383
6384 #define COPY_BUF_SIZE (4 * 1024 * 1024)
6385   bool done = false;
6386   uint64_t chunk_size = COPY_BUF_SIZE;
6387   uint64_t ofs = 0;
6388   int ret = 0;
6389   real_time mtime;
6390   struct timespec mtime_ts;
6391   uint64_t size;
6392
6393   if (src_oid == dst_oid && src_locator == dst_locator) {
6394     return 0;
6395   }
6396
6397   src_ioctx.locator_set_key(src_locator);
6398   dst_ioctx.locator_set_key(dst_locator);
6399
6400   do {
6401     bufferlist data;
6402     ObjectReadOperation rop;
6403     ObjectWriteOperation wop;
6404
6405     if (ofs == 0) {
6406       rop.stat2(&size, &mtime_ts, NULL);
6407       mtime = real_clock::from_timespec(mtime_ts);
6408     }
6409     rop.read(ofs, chunk_size, &data, NULL);
6410     ret = src_ioctx.operate(src_oid, &rop, NULL);
6411     if (ret < 0) {
6412       goto done_err;
6413     }
6414
6415     if (data.length() == 0) {
6416       break;
6417     }
6418
6419     if (ofs == 0) {
6420       wop.create(true); /* make it exclusive */
6421       wop.mtime2(&mtime_ts);
6422       mtime = real_clock::from_timespec(mtime_ts);
6423     }
6424     wop.write(ofs, data);
6425     ret = dst_ioctx.operate(dst_oid, &wop);
6426     ofs += data.length();
6427     done = data.length() != chunk_size;
6428   } while (!done);
6429
6430   if (ofs != size) {
6431     lderr(cct) << "ERROR: " << __func__ << ": copying " << src_oid << " -> " << dst_oid
6432                << ": expected " << size << " bytes to copy, ended up with " << ofs << dendl;
6433     ret = -EIO;
6434     goto done_err;
6435   }
6436
6437   src_ioctx.remove(src_oid);
6438
6439   return 0;
6440
6441 done_err:
6442   lderr(cct) << "ERROR: failed to copy " << src_oid << " -> " << dst_oid << dendl;
6443   return ret;
6444 }
6445
6446 /*
6447  * fixes an issue where head objects were supposed to have a locator created, but ended
6448  * up without one
6449  */
6450 int RGWRados::fix_tail_obj_locator(const RGWBucketInfo& bucket_info, rgw_obj_key& key, bool fix, bool *need_fix)
6451 {
6452   const rgw_bucket& bucket = bucket_info.bucket;
6453   rgw_obj obj(bucket, key);
6454
6455   if (need_fix) {
6456     *need_fix = false;
6457   }
6458
6459   rgw_rados_ref ref;
6460   int r = get_obj_head_ref(bucket_info, obj, &ref);
6461   if (r < 0) {
6462     return r;
6463   }
6464
6465   RGWObjState *astate = NULL;
6466   RGWObjectCtx rctx(this);
6467   r = get_obj_state(&rctx, bucket_info, obj, &astate, false);
6468   if (r < 0)
6469     return r;
6470
6471   if (astate->has_manifest) {
6472     RGWObjManifest::obj_iterator miter;
6473     RGWObjManifest& manifest = astate->manifest;
6474     for (miter = manifest.obj_begin(); miter != manifest.obj_end(); ++miter) {
6475       rgw_raw_obj raw_loc = miter.get_location().get_raw_obj(this);
6476       rgw_obj loc;
6477       string oid;
6478       string locator;
6479
6480       rgw_raw_obj_to_obj(manifest.get_tail_placement().bucket, raw_loc, &loc);
6481
6482       if (loc.key.ns.empty()) {
6483         /* continue, we're only interested in tail objects */
6484         continue;
6485       }
6486
6487       get_obj_bucket_and_oid_loc(loc, oid, locator);
6488       ref.ioctx.locator_set_key(locator);
6489
6490       ldout(cct, 20) << __func__ << ": key=" << key << " oid=" << oid << " locator=" << locator << dendl;
6491
6492       r = ref.ioctx.stat(oid, NULL, NULL);
6493       if (r != -ENOENT) {
6494         continue;
6495       }
6496
6497       string bad_loc;
6498       prepend_bucket_marker(bucket, loc.key.name, bad_loc);
6499
6500       /* create a new ioctx with the bad locator */
6501       librados::IoCtx src_ioctx;
6502       src_ioctx.dup(ref.ioctx);
6503       src_ioctx.locator_set_key(bad_loc);
6504
6505       r = src_ioctx.stat(oid, NULL, NULL);
6506       if (r != 0) {
6507         /* cannot find a broken part */
6508         continue;
6509       }
6510       ldout(cct, 20) << __func__ << ": found bad object part: " << loc << dendl;
6511       if (need_fix) {
6512         *need_fix = true;
6513       }
6514       if (fix) {
6515         r = move_rados_obj(src_ioctx, oid, bad_loc, ref.ioctx, oid, locator);
6516         if (r < 0) {
6517           lderr(cct) << "ERROR: copy_rados_obj() on oid=" << oid << " returned r=" << r << dendl;
6518         }
6519       }
6520     }
6521   }
6522
6523   return 0;
6524 }
6525
6526 int RGWRados::BucketShard::init(const rgw_bucket& _bucket, const rgw_obj& obj)
6527 {
6528   bucket = _bucket;
6529
6530   RGWObjectCtx obj_ctx(store);
6531
6532   RGWBucketInfo bucket_info;
6533   int ret = store->get_bucket_instance_info(obj_ctx, bucket, bucket_info, NULL, NULL);
6534   if (ret < 0) {
6535     return ret;
6536   }
6537
6538   ret = store->open_bucket_index_shard(bucket_info, index_ctx, obj.get_hash_object(), &bucket_obj, &shard_id);
6539   if (ret < 0) {
6540     ldout(store->ctx(), 0) << "ERROR: open_bucket_index_shard() returned ret=" << ret << dendl;
6541     return ret;
6542   }
6543   ldout(store->ctx(), 20) << " bucket index object: " << bucket_obj << dendl;
6544
6545   return 0;
6546 }
6547
6548 int RGWRados::BucketShard::init(const rgw_bucket& _bucket, int sid)
6549 {
6550   bucket = _bucket;
6551   shard_id = sid;
6552
6553   RGWObjectCtx obj_ctx(store);
6554
6555   RGWBucketInfo bucket_info;
6556   int ret = store->get_bucket_instance_info(obj_ctx, bucket, bucket_info, NULL, NULL);
6557   if (ret < 0) {
6558     return ret;
6559   }
6560
6561   ret = store->open_bucket_index_shard(bucket_info, index_ctx, shard_id, &bucket_obj);
6562   if (ret < 0) {
6563     ldout(store->ctx(), 0) << "ERROR: open_bucket_index_shard() returned ret=" << ret << dendl;
6564     return ret;
6565   }
6566   ldout(store->ctx(), 20) << " bucket index object: " << bucket_obj << dendl;
6567
6568   return 0;
6569 }
6570
6571
6572 /* Execute @handler on last item in bucket listing for bucket specified
6573  * in @bucket_info. @obj_prefix and @obj_delim narrow down the listing
6574  * to objects matching these criterias. */
6575 int RGWRados::on_last_entry_in_listing(RGWBucketInfo& bucket_info,
6576                                        const std::string& obj_prefix,
6577                                        const std::string& obj_delim,
6578                                        std::function<int(const rgw_bucket_dir_entry&)> handler)
6579 {
6580   RGWRados::Bucket target(this, bucket_info);
6581   RGWRados::Bucket::List list_op(&target);
6582
6583   list_op.params.prefix = obj_prefix;
6584   list_op.params.delim = obj_delim;
6585
6586   ldout(cct, 20) << "iterating listing for bucket=" << bucket_info.bucket.name
6587                  << ", obj_prefix=" << obj_prefix
6588                  << ", obj_delim=" << obj_delim
6589                  << dendl;
6590
6591   bool is_truncated = false;
6592
6593   boost::optional<rgw_bucket_dir_entry> last_entry;
6594   /* We need to rewind to the last object in a listing. */
6595   do {
6596     /* List bucket entries in chunks. */
6597     static constexpr int MAX_LIST_OBJS = 100;
6598     std::vector<rgw_bucket_dir_entry> entries(MAX_LIST_OBJS);
6599
6600     int ret = list_op.list_objects(MAX_LIST_OBJS, &entries, nullptr,
6601                                    &is_truncated);
6602     if (ret < 0) {
6603       return ret;
6604     } else if (!entries.empty()) {
6605       last_entry = entries.back();
6606     }
6607   } while (is_truncated);
6608
6609   if (last_entry) {
6610     return handler(*last_entry);
6611   }
6612
6613   /* Empty listing - no items we can run handler on. */
6614   return 0;
6615 }
6616
6617
6618 int RGWRados::swift_versioning_copy(RGWObjectCtx& obj_ctx,
6619                                     const rgw_user& user,
6620                                     RGWBucketInfo& bucket_info,
6621                                     rgw_obj& obj)
6622 {
6623   if (! swift_versioning_enabled(bucket_info)) {
6624     return 0;
6625   }
6626
6627   obj_ctx.obj.set_atomic(obj);
6628
6629   RGWObjState * state = nullptr;
6630   int r = get_obj_state(&obj_ctx, bucket_info, obj, &state, false);
6631   if (r < 0) {
6632     return r;
6633   }
6634
6635   if (!state->exists) {
6636     return 0;
6637   }
6638
6639   string client_id;
6640   string op_id;
6641
6642   const string& src_name = obj.get_oid();
6643   char buf[src_name.size() + 32];
6644   struct timespec ts = ceph::real_clock::to_timespec(state->mtime);
6645   snprintf(buf, sizeof(buf), "%03x%s/%lld.%06ld", (int)src_name.size(),
6646            src_name.c_str(), (long long)ts.tv_sec, ts.tv_nsec / 1000);
6647
6648   RGWBucketInfo dest_bucket_info;
6649
6650   r = get_bucket_info(obj_ctx, bucket_info.bucket.tenant, bucket_info.swift_ver_location, dest_bucket_info, NULL, NULL);
6651   if (r < 0) {
6652     ldout(cct, 10) << "failed to read dest bucket info: r=" << r << dendl;
6653     if (r == -ENOENT) {
6654       return -ERR_PRECONDITION_FAILED;
6655     }
6656     return r;
6657   }
6658
6659   if (dest_bucket_info.owner != bucket_info.owner) {
6660     return -ERR_PRECONDITION_FAILED;
6661   }
6662
6663   rgw_obj dest_obj(dest_bucket_info.bucket, buf);
6664   obj_ctx.obj.set_atomic(dest_obj);
6665
6666   string no_zone;
6667
6668   r = copy_obj(obj_ctx,
6669                user,
6670                client_id,
6671                op_id,
6672                NULL, /* req_info *info */
6673                no_zone,
6674                dest_obj,
6675                obj,
6676                dest_bucket_info,
6677                bucket_info,
6678                NULL, /* time_t *src_mtime */
6679                NULL, /* time_t *mtime */
6680                NULL, /* const time_t *mod_ptr */
6681                NULL, /* const time_t *unmod_ptr */
6682                false, /* bool high_precision_time */
6683                NULL, /* const char *if_match */
6684                NULL, /* const char *if_nomatch */
6685                RGWRados::ATTRSMOD_NONE,
6686                true, /* bool copy_if_newer */
6687                state->attrset,
6688                RGW_OBJ_CATEGORY_MAIN,
6689                0, /* uint64_t olh_epoch */
6690                real_time(), /* time_t delete_at */
6691                NULL, /* string *version_id */
6692                NULL, /* string *ptag */
6693                NULL, /* string *petag */
6694                NULL, /* void (*progress_cb)(off_t, void *) */
6695                NULL); /* void *progress_data */
6696   if (r == -ECANCELED || r == -ENOENT) {
6697     /* Has already been overwritten, meaning another rgw process already
6698      * copied it out */
6699     return 0;
6700   }
6701
6702   return r;
6703 }
6704
6705 int RGWRados::swift_versioning_restore(RGWObjectCtx& obj_ctx,
6706                                        const rgw_user& user,
6707                                        RGWBucketInfo& bucket_info,
6708                                        rgw_obj& obj,
6709                                        bool& restored)             /* out */
6710 {
6711   if (! swift_versioning_enabled(bucket_info)) {
6712     return 0;
6713   }
6714
6715   /* Bucket info of the bucket that stores previous versions of our object. */
6716   RGWBucketInfo archive_binfo;
6717
6718   int ret = get_bucket_info(obj_ctx, bucket_info.bucket.tenant,
6719                             bucket_info.swift_ver_location, archive_binfo,
6720                             nullptr, nullptr);
6721   if (ret < 0) {
6722     return ret;
6723   }
6724
6725   /* Abort the operation if the bucket storing our archive belongs to someone
6726    * else. This is a limitation in comparison to Swift as we aren't taking ACLs
6727    * into consideration. For we can live with that.
6728    *
6729    * TODO: delegate this check to un upper layer and compare with ACLs. */
6730   if (bucket_info.owner != archive_binfo.owner) {
6731     return -EPERM;
6732   }
6733
6734   /* This code will be executed on latest version of the object. */
6735   const auto handler = [&](const rgw_bucket_dir_entry& entry) -> int {
6736     std::string no_client_id;
6737     std::string no_op_id;
6738     std::string no_zone;
6739
6740     /* We don't support object versioning of Swift API on those buckets that
6741      * are already versioned using the S3 mechanism. This affects also bucket
6742      * storing archived objects. Otherwise the delete operation would create
6743      * a deletion marker. */
6744     if (archive_binfo.versioned()) {
6745       restored = false;
6746       return -ERR_PRECONDITION_FAILED;
6747     }
6748
6749     /* We are requesting ATTRSMOD_NONE so the attr attribute is perfectly
6750      * irrelevant and may be safely skipped. */
6751     std::map<std::string, ceph::bufferlist> no_attrs;
6752
6753     rgw_obj archive_obj(archive_binfo.bucket, entry.key);
6754     obj_ctx.obj.set_atomic(archive_obj);
6755     obj_ctx.obj.set_atomic(obj);
6756
6757     int ret = copy_obj(obj_ctx,
6758                        user,
6759                        no_client_id,
6760                        no_op_id,
6761                        nullptr,       /* req_info *info */
6762                        no_zone,
6763                        obj,           /* dest obj */
6764                        archive_obj,   /* src obj */
6765                        bucket_info,   /* dest bucket info */
6766                        archive_binfo, /* src bucket info */
6767                        nullptr,       /* time_t *src_mtime */
6768                        nullptr,       /* time_t *mtime */
6769                        nullptr,       /* const time_t *mod_ptr */
6770                        nullptr,       /* const time_t *unmod_ptr */
6771                        false,         /* bool high_precision_time */
6772                        nullptr,       /* const char *if_match */
6773                        nullptr,       /* const char *if_nomatch */
6774                        RGWRados::ATTRSMOD_NONE,
6775                        true,          /* bool copy_if_newer */
6776                        no_attrs,
6777                        RGW_OBJ_CATEGORY_MAIN,
6778                        0,             /* uint64_t olh_epoch */
6779                        real_time(),   /* time_t delete_at */
6780                        nullptr,       /* string *version_id */
6781                        nullptr,       /* string *ptag */
6782                        nullptr,       /* string *petag */
6783                        nullptr,       /* void (*progress_cb)(off_t, void *) */
6784                        nullptr);      /* void *progress_data */
6785     if (ret == -ECANCELED || ret == -ENOENT) {
6786       /* Has already been overwritten, meaning another rgw process already
6787        * copied it out */
6788       return 0;
6789     } else if (ret < 0) {
6790       return ret;
6791     } else {
6792       restored = true;
6793     }
6794
6795     /* Need to remove the archived copy. */
6796     ret = delete_obj(obj_ctx, archive_binfo, archive_obj,
6797                      archive_binfo.versioning_status());
6798
6799     return ret;
6800   };
6801
6802   const std::string& obj_name = obj.get_oid();
6803   const auto prefix = boost::str(boost::format("%03x%s") % obj_name.size()
6804                                                          % obj_name);
6805
6806   return on_last_entry_in_listing(archive_binfo, prefix, std::string(),
6807                                   handler);
6808 }
6809
6810 /**
6811  * Write/overwrite an object to the bucket storage.
6812  * bucket: the bucket to store the object in
6813  * obj: the object name/key
6814  * data: the object contents/value
6815  * size: the amount of data to write (data must be this long)
6816  * accounted_size: original size of data before compression, encryption
6817  * mtime: if non-NULL, writes the given mtime to the bucket storage
6818  * attrs: all the given attrs are written to bucket storage for the given object
6819  * exclusive: create object exclusively
6820  * Returns: 0 on success, -ERR# otherwise.
6821  */
6822 int RGWRados::Object::Write::_do_write_meta(uint64_t size, uint64_t accounted_size,
6823                                            map<string, bufferlist>& attrs,
6824                                            bool assume_noent, bool modify_tail,
6825                                            void *_index_op)
6826 {
6827   RGWRados::Bucket::UpdateIndex *index_op = static_cast<RGWRados::Bucket::UpdateIndex *>(_index_op);
6828   RGWRados *store = target->get_store();
6829
6830   ObjectWriteOperation op;
6831
6832   RGWObjState *state;
6833   int r = target->get_state(&state, false, assume_noent);
6834   if (r < 0)
6835     return r;
6836
6837   rgw_obj& obj = target->get_obj();
6838
6839   if (obj.get_oid().empty()) {
6840     ldout(store->ctx(), 0) << "ERROR: " << __func__ << "(): cannot write object with empty name" << dendl;
6841     return -EIO;
6842   }
6843
6844   rgw_rados_ref ref;
6845   r = store->get_obj_head_ref(target->get_bucket_info(), obj, &ref);
6846   if (r < 0)
6847     return r;
6848
6849   bool is_olh = state->is_olh;
6850
6851   bool reset_obj = (meta.flags & PUT_OBJ_CREATE) != 0;
6852
6853   const string *ptag = meta.ptag;
6854   if (!ptag && !index_op->get_optag()->empty()) {
6855     ptag = index_op->get_optag();
6856   }
6857   r = target->prepare_atomic_modification(op, reset_obj, ptag, meta.if_match, meta.if_nomatch, false, modify_tail);
6858   if (r < 0)
6859     return r;
6860
6861   if (real_clock::is_zero(meta.set_mtime)) {
6862     meta.set_mtime = real_clock::now();
6863   }
6864
6865   if (state->is_olh) {
6866     op.setxattr(RGW_ATTR_OLH_ID_TAG, state->olh_tag);
6867   }
6868
6869   struct timespec mtime_ts = real_clock::to_timespec(meta.set_mtime);
6870   op.mtime2(&mtime_ts);
6871
6872   if (meta.data) {
6873     /* if we want to overwrite the data, we also want to overwrite the
6874        xattrs, so just remove the object */
6875     op.write_full(*meta.data);
6876   }
6877
6878   string etag;
6879   string content_type;
6880   bufferlist acl_bl;
6881
6882   map<string, bufferlist>::iterator iter;
6883   if (meta.rmattrs) {
6884     for (iter = meta.rmattrs->begin(); iter != meta.rmattrs->end(); ++iter) {
6885       const string& name = iter->first;
6886       op.rmxattr(name.c_str());
6887     }
6888   }
6889
6890   if (meta.manifest) {
6891     /* remove existing manifest attr */
6892     iter = attrs.find(RGW_ATTR_MANIFEST);
6893     if (iter != attrs.end())
6894       attrs.erase(iter);
6895
6896     bufferlist bl;
6897     ::encode(*meta.manifest, bl);
6898     op.setxattr(RGW_ATTR_MANIFEST, bl);
6899   }
6900
6901   for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
6902     const string& name = iter->first;
6903     bufferlist& bl = iter->second;
6904
6905     if (!bl.length())
6906       continue;
6907
6908     op.setxattr(name.c_str(), bl);
6909
6910     if (name.compare(RGW_ATTR_ETAG) == 0) {
6911       etag = bl.c_str();
6912     } else if (name.compare(RGW_ATTR_CONTENT_TYPE) == 0) {
6913       content_type = bl.c_str();
6914     } else if (name.compare(RGW_ATTR_ACL) == 0) {
6915       acl_bl = bl;
6916     }
6917   }
6918   if (attrs.find(RGW_ATTR_PG_VER) == attrs.end()) {
6919     cls_rgw_obj_store_pg_ver(op, RGW_ATTR_PG_VER);
6920   }
6921
6922   if (attrs.find(RGW_ATTR_SOURCE_ZONE) == attrs.end()) {
6923     bufferlist bl;
6924     ::encode(store->get_zone_short_id(), bl);
6925     op.setxattr(RGW_ATTR_SOURCE_ZONE, bl);
6926   }
6927
6928   if (!op.size())
6929     return 0;
6930
6931   uint64_t epoch;
6932   int64_t poolid;
6933   bool orig_exists;
6934   uint64_t orig_size;
6935   
6936   if (!reset_obj) {    //Multipart upload, it has immutable head. 
6937     orig_exists = false;
6938     orig_size = 0;
6939   } else {
6940     orig_exists = state->exists;
6941     orig_size = state->accounted_size;
6942   }
6943
6944   bool versioned_target = (meta.olh_epoch > 0 || !obj.key.instance.empty());
6945
6946   bool versioned_op = (target->versioning_enabled() || is_olh || versioned_target);
6947
6948   if (versioned_op) {
6949     index_op->set_bilog_flags(RGW_BILOG_FLAG_VERSIONED_OP);
6950   }
6951
6952   if (!index_op->is_prepared()) {
6953     r = index_op->prepare(CLS_RGW_OP_ADD, &state->write_tag);
6954     if (r < 0)
6955       return r;
6956   }
6957
6958   r = ref.ioctx.operate(ref.oid, &op);
6959   if (r < 0) { /* we can expect to get -ECANCELED if object was replaced under,
6960                 or -ENOENT if was removed, or -EEXIST if it did not exist
6961                 before and now it does */
6962     if (r == -EEXIST && assume_noent) {
6963       target->invalidate_state();
6964       return r;
6965     }
6966     goto done_cancel;
6967   }
6968
6969   epoch = ref.ioctx.get_last_version();
6970   poolid = ref.ioctx.get_id();
6971
6972   r = target->complete_atomic_modification();
6973   if (r < 0) {
6974     ldout(store->ctx(), 0) << "ERROR: complete_atomic_modification returned r=" << r << dendl;
6975   }
6976
6977   r = index_op->complete(poolid, epoch, size, accounted_size,
6978                         meta.set_mtime, etag, content_type, &acl_bl,
6979                         meta.category, meta.remove_objs, meta.user_data);
6980   if (r < 0)
6981     goto done_cancel;
6982
6983   if (meta.mtime) {
6984     *meta.mtime = meta.set_mtime;
6985   }
6986
6987   /* note that index_op was using state so we couldn't invalidate it earlier */
6988   target->invalidate_state();
6989   state = NULL;
6990
6991   if (versioned_op) {
6992     r = store->set_olh(target->get_ctx(), target->get_bucket_info(), obj, false, NULL, meta.olh_epoch, real_time(), false, meta.zones_trace);
6993     if (r < 0) {
6994       return r;
6995     }
6996   }
6997
6998   if (!real_clock::is_zero(meta.delete_at)) {
6999     rgw_obj_index_key obj_key;
7000     obj.key.get_index_key(&obj_key);
7001
7002     r = store->objexp_hint_add(meta.delete_at,
7003             obj.bucket.tenant, obj.bucket.name, obj.bucket.bucket_id, obj_key);
7004     if (r < 0) {
7005       ldout(store->ctx(), 0) << "ERROR: objexp_hint_add() returned r=" << r << ", object will not get removed" << dendl;
7006       /* ignoring error, nothing we can do at this point */
7007     }
7008   }
7009   meta.canceled = false;
7010
7011   /* update quota cache */
7012   if (meta.completeMultipart){
7013         store->quota_handler->update_stats(meta.owner, obj.bucket, (orig_exists ? 0 : 1),
7014                                      0, orig_size);
7015   }
7016   else {
7017     store->quota_handler->update_stats(meta.owner, obj.bucket, (orig_exists ? 0 : 1),
7018                                      accounted_size, orig_size);  
7019   }
7020   return 0;
7021
7022 done_cancel:
7023   int ret = index_op->cancel();
7024   if (ret < 0) {
7025     ldout(store->ctx(), 0) << "ERROR: index_op.cancel()() returned ret=" << ret << dendl;
7026   }
7027
7028   meta.canceled = true;
7029
7030   /* we lost in a race. There are a few options:
7031    * - existing object was rewritten (ECANCELED)
7032    * - non existing object was created (EEXIST)
7033    * - object was removed (ENOENT)
7034    * should treat it as a success
7035    */
7036   if (meta.if_match == NULL && meta.if_nomatch == NULL) {
7037     if (r == -ECANCELED || r == -ENOENT || r == -EEXIST) {
7038       r = 0;
7039     }
7040   } else {
7041     if (meta.if_match != NULL) {
7042       // only overwrite existing object
7043       if (strcmp(meta.if_match, "*") == 0) {
7044         if (r == -ENOENT) {
7045           r = -ERR_PRECONDITION_FAILED;
7046         } else if (r == -ECANCELED) {
7047           r = 0;
7048         }
7049       }
7050     }
7051
7052     if (meta.if_nomatch != NULL) {
7053       // only create a new object
7054       if (strcmp(meta.if_nomatch, "*") == 0) {
7055         if (r == -EEXIST) {
7056           r = -ERR_PRECONDITION_FAILED;
7057         } else if (r == -ENOENT) {
7058           r = 0;
7059         }
7060       }
7061     }
7062   }
7063
7064   return r;
7065 }
7066
7067 int RGWRados::Object::Write::write_meta(uint64_t size, uint64_t accounted_size,
7068                                            map<string, bufferlist>& attrs)
7069 {
7070   RGWBucketInfo& bucket_info = target->get_bucket_info();
7071
7072   RGWRados::Bucket bop(target->get_store(), bucket_info);
7073   RGWRados::Bucket::UpdateIndex index_op(&bop, target->get_obj());
7074   index_op.set_zones_trace(meta.zones_trace);
7075   
7076   bool assume_noent = (meta.if_match == NULL && meta.if_nomatch == NULL);
7077   int r;
7078   if (assume_noent) {
7079     r = _do_write_meta(size, accounted_size, attrs, assume_noent, meta.modify_tail, (void *)&index_op);
7080     if (r == -EEXIST) {
7081       assume_noent = false;
7082     }
7083   }
7084   if (!assume_noent) {
7085     r = _do_write_meta(size, accounted_size, attrs, assume_noent, meta.modify_tail, (void *)&index_op);
7086   }
7087   return r;
7088 }
7089
7090 /** Write/overwrite a system object. */
7091 int RGWRados::put_system_obj_impl(rgw_raw_obj& obj, uint64_t size, real_time *mtime,
7092               map<std::string, bufferlist>& attrs, int flags,
7093               bufferlist& data,
7094               RGWObjVersionTracker *objv_tracker,
7095               real_time set_mtime /* 0 for don't set */)
7096 {
7097   rgw_rados_ref ref;
7098   int r = get_system_obj_ref(obj, &ref);
7099   if (r < 0)
7100     return r;
7101
7102   ObjectWriteOperation op;
7103
7104   if (flags & PUT_OBJ_EXCL) {
7105     if (!(flags & PUT_OBJ_CREATE))
7106         return -EINVAL;
7107     op.create(true); // exclusive create
7108   } else {
7109     op.remove();
7110     op.set_op_flags2(LIBRADOS_OP_FLAG_FAILOK);
7111     op.create(false);
7112   }
7113
7114   if (objv_tracker) {
7115     objv_tracker->prepare_op_for_write(&op);
7116   }
7117
7118   if (real_clock::is_zero(set_mtime)) {
7119     set_mtime = real_clock::now();
7120   }
7121
7122   struct timespec mtime_ts = real_clock::to_timespec(set_mtime);
7123   op.mtime2(&mtime_ts);
7124   op.write_full(data);
7125
7126   bufferlist acl_bl;
7127
7128   for (map<string, bufferlist>::iterator iter = attrs.begin(); iter != attrs.end(); ++iter) {
7129     const string& name = iter->first;
7130     bufferlist& bl = iter->second;
7131
7132     if (!bl.length())
7133       continue;
7134
7135     op.setxattr(name.c_str(), bl);
7136   }
7137
7138   r = ref.ioctx.operate(ref.oid, &op);
7139   if (r < 0) {
7140     return r;
7141   }
7142
7143   if (objv_tracker) {
7144     objv_tracker->apply_write();
7145   }
7146
7147   if (mtime) {
7148     *mtime = set_mtime;
7149   }
7150
7151   return 0;
7152 }
7153
7154 int RGWRados::put_system_obj_data(void *ctx, rgw_raw_obj& obj, bufferlist& bl,
7155                                   off_t ofs, bool exclusive,
7156                                   RGWObjVersionTracker *objv_tracker)
7157 {
7158   rgw_rados_ref ref;
7159   int r = get_system_obj_ref(obj, &ref);
7160   if (r < 0) {
7161     return r;
7162   }
7163
7164   ObjectWriteOperation op;
7165
7166   if (exclusive)
7167     op.create(true);
7168
7169   if (objv_tracker) {
7170     objv_tracker->prepare_op_for_write(&op);
7171   }
7172   if (ofs == -1) {
7173     op.write_full(bl);
7174   } else {
7175     op.write(ofs, bl);
7176   }
7177   r = ref.ioctx.operate(ref.oid, &op);
7178   if (r < 0)
7179     return r;
7180
7181   if (objv_tracker) {
7182     objv_tracker->apply_write();
7183   }
7184   return 0;
7185 }
7186
7187 /**
7188  * Write/overwrite an object to the bucket storage.
7189  * bucket: the bucket to store the object in
7190  * obj: the object name/key
7191  * data: the object contents/value
7192  * offset: the offet to write to in the object
7193  *         If this is -1, we will overwrite the whole object.
7194  * size: the amount of data to write (data must be this long)
7195  * attrs: all the given attrs are written to bucket storage for the given object
7196  * Returns: 0 on success, -ERR# otherwise.
7197  */
7198
7199 int RGWRados::aio_put_obj_data(void *ctx, rgw_raw_obj& obj, bufferlist& bl,
7200                                off_t ofs, bool exclusive,
7201                                void **handle)
7202 {
7203   rgw_rados_ref ref;
7204   int r = get_raw_obj_ref(obj, &ref);
7205   if (r < 0) {
7206     return r;
7207   }
7208
7209   AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL);
7210   *handle = c;
7211   
7212   ObjectWriteOperation op;
7213
7214   if (exclusive)
7215     op.create(true);
7216
7217   if (ofs == -1) {
7218     op.write_full(bl);
7219   } else {
7220     op.write(ofs, bl);
7221   }
7222   r = ref.ioctx.aio_operate(ref.oid, c, &op);
7223   if (r < 0)
7224     return r;
7225
7226   return 0;
7227 }
7228
7229 int RGWRados::aio_wait(void *handle)
7230 {
7231   AioCompletion *c = (AioCompletion *)handle;
7232   c->wait_for_safe();
7233   int ret = c->get_return_value();
7234   c->release();
7235   return ret;
7236 }
7237
7238 bool RGWRados::aio_completed(void *handle)
7239 {
7240   AioCompletion *c = (AioCompletion *)handle;
7241   return c->is_safe();
7242 }
7243
7244 class RGWRadosPutObj : public RGWGetDataCB
7245 {
7246   CephContext* cct;
7247   rgw_obj obj;
7248   RGWPutObjDataProcessor *filter;
7249   boost::optional<RGWPutObj_Compress>& compressor;
7250   CompressorRef& plugin;
7251   RGWPutObjProcessor_Atomic *processor;
7252   RGWOpStateSingleOp *opstate;
7253   void (*progress_cb)(off_t, void *);
7254   void *progress_data;
7255   bufferlist extra_data_bl;
7256   uint64_t extra_data_len;
7257   uint64_t data_len;
7258   map<string, bufferlist> src_attrs;
7259 public:
7260   RGWRadosPutObj(CephContext* cct,
7261                  CompressorRef& plugin,
7262                  boost::optional<RGWPutObj_Compress>& compressor,
7263                  RGWPutObjProcessor_Atomic *p,
7264                  RGWOpStateSingleOp *_ops,
7265                  void (*_progress_cb)(off_t, void *),
7266                  void *_progress_data) :
7267                        cct(cct),
7268                        filter(p),
7269                        compressor(compressor),
7270                        plugin(plugin),
7271                        processor(p),
7272                        opstate(_ops),
7273                        progress_cb(_progress_cb),
7274                        progress_data(_progress_data),
7275                        extra_data_len(0),
7276                        data_len(0) {}
7277
7278   int process_attrs(void) {
7279     if (extra_data_bl.length()) {
7280       JSONParser jp;
7281       if (!jp.parse(extra_data_bl.c_str(), extra_data_bl.length())) {
7282         ldout(cct, 0) << "failed to parse response extra data. len=" << extra_data_bl.length() << " data=" << extra_data_bl.c_str() << dendl;
7283         return -EIO;
7284       }
7285
7286       JSONDecoder::decode_json("attrs", src_attrs, &jp);
7287
7288       src_attrs.erase(RGW_ATTR_COMPRESSION);
7289       src_attrs.erase(RGW_ATTR_MANIFEST); // not interested in original object layout
7290     }
7291
7292     if (plugin && src_attrs.find(RGW_ATTR_CRYPT_MODE) == src_attrs.end()) {
7293       //do not compress if object is encrypted
7294       compressor = boost::in_place(cct, plugin, filter);
7295       filter = &*compressor;
7296     }
7297     return 0;
7298   }
7299
7300   int handle_data(bufferlist& bl, off_t ofs, off_t len) override {
7301     if (progress_cb) {
7302       progress_cb(ofs, progress_data);
7303     }
7304     if (extra_data_len) {
7305       size_t extra_len = bl.length();
7306       if (extra_len > extra_data_len)
7307         extra_len = extra_data_len;
7308
7309       bufferlist extra;
7310       bl.splice(0, extra_len, &extra);
7311       extra_data_bl.append(extra);
7312
7313       extra_data_len -= extra_len;
7314       if (extra_data_len == 0) {
7315         int res = process_attrs();
7316         if (res < 0)
7317           return res;
7318       }
7319       if (bl.length() == 0) {
7320         return 0;
7321       }
7322     }
7323     data_len += bl.length();
7324     bool again = false;
7325
7326     bool need_opstate = true;
7327
7328     do {
7329       void *handle = NULL;
7330       rgw_raw_obj obj;
7331       uint64_t size = bl.length();
7332       int ret = filter->handle_data(bl, ofs, &handle, &obj, &again);
7333       if (ret < 0)
7334         return ret;
7335
7336       if (need_opstate && opstate) {
7337         /* need to update opstate repository with new state. This is ratelimited, so we're not
7338          * really doing it every time
7339          */
7340         ret = opstate->renew_state();
7341         if (ret < 0) {
7342           ldout(cct, 0) << "ERROR: RGWRadosPutObj::handle_data(): failed to renew op state ret=" << ret << dendl;
7343           int r = filter->throttle_data(handle, obj, size, false);
7344           if (r < 0) {
7345             ldout(cct, 0) << "ERROR: RGWRadosPutObj::handle_data(): processor->throttle_data() returned " << r << dendl;
7346           }
7347           /* could not renew state! might have been marked as cancelled */
7348           return ret;
7349         }
7350         need_opstate = false;
7351       }
7352
7353       ret = filter->throttle_data(handle, obj, size, false);
7354       if (ret < 0)
7355         return ret;
7356     } while (again);
7357
7358     return 0;
7359   }
7360
7361   bufferlist& get_extra_data() { return extra_data_bl; }
7362
7363   map<string, bufferlist>& get_attrs() { return src_attrs; }
7364
7365   void set_extra_data_len(uint64_t len) override {
7366     extra_data_len = len;
7367   }
7368
7369   uint64_t get_data_len() {
7370     return data_len;
7371   }
7372
7373   int complete(const string& etag, real_time *mtime, real_time set_mtime,
7374                map<string, bufferlist>& attrs, real_time delete_at, rgw_zone_set *zones_trace) {
7375     return processor->complete(data_len, etag, mtime, set_mtime, attrs, delete_at, NULL, NULL, NULL, zones_trace);
7376   }
7377
7378   bool is_canceled() {
7379     return processor->is_canceled();
7380   }
7381 };
7382
7383 /*
7384  * prepare attrset depending on attrs_mod.
7385  */
7386 static void set_copy_attrs(map<string, bufferlist>& src_attrs,
7387                            map<string, bufferlist>& attrs,
7388                            RGWRados::AttrsMod attrs_mod)
7389 {
7390   switch (attrs_mod) {
7391   case RGWRados::ATTRSMOD_NONE:
7392     attrs = src_attrs;
7393     break;
7394   case RGWRados::ATTRSMOD_REPLACE:
7395     if (!attrs[RGW_ATTR_ETAG].length()) {
7396       attrs[RGW_ATTR_ETAG] = src_attrs[RGW_ATTR_ETAG];
7397     }
7398     if (!attrs[RGW_ATTR_TAIL_TAG].length()) {
7399       auto ttiter = src_attrs.find(RGW_ATTR_TAIL_TAG);
7400       if (ttiter != src_attrs.end()) {
7401         attrs[RGW_ATTR_TAIL_TAG] = src_attrs[RGW_ATTR_TAIL_TAG];
7402       }
7403     }
7404     break;
7405   case RGWRados::ATTRSMOD_MERGE:
7406     for (map<string, bufferlist>::iterator it = src_attrs.begin(); it != src_attrs.end(); ++it) {
7407       if (attrs.find(it->first) == attrs.end()) {
7408        attrs[it->first] = it->second;
7409       }
7410     }
7411     break;
7412   }
7413 }
7414
7415 int RGWRados::rewrite_obj(RGWBucketInfo& dest_bucket_info, rgw_obj& obj)
7416 {
7417   map<string, bufferlist> attrset;
7418
7419   real_time mtime;
7420   uint64_t obj_size;
7421   RGWObjectCtx rctx(this);
7422
7423   RGWRados::Object op_target(this, dest_bucket_info, rctx, obj);
7424   RGWRados::Object::Read read_op(&op_target);
7425
7426   read_op.params.attrs = &attrset;
7427   read_op.params.lastmod = &mtime;
7428   read_op.params.obj_size = &obj_size;
7429
7430   int ret = read_op.prepare();
7431   if (ret < 0)
7432     return ret;
7433
7434   attrset.erase(RGW_ATTR_ID_TAG);
7435   attrset.erase(RGW_ATTR_TAIL_TAG);
7436
7437   uint64_t max_chunk_size;
7438
7439   ret = get_max_chunk_size(dest_bucket_info.placement_rule, obj, &max_chunk_size);
7440   if (ret < 0) {
7441     ldout(cct, 0) << "ERROR: failed to get max_chunk_size() for bucket " << obj.bucket << dendl;
7442     return ret;
7443   }
7444
7445   return copy_obj_data(rctx, dest_bucket_info, read_op, obj_size - 1, obj, obj, max_chunk_size, NULL, mtime, attrset,
7446                        RGW_OBJ_CATEGORY_MAIN, 0, real_time(), NULL, NULL, NULL);
7447 }
7448
7449 struct obj_time_weight {
7450   real_time mtime;
7451   uint32_t zone_short_id;
7452   uint64_t pg_ver;
7453   bool high_precision;
7454
7455   obj_time_weight() : zone_short_id(0), pg_ver(0), high_precision(false) {}
7456
7457   bool compare_low_precision(const obj_time_weight& rhs) {
7458     struct timespec l = ceph::real_clock::to_timespec(mtime);
7459     struct timespec r = ceph::real_clock::to_timespec(rhs.mtime);
7460     l.tv_nsec = 0;
7461     r.tv_nsec = 0;
7462     if (l > r) {
7463       return false;
7464     }
7465     if (l < r) {
7466       return true;
7467     }
7468     if (zone_short_id != rhs.zone_short_id) {
7469       return (zone_short_id < rhs.zone_short_id);
7470     }
7471     return (pg_ver < rhs.pg_ver);
7472
7473   }
7474
7475   bool operator<(const obj_time_weight& rhs) {
7476     if (!high_precision || !rhs.high_precision) {
7477       return compare_low_precision(rhs);
7478     }
7479     if (mtime > rhs.mtime) {
7480       return false;
7481     }
7482     if (mtime < rhs.mtime) {
7483       return true;
7484     }
7485     if (zone_short_id != rhs.zone_short_id) {
7486       return (zone_short_id < rhs.zone_short_id);
7487     }
7488     return (pg_ver < rhs.pg_ver);
7489   }
7490
7491   void init(const real_time& _mtime, uint32_t _short_id, uint64_t _pg_ver) {
7492     mtime = _mtime;
7493     zone_short_id = _short_id;
7494     pg_ver = _pg_ver;
7495   }
7496
7497   void init(RGWObjState *state) {
7498     mtime = state->mtime;
7499     zone_short_id = state->zone_short_id;
7500     pg_ver = state->pg_ver;
7501   }
7502 };
7503
7504 inline ostream& operator<<(ostream& out, const obj_time_weight &o) {
7505   out << o.mtime;
7506
7507   if (o.zone_short_id != 0 || o.pg_ver != 0) {
7508     out << "[zid=" << o.zone_short_id << ", pgv=" << o.pg_ver << "]";
7509   }
7510
7511   return out;
7512 }
7513
7514 class RGWGetExtraDataCB : public RGWGetDataCB {
7515   bufferlist extra_data;
7516 public:
7517   RGWGetExtraDataCB() {}
7518   int handle_data(bufferlist& bl, off_t bl_ofs, off_t bl_len) override {
7519     if (extra_data.length() < extra_data_len) {
7520       off_t max = extra_data_len - extra_data.length();
7521       if (max > bl_len) {
7522         max = bl_len;
7523       }
7524       bl.splice(0, max, &extra_data);
7525     }
7526     return bl_len;
7527   }
7528
7529   bufferlist& get_extra_data() {
7530     return extra_data;
7531   }
7532 };
7533
7534 int RGWRados::stat_remote_obj(RGWObjectCtx& obj_ctx,
7535                const rgw_user& user_id,
7536                const string& client_id,
7537                req_info *info,
7538                const string& source_zone,
7539                rgw_obj& src_obj,
7540                RGWBucketInfo& src_bucket_info,
7541                real_time *src_mtime,
7542                uint64_t *psize,
7543                const real_time *mod_ptr,
7544                const real_time *unmod_ptr,
7545                bool high_precision_time,
7546                const char *if_match,
7547                const char *if_nomatch,
7548                map<string, bufferlist> *pattrs,
7549                string *version_id,
7550                string *ptag,
7551                string *petag)
7552 {
7553   /* source is in a different zonegroup, copy from there */
7554
7555   RGWRESTStreamRWRequest *in_stream_req;
7556   string tag;
7557   map<string, bufferlist> src_attrs;
7558   append_rand_alpha(cct, tag, tag, 32);
7559   obj_time_weight set_mtime_weight;
7560   set_mtime_weight.high_precision = high_precision_time;
7561
7562   RGWRESTConn *conn;
7563   if (source_zone.empty()) {
7564     if (src_bucket_info.zonegroup.empty()) {
7565       /* source is in the master zonegroup */
7566       conn = rest_master_conn;
7567     } else {
7568       map<string, RGWRESTConn *>::iterator iter = zonegroup_conn_map.find(src_bucket_info.zonegroup);
7569       if (iter == zonegroup_conn_map.end()) {
7570         ldout(cct, 0) << "could not find zonegroup connection to zonegroup: " << source_zone << dendl;
7571         return -ENOENT;
7572       }
7573       conn = iter->second;
7574     }
7575   } else {
7576     map<string, RGWRESTConn *>::iterator iter = zone_conn_map.find(source_zone);
7577     if (iter == zone_conn_map.end()) {
7578       ldout(cct, 0) << "could not find zone connection to zone: " << source_zone << dendl;
7579       return -ENOENT;
7580     }
7581     conn = iter->second;
7582   }
7583
7584   RGWGetExtraDataCB cb;
7585   string etag;
7586   map<string, string> req_headers;
7587   real_time set_mtime;
7588
7589   const real_time *pmod = mod_ptr;
7590
7591   obj_time_weight dest_mtime_weight;
7592
7593   constexpr bool prepend_meta = true;
7594   constexpr bool get_op = true;
7595   constexpr bool rgwx_stat = true;
7596   constexpr bool sync_manifest = true;
7597   constexpr bool skip_decrypt = true;
7598   int ret = conn->get_obj(user_id, info, src_obj, pmod, unmod_ptr,
7599                       dest_mtime_weight.zone_short_id, dest_mtime_weight.pg_ver,
7600                       prepend_meta, get_op, rgwx_stat,
7601                       sync_manifest, skip_decrypt, &cb, &in_stream_req);
7602   if (ret < 0) {
7603     return ret;
7604   }
7605
7606   ret = conn->complete_request(in_stream_req, etag, &set_mtime, psize, req_headers);
7607   if (ret < 0) {
7608     return ret;
7609   }
7610
7611   bufferlist& extra_data_bl = cb.get_extra_data();
7612   if (extra_data_bl.length()) {
7613     JSONParser jp;
7614     if (!jp.parse(extra_data_bl.c_str(), extra_data_bl.length())) {
7615       ldout(cct, 0) << "failed to parse response extra data. len=" << extra_data_bl.length() << " data=" << extra_data_bl.c_str() << dendl;
7616       return -EIO;
7617     }
7618
7619     JSONDecoder::decode_json("attrs", src_attrs, &jp);
7620
7621     src_attrs.erase(RGW_ATTR_MANIFEST); // not interested in original object layout
7622   }
7623
7624   if (src_mtime) {
7625     *src_mtime = set_mtime;
7626   }
7627
7628   if (petag) {
7629     map<string, bufferlist>::iterator iter = src_attrs.find(RGW_ATTR_ETAG);
7630     if (iter != src_attrs.end()) {
7631       bufferlist& etagbl = iter->second;
7632       *petag = etagbl.to_str();
7633     }
7634   }
7635
7636   if (pattrs) {
7637     *pattrs = src_attrs;
7638   }
7639
7640   return 0;
7641 }
7642
7643 int RGWRados::fetch_remote_obj(RGWObjectCtx& obj_ctx,
7644                const rgw_user& user_id,
7645                const string& client_id,
7646                const string& op_id,
7647                bool record_op_state,
7648                req_info *info,
7649                const string& source_zone,
7650                rgw_obj& dest_obj,
7651                rgw_obj& src_obj,
7652                RGWBucketInfo& dest_bucket_info,
7653                RGWBucketInfo& src_bucket_info,
7654                real_time *src_mtime,
7655                real_time *mtime,
7656                const real_time *mod_ptr,
7657                const real_time *unmod_ptr,
7658                bool high_precision_time,
7659                const char *if_match,
7660                const char *if_nomatch,
7661                AttrsMod attrs_mod,
7662                bool copy_if_newer,
7663                map<string, bufferlist>& attrs,
7664                RGWObjCategory category,
7665                uint64_t olh_epoch,
7666                real_time delete_at,
7667                string *version_id,
7668                string *ptag,
7669                ceph::buffer::list *petag,
7670                void (*progress_cb)(off_t, void *),
7671                void *progress_data,
7672                rgw_zone_set *zones_trace)
7673 {
7674   /* source is in a different zonegroup, copy from there */
7675
7676   RGWRESTStreamRWRequest *in_stream_req;
7677   string tag;
7678   int i;
7679   append_rand_alpha(cct, tag, tag, 32);
7680   obj_time_weight set_mtime_weight;
7681   set_mtime_weight.high_precision = high_precision_time;
7682
7683   RGWPutObjProcessor_Atomic processor(obj_ctx,
7684                                       dest_bucket_info, dest_obj.bucket, dest_obj.key.name,
7685                                       cct->_conf->rgw_obj_stripe_size, tag, dest_bucket_info.versioning_enabled());
7686   if (version_id && *version_id != "null") {
7687     processor.set_version_id(*version_id);
7688   }
7689   processor.set_olh_epoch(olh_epoch);
7690   int ret = processor.prepare(this, NULL);
7691   if (ret < 0) {
7692     return ret;
7693   }
7694
7695   RGWRESTConn *conn;
7696   if (source_zone.empty()) {
7697     if (dest_bucket_info.zonegroup.empty()) {
7698       /* source is in the master zonegroup */
7699       conn = rest_master_conn;
7700     } else {
7701       map<string, RGWRESTConn *>::iterator iter = zonegroup_conn_map.find(src_bucket_info.zonegroup);
7702       if (iter == zonegroup_conn_map.end()) {
7703         ldout(cct, 0) << "could not find zonegroup connection to zonegroup: " << source_zone << dendl;
7704         return -ENOENT;
7705       }
7706       conn = iter->second;
7707     }
7708   } else {
7709     map<string, RGWRESTConn *>::iterator iter = zone_conn_map.find(source_zone);
7710     if (iter == zone_conn_map.end()) {
7711       ldout(cct, 0) << "could not find zone connection to zone: " << source_zone << dendl;
7712       return -ENOENT;
7713     }
7714     conn = iter->second;
7715   }
7716
7717   string obj_name = dest_obj.bucket.name + "/" + dest_obj.get_oid();
7718
7719   RGWOpStateSingleOp *opstate = NULL;
7720
7721   if (record_op_state) {
7722     opstate = new RGWOpStateSingleOp(this, client_id, op_id, obj_name);
7723
7724     ret = opstate->set_state(RGWOpState::OPSTATE_IN_PROGRESS);
7725     if (ret < 0) {
7726       ldout(cct, 0) << "ERROR: failed to set opstate ret=" << ret << dendl;
7727       delete opstate;
7728       return ret;
7729     }
7730   }
7731
7732   boost::optional<RGWPutObj_Compress> compressor;
7733   CompressorRef plugin;
7734
7735   const auto& compression_type = zone_params.get_compression_type(
7736       dest_bucket_info.placement_rule);
7737   if (compression_type != "none") {
7738     plugin = Compressor::create(cct, compression_type);
7739     if (!plugin) {
7740       ldout(cct, 1) << "Cannot load plugin for compression type "
7741           << compression_type << dendl;
7742     }
7743   }
7744
7745   RGWRadosPutObj cb(cct, plugin, compressor, &processor, opstate, progress_cb, progress_data);
7746
7747   string etag;
7748   map<string, string> req_headers;
7749   real_time set_mtime;
7750
7751   RGWObjState *dest_state = NULL;
7752
7753   const real_time *pmod = mod_ptr;
7754
7755   obj_time_weight dest_mtime_weight;
7756
7757   if (copy_if_newer) {
7758     /* need to get mtime for destination */
7759     ret = get_obj_state(&obj_ctx, dest_bucket_info, dest_obj, &dest_state, false);
7760     if (ret < 0)
7761       goto set_err_state;
7762
7763     if (!real_clock::is_zero(dest_state->mtime)) {
7764       dest_mtime_weight.init(dest_state);
7765       pmod = &dest_mtime_weight.mtime;
7766     }
7767   }
7768
7769   static constexpr bool prepend_meta = true;
7770   static constexpr bool get_op = true;
7771   static constexpr bool rgwx_stat = false;
7772   static constexpr bool sync_manifest = true;
7773   static constexpr bool skip_decrypt = true;
7774   ret = conn->get_obj(user_id, info, src_obj, pmod, unmod_ptr,
7775                       dest_mtime_weight.zone_short_id, dest_mtime_weight.pg_ver,
7776                       prepend_meta, get_op, rgwx_stat,
7777                       sync_manifest, skip_decrypt, &cb, &in_stream_req);
7778   if (ret < 0) {
7779     goto set_err_state;
7780   }
7781
7782   ret = conn->complete_request(in_stream_req, etag, &set_mtime, nullptr, req_headers);
7783   if (ret < 0) {
7784     goto set_err_state;
7785   }
7786   if (compressor && compressor->is_compressed()) {
7787     bufferlist tmp;
7788     RGWCompressionInfo cs_info;
7789     cs_info.compression_type = plugin->get_type_name();
7790     cs_info.orig_size = cb.get_data_len();
7791     cs_info.blocks = move(compressor->get_compression_blocks());
7792     ::encode(cs_info, tmp);
7793     cb.get_attrs()[RGW_ATTR_COMPRESSION] = tmp;
7794   }
7795
7796   if (source_zone.empty()) { /* need to preserve expiration if copy in the same zonegroup */
7797     cb.get_attrs().erase(RGW_ATTR_DELETE_AT);
7798   } else {
7799     map<string, bufferlist>::iterator iter = cb.get_attrs().find(RGW_ATTR_DELETE_AT);
7800     if (iter != cb.get_attrs().end()) {
7801       try {
7802         ::decode(delete_at, iter->second);
7803       } catch (buffer::error& err) {
7804         ldout(cct, 0) << "ERROR: failed to decode delete_at field in intra zone copy" << dendl;
7805       }
7806     }
7807   }
7808
7809   if (src_mtime) {
7810     *src_mtime = set_mtime;
7811   }
7812
7813   if (petag) {
7814     const auto iter = cb.get_attrs().find(RGW_ATTR_ETAG);
7815     if (iter != cb.get_attrs().end()) {
7816       *petag = iter->second;
7817     }
7818   }
7819
7820   if (source_zone.empty()) {
7821     set_copy_attrs(cb.get_attrs(), attrs, attrs_mod);
7822   } else {
7823     attrs = cb.get_attrs();
7824   }
7825
7826   if (copy_if_newer) {
7827     uint64_t pg_ver = 0;
7828     auto i = attrs.find(RGW_ATTR_PG_VER);
7829     if (i != attrs.end() && i->second.length() > 0) {
7830       bufferlist::iterator iter = i->second.begin();
7831       try {
7832         ::decode(pg_ver, iter);
7833       } catch (buffer::error& err) {
7834         ldout(ctx(), 0) << "ERROR: failed to decode pg ver attribute, ignoring" << dendl;
7835         /* non critical error */
7836       }
7837     }
7838     set_mtime_weight.init(set_mtime, get_zone_short_id(), pg_ver);
7839   }
7840
7841 #define MAX_COMPLETE_RETRY 100
7842   for (i = 0; i < MAX_COMPLETE_RETRY; i++) {
7843     ret = cb.complete(etag, mtime, set_mtime, attrs, delete_at, zones_trace);
7844     if (ret < 0) {
7845       goto set_err_state;
7846     }
7847     if (copy_if_newer && cb.is_canceled()) {
7848       ldout(cct, 20) << "raced with another write of obj: " << dest_obj << dendl;
7849       obj_ctx.obj.invalidate(dest_obj); /* object was overwritten */
7850       ret = get_obj_state(&obj_ctx, dest_bucket_info, dest_obj, &dest_state, false);
7851       if (ret < 0) {
7852         ldout(cct, 0) << "ERROR: " << __func__ << ": get_err_state() returned ret=" << ret << dendl;
7853         goto set_err_state;
7854       }
7855       dest_mtime_weight.init(dest_state);
7856       dest_mtime_weight.high_precision = high_precision_time;
7857       if (!dest_state->exists ||
7858         dest_mtime_weight < set_mtime_weight) {
7859         ldout(cct, 20) << "retrying writing object mtime=" << set_mtime << " dest_state->mtime=" << dest_state->mtime << " dest_state->exists=" << dest_state->exists << dendl;
7860         continue;
7861       } else {
7862         ldout(cct, 20) << "not retrying writing object mtime=" << set_mtime << " dest_state->mtime=" << dest_state->mtime << " dest_state->exists=" << dest_state->exists << dendl;
7863       }
7864     }
7865     break;
7866   }
7867
7868   if (i == MAX_COMPLETE_RETRY) {
7869     ldout(cct, 0) << "ERROR: retried object completion too many times, something is wrong!" << dendl;
7870     ret = -EIO;
7871     goto set_err_state;
7872   }
7873
7874   if (opstate) {
7875     ret = opstate->set_state(RGWOpState::OPSTATE_COMPLETE);
7876     if (ret < 0) {
7877       ldout(cct, 0) << "ERROR: failed to set opstate ret=" << ret << dendl;
7878     }
7879     delete opstate;
7880   }
7881
7882   return 0;
7883 set_err_state:
7884   if (copy_if_newer && ret == -ERR_NOT_MODIFIED) {
7885     ret = 0;
7886   }
7887   if (opstate) {
7888     RGWOpState::OpState state;
7889     if (ret < 0) {
7890       state = RGWOpState::OPSTATE_ERROR;
7891     } else {
7892       state = RGWOpState::OPSTATE_COMPLETE;
7893     }
7894     int r = opstate->set_state(state);
7895     if (r < 0) {
7896       ldout(cct, 0) << "ERROR: failed to set opstate r=" << ret << dendl;
7897     }
7898     delete opstate;
7899   }
7900   return ret;
7901 }
7902
7903
7904 int RGWRados::copy_obj_to_remote_dest(RGWObjState *astate,
7905                                       map<string, bufferlist>& src_attrs,
7906                                       RGWRados::Object::Read& read_op,
7907                                       const rgw_user& user_id,
7908                                       rgw_obj& dest_obj,
7909                                       real_time *mtime)
7910 {
7911   string etag;
7912
7913   RGWRESTStreamWriteRequest *out_stream_req;
7914
7915   int ret = rest_master_conn->put_obj_init(user_id, dest_obj, astate->size, src_attrs, &out_stream_req);
7916   if (ret < 0) {
7917     return ret;
7918   }
7919
7920   ret = read_op.iterate(0, astate->size - 1, out_stream_req->get_out_cb());
7921   if (ret < 0) {
7922     delete out_stream_req;
7923     return ret;
7924   }
7925
7926   ret = rest_master_conn->complete_request(out_stream_req, etag, mtime);
7927   if (ret < 0)
7928     return ret;
7929
7930   return 0;
7931 }
7932
7933 /**
7934  * Copy an object.
7935  * dest_obj: the object to copy into
7936  * src_obj: the object to copy from
7937  * attrs: usage depends on attrs_mod parameter
7938  * attrs_mod: the modification mode of the attrs, may have the following values:
7939  *            ATTRSMOD_NONE - the attributes of the source object will be
7940  *                            copied without modifications, attrs parameter is ignored;
7941  *            ATTRSMOD_REPLACE - new object will have the attributes provided by attrs
7942  *                               parameter, source object attributes are not copied;
7943  *            ATTRSMOD_MERGE - any conflicting meta keys on the source object's attributes
7944  *                             are overwritten by values contained in attrs parameter.
7945  * err: stores any errors resulting from the get of the original object
7946  * Returns: 0 on success, -ERR# otherwise.
7947  */
7948 int RGWRados::copy_obj(RGWObjectCtx& obj_ctx,
7949                const rgw_user& user_id,
7950                const string& client_id,
7951                const string& op_id,
7952                req_info *info,
7953                const string& source_zone,
7954                rgw_obj& dest_obj,
7955                rgw_obj& src_obj,
7956                RGWBucketInfo& dest_bucket_info,
7957                RGWBucketInfo& src_bucket_info,
7958                real_time *src_mtime,
7959                real_time *mtime,
7960                const real_time *mod_ptr,
7961                const real_time *unmod_ptr,
7962                bool high_precision_time,
7963                const char *if_match,
7964                const char *if_nomatch,
7965                AttrsMod attrs_mod,
7966                bool copy_if_newer,
7967                map<string, bufferlist>& attrs,
7968                RGWObjCategory category,
7969                uint64_t olh_epoch,
7970                real_time delete_at,
7971                string *version_id,
7972                string *ptag,
7973                ceph::buffer::list *petag,
7974                void (*progress_cb)(off_t, void *),
7975                void *progress_data)
7976 {
7977   int ret;
7978   uint64_t obj_size;
7979   rgw_obj shadow_obj = dest_obj;
7980   string shadow_oid;
7981
7982   bool remote_src;
7983   bool remote_dest;
7984
7985   append_rand_alpha(cct, dest_obj.get_oid(), shadow_oid, 32);
7986   shadow_obj.init_ns(dest_obj.bucket, shadow_oid, shadow_ns);
7987
7988   remote_dest = !get_zonegroup().equals(dest_bucket_info.zonegroup);
7989   remote_src = !get_zonegroup().equals(src_bucket_info.zonegroup);
7990
7991   if (remote_src && remote_dest) {
7992     ldout(cct, 0) << "ERROR: can't copy object when both src and dest buckets are remote" << dendl;
7993     return -EINVAL;
7994   }
7995
7996   ldout(cct, 5) << "Copy object " << src_obj.bucket << ":" << src_obj.get_oid() << " => " << dest_obj.bucket << ":" << dest_obj.get_oid() << dendl;
7997
7998   if (remote_src || !source_zone.empty()) {
7999     return fetch_remote_obj(obj_ctx, user_id, client_id, op_id, true, info, source_zone,
8000                dest_obj, src_obj, dest_bucket_info, src_bucket_info, src_mtime, mtime, mod_ptr,
8001                unmod_ptr, high_precision_time,
8002                if_match, if_nomatch, attrs_mod, copy_if_newer, attrs, category,
8003                olh_epoch, delete_at, version_id, ptag, petag, progress_cb, progress_data);
8004   }
8005
8006   map<string, bufferlist> src_attrs;
8007   RGWRados::Object src_op_target(this, src_bucket_info, obj_ctx, src_obj);
8008   RGWRados::Object::Read read_op(&src_op_target);
8009
8010   read_op.conds.mod_ptr = mod_ptr;
8011   read_op.conds.unmod_ptr = unmod_ptr;
8012   read_op.conds.high_precision_time = high_precision_time;
8013   read_op.conds.if_match = if_match;
8014   read_op.conds.if_nomatch = if_nomatch;
8015   read_op.params.attrs = &src_attrs;
8016   read_op.params.lastmod = src_mtime;
8017   read_op.params.obj_size = &obj_size;
8018
8019   ret = read_op.prepare();
8020   if (ret < 0) {
8021     return ret;
8022   }
8023
8024   src_attrs[RGW_ATTR_ACL] = attrs[RGW_ATTR_ACL];
8025   src_attrs.erase(RGW_ATTR_DELETE_AT);
8026
8027   set_copy_attrs(src_attrs, attrs, attrs_mod);
8028   attrs.erase(RGW_ATTR_ID_TAG);
8029   attrs.erase(RGW_ATTR_PG_VER);
8030   attrs.erase(RGW_ATTR_SOURCE_ZONE);
8031   map<string, bufferlist>::iterator cmp = src_attrs.find(RGW_ATTR_COMPRESSION);
8032   if (cmp != src_attrs.end())
8033     attrs[RGW_ATTR_COMPRESSION] = cmp->second;
8034
8035   RGWObjManifest manifest;
8036   RGWObjState *astate = NULL;
8037
8038   ret = get_obj_state(&obj_ctx, src_bucket_info, src_obj, &astate);
8039   if (ret < 0) {
8040     return ret;
8041   }
8042
8043   vector<rgw_raw_obj> ref_objs;
8044
8045   if (remote_dest) {
8046     /* dest is in a different zonegroup, copy it there */
8047     return copy_obj_to_remote_dest(astate, attrs, read_op, user_id, dest_obj, mtime);
8048   }
8049   uint64_t max_chunk_size;
8050
8051   ret = get_max_chunk_size(dest_bucket_info.placement_rule, dest_obj, &max_chunk_size);
8052   if (ret < 0) {
8053     ldout(cct, 0) << "ERROR: failed to get max_chunk_size() for bucket " << dest_obj.bucket << dendl;
8054     return ret;
8055   }
8056
8057   rgw_pool src_pool;
8058   rgw_pool dest_pool;
8059   if (!get_obj_data_pool(src_bucket_info.placement_rule, src_obj, &src_pool)) {
8060     ldout(cct, 0) << "ERROR: failed to locate data pool for " << src_obj << dendl;
8061     return -EIO;
8062   }
8063   if (!get_obj_data_pool(dest_bucket_info.placement_rule, dest_obj, &dest_pool)) {
8064     ldout(cct, 0) << "ERROR: failed to locate data pool for " << dest_obj << dendl;
8065     return -EIO;
8066   }
8067
8068
8069   bool copy_data = !astate->has_manifest || (src_pool != dest_pool);
8070   bool copy_first = false;
8071   if (astate->has_manifest) {
8072     if (!astate->manifest.has_tail()) {
8073       copy_data = true;
8074     } else {
8075       uint64_t head_size = astate->manifest.get_head_size();
8076
8077       if (head_size > 0) {
8078         if (head_size > max_chunk_size) {
8079           copy_data = true;
8080         } else {
8081           copy_first = true;
8082         }
8083       }
8084     }
8085   }
8086
8087   if (petag) {
8088     const auto iter = attrs.find(RGW_ATTR_ETAG);
8089     if (iter != attrs.end()) {
8090       *petag = iter->second;
8091     }
8092   }
8093
8094   if (copy_data) { /* refcounting tail wouldn't work here, just copy the data */
8095     return copy_obj_data(obj_ctx, dest_bucket_info, read_op, obj_size - 1, dest_obj, src_obj,
8096                          max_chunk_size, mtime, real_time(), attrs, category, olh_epoch, delete_at,
8097                          version_id, ptag, petag);
8098   }
8099
8100   RGWObjManifest::obj_iterator miter = astate->manifest.obj_begin();
8101
8102   if (copy_first) { // we need to copy first chunk, not increase refcount
8103     ++miter;
8104   }
8105
8106   rgw_rados_ref ref;
8107   ret = get_raw_obj_ref(miter.get_location().get_raw_obj(this), &ref);
8108   if (ret < 0) {
8109     return ret;
8110   }
8111
8112   bool versioned_dest = dest_bucket_info.versioning_enabled();
8113
8114   if (version_id && !version_id->empty()) {
8115     versioned_dest = true;
8116     dest_obj.key.set_instance(*version_id);
8117   } else if (versioned_dest) {
8118     gen_rand_obj_instance_name(&dest_obj);
8119   }
8120
8121   bufferlist first_chunk;
8122
8123   bool copy_itself = (dest_obj == src_obj);
8124   RGWObjManifest *pmanifest; 
8125   ldout(cct, 20) << "dest_obj=" << dest_obj << " src_obj=" << src_obj << " copy_itself=" << (int)copy_itself << dendl;
8126
8127   RGWRados::Object dest_op_target(this, dest_bucket_info, obj_ctx, dest_obj);
8128   RGWRados::Object::Write write_op(&dest_op_target);
8129
8130   string tag;
8131
8132   if (ptag) {
8133     tag = *ptag;
8134   }
8135
8136   if (tag.empty()) {
8137     append_rand_alpha(cct, tag, tag, 32);
8138   }
8139
8140   if (!copy_itself) {
8141     attrs.erase(RGW_ATTR_TAIL_TAG);
8142     manifest = astate->manifest;
8143     const rgw_bucket_placement& tail_placement = manifest.get_tail_placement();
8144     if (tail_placement.bucket.name.empty()) {
8145       manifest.set_tail_placement(tail_placement.placement_rule, src_obj.bucket);
8146     }
8147     string ref_tag;
8148     for (; miter != astate->manifest.obj_end(); ++miter) {
8149       ObjectWriteOperation op;
8150       ref_tag = tag + '\0';
8151       cls_refcount_get(op, ref_tag, true);
8152       const rgw_raw_obj& loc = miter.get_location().get_raw_obj(this);
8153       ref.ioctx.locator_set_key(loc.loc);
8154
8155       ret = ref.ioctx.operate(loc.oid, &op);
8156       if (ret < 0) {
8157         goto done_ret;
8158       }
8159
8160       ref_objs.push_back(loc);
8161     }
8162
8163     pmanifest = &manifest;
8164   } else {
8165     pmanifest = &astate->manifest;
8166     /* don't send the object's tail for garbage collection */
8167     astate->keep_tail = true;
8168   }
8169
8170   if (copy_first) {
8171     ret = read_op.read(0, max_chunk_size, first_chunk);
8172     if (ret < 0) {
8173       goto done_ret;
8174     }
8175
8176     pmanifest->set_head(dest_bucket_info.placement_rule, dest_obj, first_chunk.length());
8177   } else {
8178     pmanifest->set_head(dest_bucket_info.placement_rule, dest_obj, 0);
8179   }
8180
8181   write_op.meta.data = &first_chunk;
8182   write_op.meta.manifest = pmanifest;
8183   write_op.meta.ptag = &tag;
8184   write_op.meta.owner = dest_bucket_info.owner;
8185   write_op.meta.mtime = mtime;
8186   write_op.meta.flags = PUT_OBJ_CREATE;
8187   write_op.meta.category = category;
8188   write_op.meta.olh_epoch = olh_epoch;
8189   write_op.meta.delete_at = delete_at;
8190   write_op.meta.modify_tail = !copy_itself;
8191
8192   ret = write_op.write_meta(obj_size, astate->accounted_size, attrs);
8193   if (ret < 0) {
8194     goto done_ret;
8195   }
8196
8197   return 0;
8198
8199 done_ret:
8200   if (!copy_itself) {
8201     vector<rgw_raw_obj>::iterator riter;
8202
8203     /* rollback reference */
8204     for (riter = ref_objs.begin(); riter != ref_objs.end(); ++riter) {
8205       ObjectWriteOperation op;
8206       cls_refcount_put(op, tag, true);
8207
8208       ref.ioctx.locator_set_key(riter->loc);
8209
8210       int r = ref.ioctx.operate(riter->oid, &op);
8211       if (r < 0) {
8212         ldout(cct, 0) << "ERROR: cleanup after error failed to drop reference on obj=" << *riter << dendl;
8213       }
8214     }
8215   }
8216   return ret;
8217 }
8218
8219
8220 int RGWRados::copy_obj_data(RGWObjectCtx& obj_ctx,
8221                RGWBucketInfo& dest_bucket_info,
8222                RGWRados::Object::Read& read_op, off_t end,
8223                rgw_obj& dest_obj,
8224                rgw_obj& src_obj,
8225                uint64_t max_chunk_size,
8226                real_time *mtime,
8227                real_time set_mtime,
8228                map<string, bufferlist>& attrs,
8229                RGWObjCategory category,
8230                uint64_t olh_epoch,
8231                real_time delete_at,
8232                string *version_id,
8233                string *ptag,
8234                ceph::buffer::list *petag)
8235 {
8236   bufferlist first_chunk;
8237   RGWObjManifest manifest;
8238
8239   string tag;
8240   append_rand_alpha(cct, tag, tag, 32);
8241
8242   RGWPutObjProcessor_Atomic processor(obj_ctx,
8243                                       dest_bucket_info, dest_obj.bucket, dest_obj.get_oid(),
8244                                       cct->_conf->rgw_obj_stripe_size, tag, dest_bucket_info.versioning_enabled());
8245   if (version_id) {
8246     processor.set_version_id(*version_id);
8247   }
8248   processor.set_olh_epoch(olh_epoch);
8249   int ret = processor.prepare(this, NULL);
8250   if (ret < 0)
8251     return ret;
8252
8253   off_t ofs = 0;
8254
8255   do {
8256     bufferlist bl;
8257     ret = read_op.read(ofs, end, bl);
8258
8259     uint64_t read_len = ret;
8260     bool again;
8261
8262     do {
8263       void *handle;
8264       rgw_raw_obj obj;
8265
8266       ret = processor.handle_data(bl, ofs, &handle, &obj, &again);
8267       if (ret < 0) {
8268         return ret;
8269       }
8270       ret = processor.throttle_data(handle, obj, read_len, false);
8271       if (ret < 0)
8272         return ret;
8273     } while (again);
8274
8275     ofs += read_len;
8276   } while (ofs <= end);
8277
8278   string etag;
8279   auto iter = attrs.find(RGW_ATTR_ETAG);
8280   if (iter != attrs.end()) {
8281     bufferlist& bl = iter->second;
8282     etag = string(bl.c_str(), bl.length());
8283     if (petag) {
8284       *petag = bl;
8285     }
8286   }
8287
8288   uint64_t accounted_size;
8289   {
8290     bool compressed{false};
8291     RGWCompressionInfo cs_info;
8292     ret = rgw_compression_info_from_attrset(attrs, compressed, cs_info);
8293     if (ret < 0) {
8294       ldout(cct, 0) << "ERROR: failed to read compression info" << dendl;
8295       return ret;
8296     }
8297     // pass original size if compressed
8298     accounted_size = compressed ? cs_info.orig_size : ofs;
8299   }
8300
8301   return processor.complete(accounted_size, etag, mtime, set_mtime, attrs, delete_at);
8302 }
8303
8304 bool RGWRados::is_meta_master()
8305 {
8306   if (!get_zonegroup().is_master_zonegroup()) {
8307     return false;
8308   }
8309
8310   return (get_zonegroup().master_zone == zone_public_config.id);
8311 }
8312
8313 /**
8314   * Check to see if the bucket metadata could be synced
8315   * bucket: the bucket to check
8316   * Returns false is the bucket is not synced
8317   */
8318 bool RGWRados::is_syncing_bucket_meta(const rgw_bucket& bucket)
8319 {
8320
8321   /* no current period  */
8322   if (current_period.get_id().empty()) {
8323     return false;
8324   }
8325
8326   /* zonegroup is not master zonegroup */
8327   if (!get_zonegroup().is_master_zonegroup()) {
8328     return false;
8329   }
8330
8331   /* single zonegroup and a single zone */
8332   if (current_period.is_single_zonegroup() && get_zonegroup().zones.size() == 1) {
8333     return false;
8334   }
8335
8336   /* zone is not master */
8337   if (get_zonegroup().master_zone.compare(zone_public_config.id) != 0) {
8338     return false;
8339   }
8340
8341   return true;
8342 }
8343
8344 int RGWRados::check_bucket_empty(RGWBucketInfo& bucket_info)
8345 {
8346   std::map<string, rgw_bucket_dir_entry> ent_map;
8347   rgw_obj_index_key marker;
8348   string prefix;
8349   bool is_truncated;
8350
8351   do {
8352 #define NUM_ENTRIES 1000
8353     int r = cls_bucket_list(bucket_info, RGW_NO_SHARD, marker, prefix, NUM_ENTRIES, true, ent_map,
8354                         &is_truncated, &marker);
8355     if (r < 0)
8356       return r;
8357
8358     string ns;
8359     std::map<string, rgw_bucket_dir_entry>::iterator eiter;
8360     for (eiter = ent_map.begin(); eiter != ent_map.end(); ++eiter) {
8361       rgw_obj_key obj;
8362
8363       if (rgw_obj_key::oid_to_key_in_ns(eiter->second.key.name, &obj, ns))
8364         return -ENOTEMPTY;
8365     }
8366   } while (is_truncated);
8367   return 0;
8368 }
8369   
8370 /**
8371  * Delete a bucket.
8372  * bucket: the name of the bucket to delete
8373  * Returns 0 on success, -ERR# otherwise.
8374  */
8375 int RGWRados::delete_bucket(RGWBucketInfo& bucket_info, RGWObjVersionTracker& objv_tracker, bool check_empty)
8376 {
8377   const rgw_bucket& bucket = bucket_info.bucket;
8378   librados::IoCtx index_ctx;
8379   map<int, string> bucket_objs;
8380   int r = open_bucket_index(bucket_info, index_ctx, bucket_objs);
8381   if (r < 0)
8382     return r;
8383   
8384   if (check_empty) {
8385     r = check_bucket_empty(bucket_info);
8386     if (r < 0) {
8387       return r;
8388     }
8389   }
8390   
8391   r = rgw_bucket_delete_bucket_obj(this, bucket.tenant, bucket.name, objv_tracker);
8392   if (r < 0)
8393     return r;
8394
8395   /* if the bucket is not synced we can remove the meta file */
8396   if (!is_syncing_bucket_meta(bucket)) {
8397     RGWObjVersionTracker objv_tracker;
8398     string entry = bucket.get_key();
8399     r= rgw_bucket_instance_remove_entry(this, entry, &objv_tracker);
8400     if (r < 0) {
8401       return r;
8402     }
8403     /* remove bucket index objects*/
8404     map<int, string>::const_iterator biter;
8405     for (biter = bucket_objs.begin(); biter != bucket_objs.end(); ++biter) {
8406       index_ctx.remove(biter->second);
8407     }
8408   }
8409   return 0;
8410 }
8411
8412 int RGWRados::set_bucket_owner(rgw_bucket& bucket, ACLOwner& owner)
8413 {
8414   RGWBucketInfo info;
8415   map<string, bufferlist> attrs;
8416   RGWObjectCtx obj_ctx(this);
8417   int r;
8418   if (bucket.bucket_id.empty()) {
8419     r = get_bucket_info(obj_ctx, bucket.tenant, bucket.name, info, NULL, &attrs);
8420   } else {
8421     r = get_bucket_instance_info(obj_ctx, bucket, info, nullptr, &attrs);
8422   }
8423   if (r < 0) {
8424     ldout(cct, 0) << "NOTICE: get_bucket_info on bucket=" << bucket.name << " returned err=" << r << dendl;
8425     return r;
8426   }
8427
8428   info.owner = owner.get_id();
8429
8430   r = put_bucket_instance_info(info, false, real_time(), &attrs);
8431   if (r < 0) {
8432     ldout(cct, 0) << "NOTICE: put_bucket_info on bucket=" << bucket.name << " returned err=" << r << dendl;
8433     return r;
8434   }
8435
8436   return 0;
8437 }
8438
8439
8440 int RGWRados::set_buckets_enabled(vector<rgw_bucket>& buckets, bool enabled)
8441 {
8442   int ret = 0;
8443
8444   vector<rgw_bucket>::iterator iter;
8445
8446   for (iter = buckets.begin(); iter != buckets.end(); ++iter) {
8447     rgw_bucket& bucket = *iter;
8448     if (enabled)
8449       ldout(cct, 20) << "enabling bucket name=" << bucket.name << dendl;
8450     else
8451       ldout(cct, 20) << "disabling bucket name=" << bucket.name << dendl;
8452
8453     RGWBucketInfo info;
8454     map<string, bufferlist> attrs;
8455     RGWObjectCtx obj_ctx(this);
8456     int r = get_bucket_info(obj_ctx, bucket.tenant, bucket.name, info, NULL, &attrs);
8457     if (r < 0) {
8458       ldout(cct, 0) << "NOTICE: get_bucket_info on bucket=" << bucket.name << " returned err=" << r << ", skipping bucket" << dendl;
8459       ret = r;
8460       continue;
8461     }
8462     if (enabled) {
8463       info.flags &= ~BUCKET_SUSPENDED;
8464     } else {
8465       info.flags |= BUCKET_SUSPENDED;
8466     }
8467
8468     r = put_bucket_instance_info(info, false, real_time(), &attrs);
8469     if (r < 0) {
8470       ldout(cct, 0) << "NOTICE: put_bucket_info on bucket=" << bucket.name << " returned err=" << r << ", skipping bucket" << dendl;
8471       ret = r;
8472       continue;
8473     }
8474   }
8475   return ret;
8476 }
8477
8478 int RGWRados::bucket_suspended(rgw_bucket& bucket, bool *suspended)
8479 {
8480   RGWBucketInfo bucket_info;
8481   RGWObjectCtx obj_ctx(this);
8482   int ret = get_bucket_info(obj_ctx, bucket.tenant, bucket.name, bucket_info, NULL);
8483   if (ret < 0) {
8484     return ret;
8485   }
8486
8487   *suspended = ((bucket_info.flags & BUCKET_SUSPENDED) != 0);
8488   return 0;
8489 }
8490
8491 int RGWRados::Object::complete_atomic_modification()
8492 {
8493   if (!state->has_manifest || state->keep_tail)
8494     return 0;
8495
8496   cls_rgw_obj_chain chain;
8497   store->update_gc_chain(obj, state->manifest, &chain);
8498
8499   if (chain.empty()) {
8500     return 0;
8501   }
8502
8503   string tag = (state->tail_tag.length() > 0 ? state->tail_tag.to_str() : state->obj_tag.to_str());
8504   return store->gc->send_chain(chain, tag, false);  // do it async
8505 }
8506
8507 void RGWRados::update_gc_chain(rgw_obj& head_obj, RGWObjManifest& manifest, cls_rgw_obj_chain *chain)
8508 {
8509   RGWObjManifest::obj_iterator iter;
8510   rgw_raw_obj raw_head;
8511   obj_to_raw(manifest.get_head_placement_rule(), head_obj, &raw_head);
8512   for (iter = manifest.obj_begin(); iter != manifest.obj_end(); ++iter) {
8513     const rgw_raw_obj& mobj = iter.get_location().get_raw_obj(this);
8514     if (mobj == raw_head)
8515       continue;
8516     cls_rgw_obj_key key(mobj.oid);
8517     chain->push_obj(mobj.pool.to_str(), key, mobj.loc);
8518   }
8519 }
8520
8521 int RGWRados::send_chain_to_gc(cls_rgw_obj_chain& chain, const string& tag, bool sync)
8522 {
8523   return gc->send_chain(chain, tag, sync);
8524 }
8525
8526 int RGWRados::open_bucket_index(const RGWBucketInfo& bucket_info, librados::IoCtx& index_ctx, string& bucket_oid)
8527 {
8528   const rgw_bucket& bucket = bucket_info.bucket;
8529   int r = open_bucket_index_ctx(bucket_info, index_ctx);
8530   if (r < 0)
8531     return r;
8532
8533   if (bucket.bucket_id.empty()) {
8534     ldout(cct, 0) << "ERROR: empty bucket id for bucket operation" << dendl;
8535     return -EIO;
8536   }
8537
8538   bucket_oid = dir_oid_prefix;
8539   bucket_oid.append(bucket.bucket_id);
8540
8541   return 0;
8542 }
8543
8544 int RGWRados::open_bucket_index_base(const RGWBucketInfo& bucket_info, librados::IoCtx& index_ctx,
8545     string& bucket_oid_base) {
8546   const rgw_bucket& bucket = bucket_info.bucket;
8547   int r = open_bucket_index_ctx(bucket_info, index_ctx);
8548   if (r < 0)
8549     return r;
8550
8551   if (bucket.bucket_id.empty()) {
8552     ldout(cct, 0) << "ERROR: empty bucket_id for bucket operation" << dendl;
8553     return -EIO;
8554   }
8555
8556   bucket_oid_base = dir_oid_prefix;
8557   bucket_oid_base.append(bucket.bucket_id);
8558
8559   return 0;
8560
8561 }
8562
8563 int RGWRados::open_bucket_index(const RGWBucketInfo& bucket_info, librados::IoCtx& index_ctx,
8564     map<int, string>& bucket_objs, int shard_id, map<int, string> *bucket_instance_ids) {
8565   string bucket_oid_base;
8566   int ret = open_bucket_index_base(bucket_info, index_ctx, bucket_oid_base);
8567   if (ret < 0) {
8568     return ret;
8569   }
8570
8571   get_bucket_index_objects(bucket_oid_base, bucket_info.num_shards, bucket_objs, shard_id);
8572   if (bucket_instance_ids) {
8573     get_bucket_instance_ids(bucket_info, shard_id, bucket_instance_ids);
8574   }
8575   return 0;
8576 }
8577
8578 template<typename T>
8579 int RGWRados::open_bucket_index(const RGWBucketInfo& bucket_info, librados::IoCtx& index_ctx,
8580                                 map<int, string>& oids, map<int, T>& bucket_objs,
8581                                 int shard_id, map<int, string> *bucket_instance_ids)
8582 {
8583   int ret = open_bucket_index(bucket_info, index_ctx, oids, shard_id, bucket_instance_ids);
8584   if (ret < 0)
8585     return ret;
8586
8587   map<int, string>::const_iterator iter = oids.begin();
8588   for (; iter != oids.end(); ++iter) {
8589     bucket_objs[iter->first] = T();
8590   }
8591   return 0;
8592 }
8593
8594 int RGWRados::open_bucket_index_shard(const RGWBucketInfo& bucket_info, librados::IoCtx& index_ctx,
8595     const string& obj_key, string *bucket_obj, int *shard_id)
8596 {
8597   string bucket_oid_base;
8598   int ret = open_bucket_index_base(bucket_info, index_ctx, bucket_oid_base);
8599   if (ret < 0)
8600     return ret;
8601
8602   RGWObjectCtx obj_ctx(this);
8603
8604   ret = get_bucket_index_object(bucket_oid_base, obj_key, bucket_info.num_shards,
8605         (RGWBucketInfo::BIShardsHashType)bucket_info.bucket_index_shard_hash_type, bucket_obj, shard_id);
8606   if (ret < 0) {
8607     ldout(cct, 10) << "get_bucket_index_object() returned ret=" << ret << dendl;
8608     return ret;
8609   }
8610   return 0;
8611 }
8612
8613 int RGWRados::open_bucket_index_shard(const RGWBucketInfo& bucket_info, librados::IoCtx& index_ctx,
8614                                       int shard_id, string *bucket_obj)
8615 {
8616   string bucket_oid_base;
8617   int ret = open_bucket_index_base(bucket_info, index_ctx, bucket_oid_base);
8618   if (ret < 0)
8619     return ret;
8620
8621   RGWObjectCtx obj_ctx(this);
8622
8623   get_bucket_index_object(bucket_oid_base, bucket_info.num_shards,
8624                           shard_id, bucket_obj);
8625   return 0;
8626 }
8627
8628 static void accumulate_raw_stats(const rgw_bucket_dir_header& header,
8629                                  map<RGWObjCategory, RGWStorageStats>& stats)
8630 {
8631   for (const auto& pair : header.stats) {
8632     const RGWObjCategory category = static_cast<RGWObjCategory>(pair.first);
8633     const rgw_bucket_category_stats& header_stats = pair.second;
8634
8635     RGWStorageStats& s = stats[category];
8636
8637     s.category = category;
8638     s.size += header_stats.total_size;
8639     s.size_rounded += header_stats.total_size_rounded;
8640     s.size_utilized += header_stats.actual_size;
8641     s.num_objects += header_stats.num_entries;
8642   }
8643 }
8644
8645 int RGWRados::bucket_check_index(RGWBucketInfo& bucket_info,
8646                                  map<RGWObjCategory, RGWStorageStats> *existing_stats,
8647                                  map<RGWObjCategory, RGWStorageStats> *calculated_stats)
8648 {
8649   librados::IoCtx index_ctx;
8650   // key - bucket index object id
8651   // value - bucket index check OP returned result with the given bucket index object (shard)
8652   map<int, string> oids;
8653   map<int, struct rgw_cls_check_index_ret> bucket_objs_ret;
8654
8655   int ret = open_bucket_index(bucket_info, index_ctx, oids, bucket_objs_ret);
8656   if (ret < 0) {
8657       return ret;
8658   }
8659
8660   ret = CLSRGWIssueBucketCheck(index_ctx, oids, bucket_objs_ret, cct->_conf->rgw_bucket_index_max_aio)();
8661   if (ret < 0) {
8662       return ret;
8663   }
8664
8665   // Aggregate results (from different shards if there is any)
8666   map<int, struct rgw_cls_check_index_ret>::iterator iter;
8667   for (iter = bucket_objs_ret.begin(); iter != bucket_objs_ret.end(); ++iter) {
8668     accumulate_raw_stats(iter->second.existing_header, *existing_stats);
8669     accumulate_raw_stats(iter->second.calculated_header, *calculated_stats);
8670   }
8671
8672   return 0;
8673 }
8674
8675 int RGWRados::bucket_rebuild_index(RGWBucketInfo& bucket_info)
8676 {
8677   librados::IoCtx index_ctx;
8678   map<int, string> bucket_objs;
8679
8680   int r = open_bucket_index(bucket_info, index_ctx, bucket_objs);
8681   if (r < 0) {
8682     return r;
8683   }
8684
8685   return CLSRGWIssueBucketRebuild(index_ctx, bucket_objs, cct->_conf->rgw_bucket_index_max_aio)();
8686 }
8687
8688 int RGWRados::bucket_set_reshard(RGWBucketInfo& bucket_info, const cls_rgw_bucket_instance_entry& entry)
8689 {
8690   librados::IoCtx index_ctx;
8691   map<int, string> bucket_objs;
8692
8693   int r = open_bucket_index(bucket_info, index_ctx, bucket_objs);
8694   if (r < 0) {
8695     return r;
8696   }
8697
8698   return CLSRGWIssueSetBucketResharding(index_ctx, bucket_objs, entry, cct->_conf->rgw_bucket_index_max_aio)();
8699 }
8700
8701 int RGWRados::defer_gc(void *ctx, const RGWBucketInfo& bucket_info, const rgw_obj& obj)
8702 {
8703   RGWObjectCtx *rctx = static_cast<RGWObjectCtx *>(ctx);
8704   std::string oid, key;
8705   get_obj_bucket_and_oid_loc(obj, oid, key);
8706   if (!rctx)
8707     return 0;
8708
8709   RGWObjState *state = NULL;
8710
8711   int r = get_obj_state(rctx, bucket_info, obj, &state, false);
8712   if (r < 0)
8713     return r;
8714
8715   if (!state->is_atomic) {
8716     ldout(cct, 20) << "state for obj=" << obj << " is not atomic, not deferring gc operation" << dendl;
8717     return -EINVAL;
8718   }
8719
8720   string tag;
8721
8722   if (state->tail_tag.length() > 0) {
8723     tag = state->tail_tag.c_str();
8724   } else if (state->obj_tag.length() > 0) {
8725     tag = state->obj_tag.c_str();
8726   } else {
8727     ldout(cct, 20) << "state->obj_tag is empty, not deferring gc operation" << dendl;
8728     return -EINVAL;
8729   }
8730
8731   ldout(cct, 0) << "defer chain tag=" << tag << dendl;
8732
8733   return gc->defer_chain(tag, false);
8734 }
8735
8736 void RGWRados::remove_rgw_head_obj(ObjectWriteOperation& op)
8737 {
8738   list<string> prefixes;
8739   prefixes.push_back(RGW_ATTR_OLH_PREFIX);
8740   cls_rgw_remove_obj(op, prefixes);
8741 }
8742
8743 void RGWRados::cls_obj_check_prefix_exist(ObjectOperation& op, const string& prefix, bool fail_if_exist)
8744 {
8745   cls_rgw_obj_check_attrs_prefix(op, prefix, fail_if_exist);
8746 }
8747
8748 void RGWRados::cls_obj_check_mtime(ObjectOperation& op, const real_time& mtime, bool high_precision_time, RGWCheckMTimeType type)
8749 {
8750   cls_rgw_obj_check_mtime(op, mtime, high_precision_time, type);
8751 }
8752
8753
8754 /**
8755  * Delete an object.
8756  * bucket: name of the bucket storing the object
8757  * obj: name of the object to delete
8758  * Returns: 0 on success, -ERR# otherwise.
8759  */
8760 int RGWRados::Object::Delete::delete_obj()
8761 {
8762   RGWRados *store = target->get_store();
8763   rgw_obj& src_obj = target->get_obj();
8764   const string& instance = src_obj.key.instance;
8765   rgw_obj obj = src_obj;
8766
8767   if (instance == "null") {
8768     obj.key.instance.clear();
8769   }
8770
8771   bool explicit_marker_version = (!params.marker_version_id.empty());
8772
8773   if (params.versioning_status & BUCKET_VERSIONED || explicit_marker_version) {
8774     if (instance.empty() || explicit_marker_version) {
8775       rgw_obj marker = obj;
8776
8777       if (!params.marker_version_id.empty()) {
8778         if (params.marker_version_id != "null") {
8779           marker.key.set_instance(params.marker_version_id);
8780         }
8781       } else if ((params.versioning_status & BUCKET_VERSIONS_SUSPENDED) == 0) {
8782         store->gen_rand_obj_instance_name(&marker);
8783       }
8784
8785       result.version_id = marker.key.instance;
8786       result.delete_marker = true;
8787
8788       struct rgw_bucket_dir_entry_meta meta;
8789
8790       meta.owner = params.obj_owner.get_id().to_str();
8791       meta.owner_display_name = params.obj_owner.get_display_name();
8792
8793       if (real_clock::is_zero(params.mtime)) {
8794         meta.mtime = real_clock::now();
8795       } else {
8796         meta.mtime = params.mtime;
8797       }
8798
8799       int r = store->set_olh(target->get_ctx(), target->get_bucket_info(), marker, true, &meta, params.olh_epoch, params.unmod_since, params.high_precision_time, params.zones_trace);
8800       if (r < 0) {
8801         return r;
8802       }
8803     } else {
8804       rgw_bucket_dir_entry dirent;
8805
8806       int r = store->bi_get_instance(target->get_bucket_info(), obj, &dirent);
8807       if (r < 0) {
8808         return r;
8809       }
8810       result.delete_marker = dirent.is_delete_marker();
8811       r = store->unlink_obj_instance(target->get_ctx(), target->get_bucket_info(), obj, params.olh_epoch, params.zones_trace);
8812       if (r < 0) {
8813         return r;
8814       }
8815       result.version_id = instance;
8816     }
8817
8818     BucketShard *bs;
8819     int r = target->get_bucket_shard(&bs);
8820     if (r < 0) {
8821       ldout(store->ctx(), 5) << "failed to get BucketShard object: r=" << r << dendl;
8822       return r;
8823     }
8824
8825     if (target->bucket_info.datasync_flag_enabled()) {
8826       r = store->data_log->add_entry(bs->bucket, bs->shard_id);
8827       if (r < 0) {
8828         lderr(store->ctx()) << "ERROR: failed writing data log" << dendl;
8829         return r;
8830       }
8831     }
8832
8833     return 0;
8834   }
8835
8836   rgw_rados_ref ref;
8837   int r = store->get_obj_head_ref(target->get_bucket_info(), obj, &ref);
8838   if (r < 0) {
8839     return r;
8840   }
8841
8842   RGWObjState *state;
8843   r = target->get_state(&state, false);
8844   if (r < 0)
8845     return r;
8846
8847   ObjectWriteOperation op;
8848
8849   if (!real_clock::is_zero(params.unmod_since)) {
8850     struct timespec ctime = ceph::real_clock::to_timespec(state->mtime);
8851     struct timespec unmod = ceph::real_clock::to_timespec(params.unmod_since);
8852     if (!params.high_precision_time) {
8853       ctime.tv_nsec = 0;
8854       unmod.tv_nsec = 0;
8855     }
8856
8857     ldout(store->ctx(), 10) << "If-UnModified-Since: " << params.unmod_since << " Last-Modified: " << ctime << dendl;
8858     if (ctime > unmod) {
8859       return -ERR_PRECONDITION_FAILED;
8860     }
8861
8862     /* only delete object if mtime is less than or equal to params.unmod_since */
8863     store->cls_obj_check_mtime(op, params.unmod_since, params.high_precision_time, CLS_RGW_CHECK_TIME_MTIME_LE);
8864   }
8865   uint64_t obj_size = state->size;
8866
8867   if (!real_clock::is_zero(params.expiration_time)) {
8868     bufferlist bl;
8869     real_time delete_at;
8870
8871     if (state->get_attr(RGW_ATTR_DELETE_AT, bl)) {
8872       try {
8873         bufferlist::iterator iter = bl.begin();
8874         ::decode(delete_at, iter);
8875       } catch (buffer::error& err) {
8876         ldout(store->ctx(), 0) << "ERROR: couldn't decode RGW_ATTR_DELETE_AT" << dendl;
8877         return -EIO;
8878       }
8879
8880       if (params.expiration_time != delete_at) {
8881         return -ERR_PRECONDITION_FAILED;
8882       }
8883     } else {
8884       return -ERR_PRECONDITION_FAILED;
8885     }
8886   }
8887
8888   if (!state->exists) {
8889     target->invalidate_state();
8890     return -ENOENT;
8891   }
8892
8893   r = target->prepare_atomic_modification(op, false, NULL, NULL, NULL, true, false);
8894   if (r < 0)
8895     return r;
8896
8897   RGWBucketInfo& bucket_info = target->get_bucket_info();
8898
8899   RGWRados::Bucket bop(store, bucket_info);
8900   RGWRados::Bucket::UpdateIndex index_op(&bop, obj);
8901   
8902   index_op.set_zones_trace(params.zones_trace);
8903   index_op.set_bilog_flags(params.bilog_flags);
8904
8905   r = index_op.prepare(CLS_RGW_OP_DEL, &state->write_tag);
8906   if (r < 0)
8907     return r;
8908
8909   store->remove_rgw_head_obj(op);
8910   r = ref.ioctx.operate(ref.oid, &op);
8911   bool need_invalidate = false;
8912   if (r == -ECANCELED) {
8913     /* raced with another operation, we can regard it as removed */
8914     need_invalidate = true;
8915     r = 0;
8916   }
8917
8918   int64_t poolid = ref.ioctx.get_id();
8919   if (r >= 0) {
8920     tombstone_cache_t *obj_tombstone_cache = store->get_tombstone_cache();
8921     if (obj_tombstone_cache) {
8922       tombstone_entry entry{*state};
8923       obj_tombstone_cache->add(obj, entry);
8924     }
8925     r = index_op.complete_del(poolid, ref.ioctx.get_last_version(), state->mtime, params.remove_objs);
8926     
8927     int ret = target->complete_atomic_modification();
8928     if (ret < 0) {
8929       ldout(store->ctx(), 0) << "ERROR: complete_atomic_modification returned ret=" << ret << dendl;
8930     }
8931     /* other than that, no need to propagate error */
8932   } else {
8933     int ret = index_op.cancel();
8934     if (ret < 0) {
8935       ldout(store->ctx(), 0) << "ERROR: index_op.cancel() returned ret=" << ret << dendl;
8936     }
8937   }
8938
8939   if (need_invalidate) {
8940     target->invalidate_state();
8941   }
8942
8943   if (r < 0)
8944     return r;
8945
8946   /* update quota cache */
8947   store->quota_handler->update_stats(params.bucket_owner, obj.bucket, -1, 0, obj_size);
8948
8949   return 0;
8950 }
8951
8952 int RGWRados::delete_obj(RGWObjectCtx& obj_ctx,
8953                          const RGWBucketInfo& bucket_info,
8954                          const rgw_obj& obj,
8955                          int versioning_status,
8956                          uint16_t bilog_flags,
8957                          const real_time& expiration_time,
8958                          rgw_zone_set *zones_trace)
8959 {
8960   RGWRados::Object del_target(this, bucket_info, obj_ctx, obj);
8961   RGWRados::Object::Delete del_op(&del_target);
8962
8963   del_op.params.bucket_owner = bucket_info.owner;
8964   del_op.params.versioning_status = versioning_status;
8965   del_op.params.bilog_flags = bilog_flags;
8966   del_op.params.expiration_time = expiration_time;
8967   del_op.params.zones_trace = zones_trace;
8968
8969   return del_op.delete_obj();
8970 }
8971
8972 int RGWRados::delete_raw_obj(const rgw_raw_obj& obj)
8973 {
8974   rgw_rados_ref ref;
8975   int r = get_raw_obj_ref(obj, &ref);
8976   if (r < 0) {
8977     return r;
8978   }
8979
8980   ObjectWriteOperation op;
8981
8982   op.remove();
8983   r = ref.ioctx.operate(ref.oid, &op);
8984   if (r < 0)
8985     return r;
8986
8987   return 0;
8988 }
8989
8990 int RGWRados::delete_system_obj(rgw_raw_obj& obj, RGWObjVersionTracker *objv_tracker)
8991 {
8992   if (obj.empty()) {
8993     ldout(cct, 1) << "delete_system_obj got empty object name "
8994         << obj << ", returning EINVAL" << dendl;
8995     return -EINVAL;
8996   }
8997   rgw_rados_ref ref;
8998   int r = get_raw_obj_ref(obj, &ref);
8999   if (r < 0) {
9000     return r;
9001   }
9002
9003   ObjectWriteOperation op;
9004
9005   if (objv_tracker) {
9006     objv_tracker->prepare_op_for_write(&op);
9007   }
9008
9009   op.remove();
9010   r = ref.ioctx.operate(ref.oid, &op);
9011   if (r < 0)
9012     return r;
9013
9014   return 0;
9015 }
9016
9017 int RGWRados::delete_obj_index(const rgw_obj& obj)
9018 {
9019   std::string oid, key;
9020   get_obj_bucket_and_oid_loc(obj, oid, key);
9021
9022   RGWObjectCtx obj_ctx(this);
9023
9024   RGWBucketInfo bucket_info;
9025   int ret = get_bucket_instance_info(obj_ctx, obj.bucket, bucket_info, NULL, NULL);
9026   if (ret < 0) {
9027     ldout(cct, 0) << "ERROR: " << __func__ << "() get_bucket_instance_info(bucket=" << obj.bucket << ") returned ret=" << ret << dendl;
9028     return ret;
9029   }
9030
9031   RGWRados::Bucket bop(this, bucket_info);
9032   RGWRados::Bucket::UpdateIndex index_op(&bop, obj);
9033
9034   real_time removed_mtime;
9035   int r = index_op.complete_del(-1 /* pool */, 0, removed_mtime, NULL);
9036
9037   return r;
9038 }
9039
9040 static void generate_fake_tag(RGWRados *store, map<string, bufferlist>& attrset, RGWObjManifest& manifest, bufferlist& manifest_bl, bufferlist& tag_bl)
9041 {
9042   string tag;
9043
9044   RGWObjManifest::obj_iterator mi = manifest.obj_begin();
9045   if (mi != manifest.obj_end()) {
9046     if (manifest.has_tail()) // first object usually points at the head, let's skip to a more unique part
9047       ++mi;
9048     tag = mi.get_location().get_raw_obj(store).oid;
9049     tag.append("_");
9050   }
9051
9052   unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE];
9053   char md5_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
9054   MD5 hash;
9055   hash.Update((const byte *)manifest_bl.c_str(), manifest_bl.length());
9056
9057   map<string, bufferlist>::iterator iter = attrset.find(RGW_ATTR_ETAG);
9058   if (iter != attrset.end()) {
9059     bufferlist& bl = iter->second;
9060     hash.Update((const byte *)bl.c_str(), bl.length());
9061   }
9062
9063   hash.Final(md5);
9064   buf_to_hex(md5, CEPH_CRYPTO_MD5_DIGESTSIZE, md5_str);
9065   tag.append(md5_str);
9066
9067   ldout(store->ctx(), 10) << "generate_fake_tag new tag=" << tag << dendl;
9068
9069   tag_bl.append(tag.c_str(), tag.size() + 1);
9070 }
9071
9072 static bool is_olh(map<string, bufferlist>& attrs)
9073 {
9074   map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_OLH_INFO);
9075   return (iter != attrs.end());
9076 }
9077
9078 static bool has_olh_tag(map<string, bufferlist>& attrs)
9079 {
9080   map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_OLH_ID_TAG);
9081   return (iter != attrs.end());
9082 }
9083
9084 int RGWRados::get_olh_target_state(RGWObjectCtx& obj_ctx, const RGWBucketInfo& bucket_info, const rgw_obj& obj,
9085                                    RGWObjState *olh_state, RGWObjState **target_state)
9086 {
9087   assert(olh_state->is_olh);
9088
9089   rgw_obj target;
9090   int r = RGWRados::follow_olh(bucket_info, obj_ctx, olh_state, obj, &target); /* might return -EAGAIN */
9091   if (r < 0) {
9092     return r;
9093   }
9094   r = get_obj_state(&obj_ctx, bucket_info, target, target_state, false);
9095   if (r < 0) {
9096     return r;
9097   }
9098
9099   return 0;
9100 }
9101
9102 int RGWRados::get_system_obj_state_impl(RGWObjectCtx *rctx, rgw_raw_obj& obj, RGWRawObjState **state, RGWObjVersionTracker *objv_tracker)
9103 {
9104   if (obj.empty()) {
9105     return -EINVAL;
9106   }
9107
9108   RGWRawObjState *s = rctx->raw.get_state(obj);
9109   ldout(cct, 20) << "get_system_obj_state: rctx=" << (void *)rctx << " obj=" << obj << " state=" << (void *)s << " s->prefetch_data=" << s->prefetch_data << dendl;
9110   *state = s;
9111   if (s->has_attrs) {
9112     return 0;
9113   }
9114
9115   s->obj = obj;
9116
9117   int r = raw_obj_stat(obj, &s->size, &s->mtime, &s->epoch, &s->attrset, (s->prefetch_data ? &s->data : NULL), objv_tracker);
9118   if (r == -ENOENT) {
9119     s->exists = false;
9120     s->has_attrs = true;
9121     s->mtime = real_time();
9122     return 0;
9123   }
9124   if (r < 0)
9125     return r;
9126
9127   s->exists = true;
9128   s->has_attrs = true;
9129   s->obj_tag = s->attrset[RGW_ATTR_ID_TAG];
9130
9131   if (s->obj_tag.length())
9132     ldout(cct, 20) << "get_system_obj_state: setting s->obj_tag to "
9133                    << s->obj_tag.c_str() << dendl;
9134   else
9135     ldout(cct, 20) << "get_system_obj_state: s->obj_tag was set empty" << dendl;
9136
9137   return 0;
9138 }
9139
9140 int RGWRados::get_system_obj_state(RGWObjectCtx *rctx, rgw_raw_obj& obj, RGWRawObjState **state, RGWObjVersionTracker *objv_tracker)
9141 {
9142   int ret;
9143
9144   do {
9145     ret = get_system_obj_state_impl(rctx, obj, state, objv_tracker);
9146   } while (ret == -EAGAIN);
9147
9148   return ret;
9149 }
9150
9151 int RGWRados::get_obj_state_impl(RGWObjectCtx *rctx, const RGWBucketInfo& bucket_info, const rgw_obj& obj,
9152                                  RGWObjState **state, bool follow_olh, bool assume_noent)
9153 {
9154   if (obj.empty()) {
9155     return -EINVAL;
9156   }
9157
9158   bool need_follow_olh = follow_olh && obj.key.instance.empty();
9159
9160   RGWObjState *s = rctx->obj.get_state(obj);
9161   ldout(cct, 20) << "get_obj_state: rctx=" << (void *)rctx << " obj=" << obj << " state=" << (void *)s << " s->prefetch_data=" << s->prefetch_data << dendl;
9162   *state = s;
9163   if (s->has_attrs) {
9164     if (s->is_olh && need_follow_olh) {
9165       return get_olh_target_state(*rctx, bucket_info, obj, s, state);
9166     }
9167     return 0;
9168   }
9169
9170   s->obj = obj;
9171
9172   rgw_raw_obj raw_obj;
9173   obj_to_raw(bucket_info.placement_rule, obj, &raw_obj);
9174
9175   int r = -ENOENT;
9176
9177   if (!assume_noent) {
9178     r = RGWRados::raw_obj_stat(raw_obj, &s->size, &s->mtime, &s->epoch, &s->attrset, (s->prefetch_data ? &s->data : NULL), NULL);
9179   }
9180
9181   if (r == -ENOENT) {
9182     s->exists = false;
9183     s->has_attrs = true;
9184     tombstone_entry entry;
9185     if (obj_tombstone_cache && obj_tombstone_cache->find(obj, entry)) {
9186       s->mtime = entry.mtime;
9187       s->zone_short_id = entry.zone_short_id;
9188       s->pg_ver = entry.pg_ver;
9189       ldout(cct, 20) << __func__ << "(): found obj in tombstone cache: obj=" << obj
9190           << " mtime=" << s->mtime << " pgv=" << s->pg_ver << dendl;
9191     } else {
9192       s->mtime = real_time();
9193     }
9194     return 0;
9195   }
9196   if (r < 0)
9197     return r;
9198
9199   s->exists = true;
9200   s->has_attrs = true;
9201   s->accounted_size = s->size;
9202
9203   auto iter = s->attrset.find(RGW_ATTR_COMPRESSION);
9204   const bool compressed = (iter != s->attrset.end());
9205   if (compressed) {
9206     // use uncompressed size for accounted_size
9207     try {
9208       RGWCompressionInfo info;
9209       auto p = iter->second.begin();
9210       ::decode(info, p);
9211       s->accounted_size = info.orig_size; 
9212     } catch (buffer::error&) {
9213       dout(0) << "ERROR: could not decode compression info for object: " << obj << dendl;
9214       return -EIO;
9215     }
9216   }
9217
9218   iter = s->attrset.find(RGW_ATTR_SHADOW_OBJ);
9219   if (iter != s->attrset.end()) {
9220     bufferlist bl = iter->second;
9221     bufferlist::iterator it = bl.begin();
9222     it.copy(bl.length(), s->shadow_obj);
9223     s->shadow_obj[bl.length()] = '\0';
9224   }
9225   s->obj_tag = s->attrset[RGW_ATTR_ID_TAG];
9226   auto ttiter = s->attrset.find(RGW_ATTR_TAIL_TAG);
9227   if (ttiter != s->attrset.end()) {
9228     s->tail_tag = s->attrset[RGW_ATTR_TAIL_TAG];
9229   }
9230
9231   bufferlist manifest_bl = s->attrset[RGW_ATTR_MANIFEST];
9232   if (manifest_bl.length()) {
9233     bufferlist::iterator miter = manifest_bl.begin();
9234     try {
9235       ::decode(s->manifest, miter);
9236       s->has_manifest = true;
9237       s->manifest.set_head(bucket_info.placement_rule, obj, s->size); /* patch manifest to reflect the head we just read, some manifests might be
9238                                              broken due to old bugs */
9239       s->size = s->manifest.get_obj_size();
9240       if (!compressed)
9241         s->accounted_size = s->size;
9242     } catch (buffer::error& err) {
9243       ldout(cct, 0) << "ERROR: couldn't decode manifest" << dendl;
9244       return -EIO;
9245     }
9246     ldout(cct, 10) << "manifest: total_size = " << s->manifest.get_obj_size() << dendl;
9247     if (cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20) && s->manifest.has_explicit_objs()) {
9248       RGWObjManifest::obj_iterator mi;
9249       for (mi = s->manifest.obj_begin(); mi != s->manifest.obj_end(); ++mi) {
9250         ldout(cct, 20) << "manifest: ofs=" << mi.get_ofs() << " loc=" << mi.get_location().get_raw_obj(this) << dendl;
9251       }
9252     }
9253
9254     if (!s->obj_tag.length()) {
9255       /*
9256        * Uh oh, something's wrong, object with manifest should have tag. Let's
9257        * create one out of the manifest, would be unique
9258        */
9259       generate_fake_tag(this, s->attrset, s->manifest, manifest_bl, s->obj_tag);
9260       s->fake_tag = true;
9261     }
9262   }
9263   map<string, bufferlist>::iterator aiter = s->attrset.find(RGW_ATTR_PG_VER);
9264   if (aiter != s->attrset.end()) {
9265     bufferlist& pg_ver_bl = aiter->second;
9266     if (pg_ver_bl.length()) {
9267       bufferlist::iterator pgbl = pg_ver_bl.begin();
9268       try {
9269         ::decode(s->pg_ver, pgbl);
9270       } catch (buffer::error& err) {
9271         ldout(cct, 0) << "ERROR: couldn't decode pg ver attr for object " << s->obj << ", non-critical error, ignoring" << dendl;
9272       }
9273     }
9274   }
9275   aiter = s->attrset.find(RGW_ATTR_SOURCE_ZONE);
9276   if (aiter != s->attrset.end()) {
9277     bufferlist& zone_short_id_bl = aiter->second;
9278     if (zone_short_id_bl.length()) {
9279       bufferlist::iterator zbl = zone_short_id_bl.begin();
9280       try {
9281         ::decode(s->zone_short_id, zbl);
9282       } catch (buffer::error& err) {
9283         ldout(cct, 0) << "ERROR: couldn't decode zone short id attr for object " << s->obj << ", non-critical error, ignoring" << dendl;
9284       }
9285     }
9286   }
9287   if (s->obj_tag.length())
9288     ldout(cct, 20) << "get_obj_state: setting s->obj_tag to " << s->obj_tag.c_str() << dendl;
9289   else
9290     ldout(cct, 20) << "get_obj_state: s->obj_tag was set empty" << dendl;
9291
9292   /* an object might not be olh yet, but could have olh id tag, so we should set it anyway if
9293    * it exist, and not only if is_olh() returns true
9294    */
9295   iter = s->attrset.find(RGW_ATTR_OLH_ID_TAG);
9296   if (iter != s->attrset.end()) {
9297     s->olh_tag = iter->second;
9298   }
9299
9300   if (is_olh(s->attrset)) {
9301     s->is_olh = true;
9302
9303     ldout(cct, 20) << __func__ << ": setting s->olh_tag to " << string(s->olh_tag.c_str(), s->olh_tag.length()) << dendl;
9304
9305     if (need_follow_olh) {
9306       return get_olh_target_state(*rctx, bucket_info, obj, s, state);
9307     }
9308   }
9309
9310   return 0;
9311 }
9312
9313 int RGWRados::get_obj_state(RGWObjectCtx *rctx, const RGWBucketInfo& bucket_info, const rgw_obj& obj, RGWObjState **state,
9314                             bool follow_olh, bool assume_noent)
9315 {
9316   int ret;
9317
9318   do {
9319     ret = get_obj_state_impl(rctx, bucket_info, obj, state, follow_olh, assume_noent);
9320   } while (ret == -EAGAIN);
9321
9322   return ret;
9323 }
9324
9325 int RGWRados::Object::get_manifest(RGWObjManifest **pmanifest)
9326 {
9327   RGWObjState *astate;
9328   int r = get_state(&astate, true);
9329   if (r < 0) {
9330     return r;
9331   }
9332
9333   *pmanifest = &astate->manifest;
9334
9335   return 0;
9336 }
9337
9338 int RGWRados::Object::Read::get_attr(const char *name, bufferlist& dest)
9339 {
9340   RGWObjState *state;
9341   int r = source->get_state(&state, true);
9342   if (r < 0)
9343     return r;
9344   if (!state->exists)
9345     return -ENOENT;
9346   if (!state->get_attr(name, dest))
9347     return -ENODATA;
9348
9349   return 0;
9350 }
9351
9352
9353 int RGWRados::Object::Stat::stat_async()
9354 {
9355   RGWObjectCtx& ctx = source->get_ctx();
9356   rgw_obj& obj = source->get_obj();
9357   RGWRados *store = source->get_store();
9358
9359   RGWObjState *s = ctx.obj.get_state(obj); /* calling this one directly because otherwise a sync request will be sent */
9360   result.obj = obj;
9361   if (s->has_attrs) {
9362     state.ret = 0;
9363     result.size = s->size;
9364     result.mtime = ceph::real_clock::to_timespec(s->mtime);
9365     result.attrs = s->attrset;
9366     result.has_manifest = s->has_manifest;
9367     result.manifest = s->manifest;
9368     return 0;
9369   }
9370
9371   string oid;
9372   string loc;
9373   get_obj_bucket_and_oid_loc(obj, oid, loc);
9374
9375   int r = store->get_obj_head_ioctx(source->get_bucket_info(), obj, &state.io_ctx);
9376   if (r < 0) {
9377     return r;
9378   }
9379
9380   librados::ObjectReadOperation op;
9381   op.stat2(&result.size, &result.mtime, NULL);
9382   op.getxattrs(&result.attrs, NULL);
9383   state.completion = librados::Rados::aio_create_completion(NULL, NULL, NULL);
9384   state.io_ctx.locator_set_key(loc);
9385   r = state.io_ctx.aio_operate(oid, state.completion, &op, NULL);
9386   if (r < 0) {
9387     ldout(store->ctx(), 5) << __func__
9388                                                    << ": ERROR: aio_operate() returned ret=" << r
9389                                                    << dendl;
9390     return r;
9391   }
9392
9393   return 0;
9394 }
9395
9396
9397 int RGWRados::Object::Stat::wait()
9398 {
9399   if (!state.completion) {
9400     return state.ret;
9401   }
9402
9403   state.completion->wait_for_safe();
9404   state.ret = state.completion->get_return_value();
9405   state.completion->release();
9406
9407   if (state.ret != 0) {
9408     return state.ret;
9409   }
9410
9411   return finish();
9412 }
9413
9414 int RGWRados::Object::Stat::finish()
9415 {
9416   map<string, bufferlist>::iterator iter = result.attrs.find(RGW_ATTR_MANIFEST);
9417   if (iter != result.attrs.end()) {
9418     bufferlist& bl = iter->second;
9419     bufferlist::iterator biter = bl.begin();
9420     try {
9421       ::decode(result.manifest, biter);
9422     } catch (buffer::error& err) {
9423       RGWRados *store = source->get_store();
9424       ldout(store->ctx(), 0) << "ERROR: " << __func__ << ": failed to decode manifest"  << dendl;
9425       return -EIO;
9426     }
9427     result.has_manifest = true;
9428   }
9429
9430   return 0;
9431 }
9432
9433 /**
9434  * Get an attribute for a system object.
9435  * obj: the object to get attr
9436  * name: name of the attr to retrieve
9437  * dest: bufferlist to store the result in
9438  * Returns: 0 on success, -ERR# otherwise.
9439  */
9440 int RGWRados::system_obj_get_attr(rgw_raw_obj& obj, const char *name, bufferlist& dest)
9441 {
9442   rgw_rados_ref ref;
9443   int r = get_system_obj_ref(obj, &ref);
9444   if (r < 0) {
9445     return r;
9446   }
9447
9448   ObjectReadOperation op;
9449
9450   int rval;
9451   op.getxattr(name, &dest, &rval);
9452   
9453   r = ref.ioctx.operate(ref.oid, &op, NULL);
9454   if (r < 0)
9455     return r;
9456
9457   return 0;
9458 }
9459
9460 int RGWRados::append_atomic_test(RGWObjectCtx *rctx,
9461                                  const RGWBucketInfo& bucket_info, const rgw_obj& obj,
9462                                  ObjectOperation& op, RGWObjState **pstate)
9463 {
9464   if (!rctx)
9465     return 0;
9466
9467   int r = get_obj_state(rctx, bucket_info, obj, pstate, false);
9468   if (r < 0)
9469     return r;
9470
9471   RGWObjState *state = *pstate;
9472
9473   if (!state->is_atomic) {
9474     ldout(cct, 20) << "state for obj=" << obj << " is not atomic, not appending atomic test" << dendl;
9475     return 0;
9476   }
9477
9478   if (state->obj_tag.length() > 0 && !state->fake_tag) {// check for backward compatibility
9479     op.cmpxattr(RGW_ATTR_ID_TAG, LIBRADOS_CMPXATTR_OP_EQ, state->obj_tag);
9480   } else {
9481     ldout(cct, 20) << "state->obj_tag is empty, not appending atomic test" << dendl;
9482   }
9483   return 0;
9484 }
9485
9486 int RGWRados::Object::get_state(RGWObjState **pstate, bool follow_olh, bool assume_noent)
9487 {
9488   return store->get_obj_state(&ctx, bucket_info, obj, pstate, follow_olh, assume_noent);
9489 }
9490
9491 void RGWRados::Object::invalidate_state()
9492 {
9493   ctx.obj.invalidate(obj);
9494 }
9495
9496 void RGWRados::SystemObject::invalidate_state()
9497 {
9498   ctx.raw.invalidate(obj);
9499 }
9500
9501 int RGWRados::Object::prepare_atomic_modification(ObjectWriteOperation& op, bool reset_obj, const string *ptag,
9502                                                   const char *if_match, const char *if_nomatch, bool removal_op,
9503                                                   bool modify_tail)
9504 {
9505   int r = get_state(&state, false);
9506   if (r < 0)
9507     return r;
9508
9509   bool need_guard = (state->has_manifest || (state->obj_tag.length() != 0) ||
9510                      if_match != NULL || if_nomatch != NULL) &&
9511                      (!state->fake_tag);
9512
9513   if (!state->is_atomic) {
9514     ldout(store->ctx(), 20) << "prepare_atomic_modification: state is not atomic. state=" << (void *)state << dendl;
9515
9516     if (reset_obj) {
9517       op.create(false);
9518       store->remove_rgw_head_obj(op); // we're not dropping reference here, actually removing object
9519     }
9520
9521     return 0;
9522   }
9523
9524   if (need_guard) {
9525     /* first verify that the object wasn't replaced under */
9526     if (if_nomatch == NULL || strcmp(if_nomatch, "*") != 0) {
9527       op.cmpxattr(RGW_ATTR_ID_TAG, LIBRADOS_CMPXATTR_OP_EQ, state->obj_tag); 
9528       // FIXME: need to add FAIL_NOTEXIST_OK for racing deletion
9529     }
9530
9531     if (if_match) {
9532       if (strcmp(if_match, "*") == 0) {
9533         // test the object is existing
9534         if (!state->exists) {
9535           return -ERR_PRECONDITION_FAILED;
9536         }
9537       } else {
9538         bufferlist bl;
9539         if (!state->get_attr(RGW_ATTR_ETAG, bl) ||
9540             strncmp(if_match, bl.c_str(), bl.length()) != 0) {
9541           return -ERR_PRECONDITION_FAILED;
9542         }
9543       }
9544     }
9545
9546     if (if_nomatch) {
9547       if (strcmp(if_nomatch, "*") == 0) {
9548         // test the object is NOT existing
9549         if (state->exists) {
9550           return -ERR_PRECONDITION_FAILED;
9551         }
9552       } else {
9553         bufferlist bl;
9554         if (!state->get_attr(RGW_ATTR_ETAG, bl) ||
9555             strncmp(if_nomatch, bl.c_str(), bl.length()) == 0) {
9556           return -ERR_PRECONDITION_FAILED;
9557         }
9558       }
9559     }
9560   }
9561
9562   if (reset_obj) {
9563     if (state->exists) {
9564       op.create(false);
9565       store->remove_rgw_head_obj(op);
9566     } else {
9567       op.create(true);
9568     }
9569   }
9570
9571   if (removal_op) {
9572     /* the object is being removed, no need to update its tag */
9573     return 0;
9574   }
9575
9576   if (ptag) {
9577     state->write_tag = *ptag;
9578   } else {
9579     append_rand_alpha(store->ctx(), state->write_tag, state->write_tag, 32);
9580   }
9581   bufferlist bl;
9582   bl.append(state->write_tag.c_str(), state->write_tag.size() + 1);
9583
9584   ldout(store->ctx(), 10) << "setting object write_tag=" << state->write_tag << dendl;
9585
9586   op.setxattr(RGW_ATTR_ID_TAG, bl);
9587   if (modify_tail) {
9588     op.setxattr(RGW_ATTR_TAIL_TAG, bl);
9589   }
9590
9591   return 0;
9592 }
9593
9594 int RGWRados::system_obj_set_attr(void *ctx, rgw_raw_obj& obj, const char *name, bufferlist& bl,
9595                                   RGWObjVersionTracker *objv_tracker)
9596 {
9597   map<string, bufferlist> attrs;
9598   attrs[name] = bl;
9599   return system_obj_set_attrs(ctx, obj, attrs, NULL, objv_tracker);
9600 }
9601
9602 int RGWRados::system_obj_set_attrs(void *ctx, rgw_raw_obj& obj,
9603                         map<string, bufferlist>& attrs,
9604                         map<string, bufferlist>* rmattrs,
9605                         RGWObjVersionTracker *objv_tracker)
9606 {
9607   rgw_rados_ref ref;
9608   int r = get_system_obj_ref(obj, &ref);
9609   if (r < 0) {
9610     return r;
9611   }
9612   ObjectWriteOperation op;
9613
9614   if (objv_tracker) {
9615     objv_tracker->prepare_op_for_write(&op);
9616   }
9617
9618   map<string, bufferlist>::iterator iter;
9619   if (rmattrs) {
9620     for (iter = rmattrs->begin(); iter != rmattrs->end(); ++iter) {
9621       const string& name = iter->first;
9622       op.rmxattr(name.c_str());
9623     }
9624   }
9625
9626   for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
9627     const string& name = iter->first;
9628     bufferlist& bl = iter->second;
9629
9630     if (!bl.length())
9631       continue;
9632
9633     op.setxattr(name.c_str(), bl);
9634   }
9635
9636   if (!op.size())
9637     return 0;
9638
9639   bufferlist bl;
9640
9641   r = ref.ioctx.operate(ref.oid, &op);
9642   if (r < 0)
9643     return r;
9644
9645   return 0;
9646 }
9647
9648 /**
9649  * Set an attr on an object.
9650  * bucket: name of the bucket holding the object
9651  * obj: name of the object to set the attr on
9652  * name: the attr to set
9653  * bl: the contents of the attr
9654  * Returns: 0 on success, -ERR# otherwise.
9655  */
9656 int RGWRados::set_attr(void *ctx, const RGWBucketInfo& bucket_info, rgw_obj& obj, const char *name, bufferlist& bl)
9657 {
9658   map<string, bufferlist> attrs;
9659   attrs[name] = bl;
9660   return set_attrs(ctx, bucket_info, obj, attrs, NULL);
9661 }
9662
9663 int RGWRados::set_attrs(void *ctx, const RGWBucketInfo& bucket_info, rgw_obj& obj,
9664                         map<string, bufferlist>& attrs,
9665                         map<string, bufferlist>* rmattrs)
9666 {
9667   rgw_rados_ref ref;
9668   int r = get_obj_head_ref(bucket_info, obj, &ref);
9669   if (r < 0) {
9670     return r;
9671   }
9672   RGWObjectCtx *rctx = static_cast<RGWObjectCtx *>(ctx);
9673
9674   ObjectWriteOperation op;
9675   RGWObjState *state = NULL;
9676
9677   r = append_atomic_test(rctx, bucket_info, obj, op, &state);
9678   if (r < 0)
9679     return r;
9680
9681   map<string, bufferlist>::iterator iter;
9682   if (rmattrs) {
9683     for (iter = rmattrs->begin(); iter != rmattrs->end(); ++iter) {
9684       const string& name = iter->first;
9685       op.rmxattr(name.c_str());
9686     }
9687   }
9688
9689   const rgw_bucket& bucket = obj.bucket;
9690
9691   for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
9692     const string& name = iter->first;
9693     bufferlist& bl = iter->second;
9694
9695     if (!bl.length())
9696       continue;
9697
9698     op.setxattr(name.c_str(), bl);
9699
9700     if (name.compare(RGW_ATTR_DELETE_AT) == 0) {
9701       real_time ts;
9702       try {
9703         ::decode(ts, bl);
9704
9705         rgw_obj_index_key obj_key;
9706         obj.key.get_index_key(&obj_key);
9707
9708         objexp_hint_add(ts, bucket.tenant, bucket.name, bucket.bucket_id, obj_key);
9709       } catch (buffer::error& err) {
9710         ldout(cct, 0) << "ERROR: failed to decode " RGW_ATTR_DELETE_AT << " attr" << dendl;
9711       }
9712     }
9713   }
9714
9715   if (!op.size())
9716     return 0;
9717
9718   RGWObjectCtx obj_ctx(this);
9719
9720   bufferlist bl;
9721   RGWRados::Bucket bop(this, bucket_info);
9722   RGWRados::Bucket::UpdateIndex index_op(&bop, obj);
9723
9724   if (state) {
9725     string tag;
9726     append_rand_alpha(cct, tag, tag, 32);
9727     state->write_tag = tag;
9728     r = index_op.prepare(CLS_RGW_OP_ADD, &state->write_tag);
9729
9730     if (r < 0)
9731       return r;
9732
9733     bl.append(tag.c_str(), tag.size() + 1);
9734     op.setxattr(RGW_ATTR_ID_TAG,  bl);
9735   }
9736
9737
9738   real_time mtime = real_clock::now();
9739   struct timespec mtime_ts = real_clock::to_timespec(mtime);
9740   op.mtime2(&mtime_ts);
9741   r = ref.ioctx.operate(ref.oid, &op);
9742   if (state) {
9743     if (r >= 0) {
9744       bufferlist acl_bl = attrs[RGW_ATTR_ACL];
9745       bufferlist etag_bl = attrs[RGW_ATTR_ETAG];
9746       bufferlist content_type_bl = attrs[RGW_ATTR_CONTENT_TYPE];
9747       string etag(etag_bl.c_str(), etag_bl.length());
9748       string content_type(content_type_bl.c_str(), content_type_bl.length());
9749       uint64_t epoch = ref.ioctx.get_last_version();
9750       int64_t poolid = ref.ioctx.get_id();
9751       r = index_op.complete(poolid, epoch, state->size, state->accounted_size,
9752                             mtime, etag, content_type, &acl_bl,
9753                             RGW_OBJ_CATEGORY_MAIN, NULL);
9754     } else {
9755       int ret = index_op.cancel();
9756       if (ret < 0) {
9757         ldout(cct, 0) << "ERROR: complete_update_index_cancel() returned ret=" << ret << dendl;
9758       }
9759     }
9760   }
9761   if (r < 0)
9762     return r;
9763
9764   if (state) {
9765     state->obj_tag.swap(bl);
9766     if (rmattrs) {
9767       for (iter = rmattrs->begin(); iter != rmattrs->end(); ++iter) {
9768         state->attrset.erase(iter->first);
9769       }
9770     }
9771     for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
9772       state->attrset[iter->first] = iter->second;
9773     }
9774   }
9775
9776   return 0;
9777 }
9778
9779 int RGWRados::Object::Read::prepare()
9780 {
9781   RGWRados *store = source->get_store();
9782   CephContext *cct = store->ctx();
9783
9784   bufferlist etag;
9785
9786   map<string, bufferlist>::iterator iter;
9787
9788   RGWObjState *astate;
9789   int r = source->get_state(&astate, true);
9790   if (r < 0)
9791     return r;
9792
9793   if (!astate->exists) {
9794     return -ENOENT;
9795   }
9796
9797   const RGWBucketInfo& bucket_info = source->get_bucket_info();
9798
9799   state.obj = astate->obj;
9800   store->obj_to_raw(bucket_info.placement_rule, state.obj, &state.head_obj);
9801
9802   r = store->get_obj_head_ioctx(bucket_info, state.obj, &state.io_ctx);
9803   if (r < 0) {
9804     return r;
9805   }
9806   if (params.attrs) {
9807     *params.attrs = astate->attrset;
9808     if (cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
9809       for (iter = params.attrs->begin(); iter != params.attrs->end(); ++iter) {
9810         ldout(cct, 20) << "Read xattr: " << iter->first << dendl;
9811       }
9812     }
9813   }
9814
9815   /* Convert all times go GMT to make them compatible */
9816   if (conds.mod_ptr || conds.unmod_ptr) {
9817     obj_time_weight src_weight;
9818     src_weight.init(astate);
9819     src_weight.high_precision = conds.high_precision_time;
9820
9821     obj_time_weight dest_weight;
9822     dest_weight.high_precision = conds.high_precision_time;
9823
9824     if (conds.mod_ptr) {
9825       dest_weight.init(*conds.mod_ptr, conds.mod_zone_id, conds.mod_pg_ver);
9826       ldout(cct, 10) << "If-Modified-Since: " << dest_weight << " Last-Modified: " << src_weight << dendl;
9827       if (!(dest_weight < src_weight)) {
9828         return -ERR_NOT_MODIFIED;
9829       }
9830     }
9831
9832     if (conds.unmod_ptr) {
9833       dest_weight.init(*conds.unmod_ptr, conds.mod_zone_id, conds.mod_pg_ver);
9834       ldout(cct, 10) << "If-UnModified-Since: " << dest_weight << " Last-Modified: " << src_weight << dendl;
9835       if (dest_weight < src_weight) {
9836         return -ERR_PRECONDITION_FAILED;
9837       }
9838     }
9839   }
9840   if (conds.if_match || conds.if_nomatch) {
9841     r = get_attr(RGW_ATTR_ETAG, etag);
9842     if (r < 0)
9843       return r;
9844
9845     if (conds.if_match) {
9846       string if_match_str = rgw_string_unquote(conds.if_match);
9847       ldout(cct, 10) << "ETag: " << etag.c_str() << " " << " If-Match: " << if_match_str << dendl;
9848       if (if_match_str.compare(etag.c_str()) != 0) {
9849         return -ERR_PRECONDITION_FAILED;
9850       }
9851     }
9852
9853     if (conds.if_nomatch) {
9854       string if_nomatch_str = rgw_string_unquote(conds.if_nomatch);
9855       ldout(cct, 10) << "ETag: " << etag.c_str() << " " << " If-NoMatch: " << if_nomatch_str << dendl;
9856       if (if_nomatch_str.compare(etag.c_str()) == 0) {
9857         return -ERR_NOT_MODIFIED;
9858       }
9859     }
9860   }
9861
9862   if (params.obj_size)
9863     *params.obj_size = astate->size;
9864   if (params.lastmod)
9865     *params.lastmod = astate->mtime;
9866
9867   return 0;
9868 }
9869
9870 int RGWRados::Object::Read::range_to_ofs(uint64_t obj_size, int64_t &ofs, int64_t &end)
9871 {
9872   if (ofs < 0) {
9873     ofs += obj_size;
9874     if (ofs < 0)
9875       ofs = 0;
9876     end = obj_size - 1;
9877   } else if (end < 0) {
9878     end = obj_size - 1;
9879   }
9880
9881   if (obj_size > 0) {
9882     if (ofs >= (off_t)obj_size) {
9883       return -ERANGE;
9884     }
9885     if (end >= (off_t)obj_size) {
9886       end = obj_size - 1;
9887     }
9888   }
9889   return 0;
9890 }
9891
9892 int RGWRados::SystemObject::get_state(RGWRawObjState **pstate, RGWObjVersionTracker *objv_tracker)
9893 {
9894   return store->get_system_obj_state(&ctx, obj, pstate, objv_tracker);
9895 }
9896
9897 int RGWRados::stat_system_obj(RGWObjectCtx& obj_ctx,
9898                               RGWRados::SystemObject::Read::GetObjState& state,
9899                               rgw_raw_obj& obj,
9900                               map<string, bufferlist> *attrs,
9901                               real_time *lastmod,
9902                               uint64_t *obj_size,
9903                               RGWObjVersionTracker *objv_tracker)
9904 {
9905   RGWRawObjState *astate = NULL;
9906
9907   int r = get_system_obj_state(&obj_ctx, obj, &astate, objv_tracker);
9908   if (r < 0)
9909     return r;
9910
9911   if (!astate->exists) {
9912     return -ENOENT;
9913   }
9914
9915   if (attrs) {
9916     *attrs = astate->attrset;
9917     if (cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
9918       map<string, bufferlist>::iterator iter;
9919       for (iter = attrs->begin(); iter != attrs->end(); ++iter) {
9920         ldout(cct, 20) << "Read xattr: " << iter->first << dendl;
9921       }
9922     }
9923   }
9924
9925   if (obj_size)
9926     *obj_size = astate->size;
9927   if (lastmod)
9928     *lastmod = astate->mtime;
9929
9930   return 0;
9931 }
9932
9933
9934 int RGWRados::Bucket::UpdateIndex::guard_reshard(BucketShard **pbs, std::function<int(BucketShard *)> call)
9935 {
9936   RGWRados *store = target->get_store();
9937   BucketShard *bs;
9938   int r;
9939
9940 #define NUM_RESHARD_RETRIES 10
9941   for (int i = 0; i < NUM_RESHARD_RETRIES; ++i) {
9942     int ret = get_bucket_shard(&bs);
9943     if (ret < 0) {
9944       ldout(store->ctx(), 5) << "failed to get BucketShard object: ret=" << ret << dendl;
9945       return ret;
9946     }
9947     r = call(bs);
9948     if (r != -ERR_BUSY_RESHARDING) {
9949       break;
9950     }
9951     ldout(store->ctx(), 0) << "NOTICE: resharding operation on bucket index detected, blocking" << dendl;
9952     string new_bucket_id;
9953     r = store->block_while_resharding(bs, &new_bucket_id);
9954     if (r == -ERR_BUSY_RESHARDING) {
9955       continue;
9956     }
9957     if (r < 0) {
9958       return r;
9959     }
9960     ldout(store->ctx(), 20) << "reshard completion identified, new_bucket_id=" << new_bucket_id << dendl;
9961     i = 0; /* resharding is finished, make sure we can retry */
9962     r = target->update_bucket_id(new_bucket_id);
9963     if (r < 0) {
9964       ldout(store->ctx(), 0) << "ERROR: update_bucket_id() new_bucket_id=" << new_bucket_id << " returned r=" << r << dendl;
9965       return r;
9966     }
9967     invalidate_bs();
9968   }
9969
9970   if (r < 0) {
9971     return r;
9972   }
9973
9974   if (pbs) {
9975     *pbs = bs;
9976   }
9977
9978   return 0;
9979 }
9980
9981 int RGWRados::SystemObject::Read::stat(RGWObjVersionTracker *objv_tracker)
9982 {
9983   RGWRados *store = source->get_store();
9984   rgw_raw_obj& obj = source->get_obj();
9985
9986   return store->stat_system_obj(source->get_ctx(), state, obj, stat_params.attrs,
9987                                 stat_params.lastmod, stat_params.obj_size, objv_tracker);
9988 }
9989
9990 int RGWRados::Bucket::UpdateIndex::prepare(RGWModifyOp op, const string *write_tag)
9991 {
9992   if (blind) {
9993     return 0;
9994   }
9995   RGWRados *store = target->get_store();
9996
9997   if (write_tag && write_tag->length()) {
9998     optag = string(write_tag->c_str(), write_tag->length());
9999   } else {
10000     if (optag.empty()) {
10001       append_rand_alpha(store->ctx(), optag, optag, 32);
10002     }
10003   }
10004
10005   int r = guard_reshard(nullptr, [&](BucketShard *bs) -> int { 
10006     return store->cls_obj_prepare_op(*bs, op, optag, obj, bilog_flags, zones_trace);
10007   });
10008
10009   if (r < 0) {
10010     return r;
10011   }
10012   prepared = true;
10013
10014   return 0;
10015 }
10016
10017 int RGWRados::Bucket::UpdateIndex::complete(int64_t poolid, uint64_t epoch,
10018                                             uint64_t size, uint64_t accounted_size,
10019                                             ceph::real_time& ut, const string& etag,
10020                                             const string& content_type,
10021                                             bufferlist *acl_bl,
10022                                             RGWObjCategory category,
10023                                             list<rgw_obj_index_key> *remove_objs, const string *user_data)
10024 {
10025   if (blind) {
10026     return 0;
10027   }
10028   RGWRados *store = target->get_store();
10029   BucketShard *bs;
10030
10031   int ret = get_bucket_shard(&bs);
10032   if (ret < 0) {
10033     ldout(store->ctx(), 5) << "failed to get BucketShard object: ret=" << ret << dendl;
10034     return ret;
10035   }
10036
10037   rgw_bucket_dir_entry ent;
10038   obj.key.get_index_key(&ent.key);
10039   ent.meta.size = size;
10040   ent.meta.accounted_size = accounted_size;
10041   ent.meta.mtime = ut;
10042   ent.meta.etag = etag;
10043   if (user_data)
10044     ent.meta.user_data = *user_data;
10045
10046   ACLOwner owner;
10047   if (acl_bl && acl_bl->length()) {
10048     int ret = store->decode_policy(*acl_bl, &owner);
10049     if (ret < 0) {
10050       ldout(store->ctx(), 0) << "WARNING: could not decode policy ret=" << ret << dendl;
10051     }
10052   }
10053   ent.meta.owner = owner.get_id().to_str();
10054   ent.meta.owner_display_name = owner.get_display_name();
10055   ent.meta.content_type = content_type;
10056
10057   ret = store->cls_obj_complete_add(*bs, obj, optag, poolid, epoch, ent, category, remove_objs, bilog_flags, zones_trace);
10058
10059   if (target->bucket_info.datasync_flag_enabled()) {
10060     int r = store->data_log->add_entry(bs->bucket, bs->shard_id);
10061     if (r < 0) {
10062       lderr(store->ctx()) << "ERROR: failed writing data log" << dendl;
10063     }
10064   }
10065
10066   return ret;
10067 }
10068
10069 int RGWRados::Bucket::UpdateIndex::complete_del(int64_t poolid, uint64_t epoch,
10070                                                 real_time& removed_mtime,
10071                                                 list<rgw_obj_index_key> *remove_objs)
10072 {
10073   if (blind) {
10074     return 0;
10075   }
10076   RGWRados *store = target->get_store();
10077   BucketShard *bs;
10078
10079   int ret = get_bucket_shard(&bs);
10080   if (ret < 0) {
10081     ldout(store->ctx(), 5) << "failed to get BucketShard object: ret=" << ret << dendl;
10082     return ret;
10083   }
10084
10085   ret = store->cls_obj_complete_del(*bs, optag, poolid, epoch, obj, removed_mtime, remove_objs, bilog_flags, zones_trace);
10086
10087   if (target->bucket_info.datasync_flag_enabled()) {
10088     int r = store->data_log->add_entry(bs->bucket, bs->shard_id);
10089     if (r < 0) {
10090       lderr(store->ctx()) << "ERROR: failed writing data log" << dendl;
10091     }
10092   }
10093
10094   return ret;
10095 }
10096
10097
10098 int RGWRados::Bucket::UpdateIndex::cancel()
10099 {
10100   if (blind) {
10101     return 0;
10102   }
10103   RGWRados *store = target->get_store();
10104   BucketShard *bs;
10105
10106   int ret = guard_reshard(&bs, [&](BucketShard *bs) -> int { 
10107     return store->cls_obj_complete_cancel(*bs, optag, obj, bilog_flags, zones_trace);
10108   });
10109
10110   /*
10111    * need to update data log anyhow, so that whoever follows needs to update its internal markers
10112    * for following the specific bucket shard log. Otherwise they end up staying behind, and users
10113    * have no way to tell that they're all caught up
10114    */
10115   if (target->bucket_info.datasync_flag_enabled()) {
10116     int r = store->data_log->add_entry(bs->bucket, bs->shard_id);
10117     if (r < 0) {
10118       lderr(store->ctx()) << "ERROR: failed writing data log" << dendl;
10119     }
10120   }
10121
10122   return ret;
10123 }
10124
10125 int RGWRados::Object::Read::read(int64_t ofs, int64_t end, bufferlist& bl)
10126 {
10127   RGWRados *store = source->get_store();
10128   CephContext *cct = store->ctx();
10129
10130   rgw_raw_obj read_obj;
10131   uint64_t read_ofs = ofs;
10132   uint64_t len, read_len;
10133   bool reading_from_head = true;
10134   ObjectReadOperation op;
10135
10136   bool merge_bl = false;
10137   bufferlist *pbl = &bl;
10138   bufferlist read_bl;
10139   uint64_t max_chunk_size;
10140
10141   RGWObjState *astate;
10142   int r = source->get_state(&astate, true);
10143   if (r < 0)
10144     return r;
10145
10146   if (end < 0)
10147     len = 0;
10148   else
10149     len = end - ofs + 1;
10150
10151   if (astate->has_manifest && astate->manifest.has_tail()) {
10152     /* now get the relevant object part */
10153     RGWObjManifest::obj_iterator iter = astate->manifest.obj_find(ofs);
10154
10155     uint64_t stripe_ofs = iter.get_stripe_ofs();
10156     read_obj = iter.get_location().get_raw_obj(store);
10157     len = min(len, iter.get_stripe_size() - (ofs - stripe_ofs));
10158     read_ofs = iter.location_ofs() + (ofs - stripe_ofs);
10159     reading_from_head = (read_obj == state.head_obj);
10160   } else {
10161     read_obj = state.head_obj;
10162   }
10163
10164   r = store->get_max_chunk_size(read_obj.pool, &max_chunk_size);
10165   if (r < 0) {
10166     ldout(cct, 0) << "ERROR: failed to get max_chunk_size() for pool " << read_obj.pool << dendl;
10167     return r;
10168   }
10169
10170   if (len > max_chunk_size)
10171     len = max_chunk_size;
10172
10173
10174   state.io_ctx.locator_set_key(read_obj.loc);
10175
10176   read_len = len;
10177
10178   if (reading_from_head) {
10179     /* only when reading from the head object do we need to do the atomic test */
10180     r = store->append_atomic_test(&source->get_ctx(), source->get_bucket_info(), state.obj, op, &astate);
10181     if (r < 0)
10182       return r;
10183
10184     if (astate && astate->prefetch_data) {
10185       if (!ofs && astate->data.length() >= len) {
10186         bl = astate->data;
10187         return bl.length();
10188       }
10189
10190       if (ofs < astate->data.length()) {
10191         unsigned copy_len = min((uint64_t)astate->data.length() - ofs, len);
10192         astate->data.copy(ofs, copy_len, bl);
10193         read_len -= copy_len;
10194         read_ofs += copy_len;
10195         if (!read_len)
10196           return bl.length();
10197
10198         merge_bl = true;
10199         pbl = &read_bl;
10200       }
10201     }
10202   }
10203
10204   ldout(cct, 20) << "rados->read obj-ofs=" << ofs << " read_ofs=" << read_ofs << " read_len=" << read_len << dendl;
10205   op.read(read_ofs, read_len, pbl, NULL);
10206
10207   r = state.io_ctx.operate(read_obj.oid, &op, NULL);
10208   ldout(cct, 20) << "rados->read r=" << r << " bl.length=" << bl.length() << dendl;
10209
10210   if (r < 0) {
10211     return r;
10212   }
10213
10214   if (merge_bl) {
10215     bl.append(read_bl);
10216   }
10217
10218   return bl.length();
10219 }
10220
10221 int RGWRados::SystemObject::Read::GetObjState::get_ref(RGWRados *store, rgw_raw_obj& obj, rgw_rados_ref **pref)
10222 {
10223   if (!has_ref) {
10224     int r = store->get_raw_obj_ref(obj, &ref);
10225     if (r < 0) {
10226       return r;
10227     }
10228     has_ref = true;
10229   }
10230   *pref = &ref;
10231   return 0;
10232
10233 }
10234
10235 int RGWRados::get_system_obj(RGWObjectCtx& obj_ctx, RGWRados::SystemObject::Read::GetObjState& read_state,
10236                              RGWObjVersionTracker *objv_tracker, rgw_raw_obj& obj,
10237                              bufferlist& bl, off_t ofs, off_t end,
10238                              map<string, bufferlist> *attrs,
10239                              rgw_cache_entry_info *cache_info)
10240 {
10241   uint64_t len;
10242   ObjectReadOperation op;
10243
10244   if (end < 0)
10245     len = 0;
10246   else
10247     len = end - ofs + 1;
10248
10249   if (objv_tracker) {
10250     objv_tracker->prepare_op_for_read(&op);
10251   }
10252
10253   ldout(cct, 20) << "rados->read ofs=" << ofs << " len=" << len << dendl;
10254   op.read(ofs, len, &bl, NULL);
10255
10256   if (attrs) {
10257     op.getxattrs(attrs, NULL);
10258   }
10259
10260   rgw_rados_ref *ref;
10261   int r = read_state.get_ref(this, obj, &ref);
10262   if (r < 0) {
10263     ldout(cct, 20) << "read_state.get_ref() on obj=" << obj << " returned " << r << dendl;
10264     return r;
10265   }
10266   r = ref->ioctx.operate(ref->oid, &op, NULL);
10267   if (r < 0) {
10268     ldout(cct, 20) << "rados->read r=" << r << " bl.length=" << bl.length() << dendl;
10269     return r;
10270   }
10271   ldout(cct, 20) << "rados->read r=" << r << " bl.length=" << bl.length() << dendl;
10272
10273   uint64_t op_ver = ref->ioctx.get_last_version();
10274
10275   if (read_state.last_ver > 0 &&
10276       read_state.last_ver != op_ver) {
10277     ldout(cct, 5) << "raced with an object write, abort" << dendl;
10278     return -ECANCELED;
10279   }
10280
10281   read_state.last_ver = op_ver;
10282
10283   return bl.length();
10284 }
10285
10286 int RGWRados::SystemObject::Read::read(int64_t ofs, int64_t end, bufferlist& bl, RGWObjVersionTracker *objv_tracker)
10287 {
10288   RGWRados *store = source->get_store();
10289   rgw_raw_obj& obj = source->get_obj();
10290
10291   return store->get_system_obj(source->get_ctx(), state, objv_tracker, obj, bl, ofs, end, read_params.attrs, read_params.cache_info);
10292 }
10293
10294 int RGWRados::SystemObject::Read::get_attr(const char *name, bufferlist& dest)
10295 {
10296   RGWRados *store = source->get_store();
10297   rgw_raw_obj& obj = source->get_obj();
10298
10299   return store->system_obj_get_attr(obj, name, dest);
10300 }
10301
10302 struct get_obj_data;
10303
10304 struct get_obj_aio_data {
10305   struct get_obj_data *op_data;
10306   off_t ofs;
10307   off_t len;
10308 };
10309
10310 struct get_obj_io {
10311   off_t len;
10312   bufferlist bl;
10313 };
10314
10315 static void _get_obj_aio_completion_cb(completion_t cb, void *arg);
10316
10317 struct get_obj_data : public RefCountedObject {
10318   CephContext *cct;
10319   RGWRados *rados;
10320   RGWObjectCtx *ctx;
10321   IoCtx io_ctx;
10322   map<off_t, get_obj_io> io_map;
10323   map<off_t, librados::AioCompletion *> completion_map;
10324   uint64_t total_read;
10325   Mutex lock;
10326   Mutex data_lock;
10327   list<get_obj_aio_data> aio_data;
10328   RGWGetDataCB *client_cb;
10329   std::atomic<bool> cancelled = { false };
10330   std::atomic<int64_t> err_code = { 0 };
10331   Throttle throttle;
10332   list<bufferlist> read_list;
10333
10334   explicit get_obj_data(CephContext *_cct)
10335     : cct(_cct),
10336       rados(NULL), ctx(NULL),
10337       total_read(0), lock("get_obj_data"), data_lock("get_obj_data::data_lock"),
10338       client_cb(NULL),
10339       throttle(cct, "get_obj_data", cct->_conf->rgw_get_obj_window_size, false) {}
10340   ~get_obj_data() override { } 
10341   void set_cancelled(int r) {
10342     cancelled = true;
10343     err_code = r;
10344   }
10345
10346   bool is_cancelled() {
10347     return cancelled;
10348   }
10349
10350   int get_err_code() {
10351     return err_code;
10352   }
10353
10354   int wait_next_io(bool *done) {
10355     lock.Lock();
10356     map<off_t, librados::AioCompletion *>::iterator iter = completion_map.begin();
10357     if (iter == completion_map.end()) {
10358       *done = true;
10359       lock.Unlock();
10360       return 0;
10361     }
10362     off_t cur_ofs = iter->first;
10363     librados::AioCompletion *c = iter->second;
10364     lock.Unlock();
10365
10366     c->wait_for_safe_and_cb();
10367     int r = c->get_return_value();
10368
10369     lock.Lock();
10370     completion_map.erase(cur_ofs);
10371
10372     if (completion_map.empty()) {
10373       *done = true;
10374     }
10375     lock.Unlock();
10376
10377     c->release();
10378     
10379     return r;
10380   }
10381
10382   void add_io(off_t ofs, off_t len, bufferlist **pbl, AioCompletion **pc) {
10383     Mutex::Locker l(lock);
10384
10385     const auto& io_iter = io_map.insert(
10386       map<off_t, get_obj_io>::value_type(ofs, get_obj_io()));
10387
10388     assert(io_iter.second); // assert new insertion
10389
10390     get_obj_io& io = (io_iter.first)->second;
10391     *pbl = &io.bl;
10392
10393     struct get_obj_aio_data aio;
10394     aio.ofs = ofs;
10395     aio.len = len;
10396     aio.op_data = this;
10397
10398     aio_data.push_back(aio);
10399
10400     struct get_obj_aio_data *paio_data =  &aio_data.back(); /* last element */
10401
10402     librados::AioCompletion *c = librados::Rados::aio_create_completion((void *)paio_data, NULL, _get_obj_aio_completion_cb);
10403     completion_map[ofs] = c;
10404
10405     *pc = c;
10406
10407     /* we have a reference per IO, plus one reference for the calling function.
10408      * reference is dropped for each callback, plus when we're done iterating
10409      * over the parts */
10410     get();
10411   }
10412
10413   void cancel_io(off_t ofs) {
10414     ldout(cct, 20) << "get_obj_data::cancel_io() ofs=" << ofs << dendl;
10415     lock.Lock();
10416     map<off_t, AioCompletion *>::iterator iter = completion_map.find(ofs);
10417     if (iter != completion_map.end()) {
10418       AioCompletion *c = iter->second;
10419       c->release();
10420       completion_map.erase(ofs);
10421       io_map.erase(ofs);
10422     }
10423     lock.Unlock();
10424
10425     /* we don't drop a reference here -- e.g., not calling d->put(), because we still
10426      * need IoCtx to live, as io callback may still be called
10427      */
10428   }
10429
10430   void cancel_all_io() {
10431     ldout(cct, 20) << "get_obj_data::cancel_all_io()" << dendl;
10432     Mutex::Locker l(lock);
10433     for (map<off_t, librados::AioCompletion *>::iterator iter = completion_map.begin();
10434          iter != completion_map.end(); ++iter) {
10435       librados::AioCompletion  *c = iter->second;
10436       c->release();
10437     }
10438   }
10439
10440   int get_complete_ios(off_t ofs, list<bufferlist>& bl_list) {
10441     Mutex::Locker l(lock);
10442
10443     map<off_t, get_obj_io>::iterator liter = io_map.begin();
10444
10445     if (liter == io_map.end() ||
10446         liter->first != ofs) {
10447       return 0;
10448     }
10449
10450     map<off_t, librados::AioCompletion *>::iterator aiter;
10451     aiter = completion_map.find(ofs);
10452     if (aiter == completion_map.end()) {
10453     /* completion map does not hold this io, it was cancelled */
10454       return 0;
10455     }
10456
10457     AioCompletion *completion = aiter->second;
10458     int r = completion->get_return_value();
10459     if (r < 0)
10460       return r;
10461
10462     for (; aiter != completion_map.end(); ++aiter) {
10463       completion = aiter->second;
10464       if (!completion->is_safe()) {
10465         /* reached a request that is not yet complete, stop */
10466         break;
10467       }
10468
10469       r = completion->get_return_value();
10470       if (r < 0) {
10471         set_cancelled(r); /* mark it as cancelled, so that we don't continue processing next operations */
10472         return r;
10473       }
10474
10475       total_read += r;
10476
10477       map<off_t, get_obj_io>::iterator old_liter = liter++;
10478       bl_list.push_back(old_liter->second.bl);
10479       io_map.erase(old_liter);
10480     }
10481
10482     return 0;
10483   }
10484 };
10485
10486 static int _get_obj_iterate_cb(const RGWBucketInfo& bucket_info, const rgw_obj& obj, const rgw_raw_obj& read_obj, off_t obj_ofs, off_t read_ofs, off_t len, bool is_head_obj, RGWObjState *astate, void *arg)
10487 {
10488   struct get_obj_data *d = (struct get_obj_data *)arg;
10489
10490   return d->rados->get_obj_iterate_cb(d->ctx, astate, bucket_info, obj, read_obj, obj_ofs, read_ofs, len, is_head_obj, arg);
10491 }
10492
10493 static void _get_obj_aio_completion_cb(completion_t cb, void *arg)
10494 {
10495   struct get_obj_aio_data *aio_data = (struct get_obj_aio_data *)arg;
10496   struct get_obj_data *d = aio_data->op_data;
10497
10498   d->rados->get_obj_aio_completion_cb(cb, arg);
10499 }
10500
10501
10502 void RGWRados::get_obj_aio_completion_cb(completion_t c, void *arg)
10503 {
10504   struct get_obj_aio_data *aio_data = (struct get_obj_aio_data *)arg;
10505   struct get_obj_data *d = aio_data->op_data;
10506   off_t ofs = aio_data->ofs;
10507   off_t len = aio_data->len;
10508
10509   list<bufferlist> bl_list;
10510   list<bufferlist>::iterator iter;
10511   int r;
10512
10513   ldout(cct, 20) << "get_obj_aio_completion_cb: io completion ofs=" << ofs << " len=" << len << dendl;
10514   d->throttle.put(len);
10515
10516   r = rados_aio_get_return_value(c);
10517   if (r < 0) {
10518     ldout(cct, 0) << "ERROR: got unexpected error when trying to read object: " << r << dendl;
10519     d->set_cancelled(r);
10520     goto done;
10521   }
10522
10523   if (d->is_cancelled()) {
10524     goto done;
10525   }
10526
10527   d->data_lock.Lock();
10528
10529   r = d->get_complete_ios(ofs, bl_list);
10530   if (r < 0) {
10531     goto done_unlock;
10532   }
10533
10534   d->read_list.splice(d->read_list.end(), bl_list);
10535
10536 done_unlock:
10537   d->data_lock.Unlock();
10538 done:
10539   d->put();
10540   return;
10541 }
10542
10543 int RGWRados::flush_read_list(struct get_obj_data *d)
10544 {
10545   d->data_lock.Lock();
10546   list<bufferlist> l;
10547   l.swap(d->read_list);
10548   d->get();
10549   d->read_list.clear();
10550
10551   d->data_lock.Unlock();
10552
10553   int r = 0;
10554
10555   list<bufferlist>::iterator iter;
10556   for (iter = l.begin(); iter != l.end(); ++iter) {
10557     bufferlist& bl = *iter;
10558     r = d->client_cb->handle_data(bl, 0, bl.length());
10559     if (r < 0) {
10560       dout(0) << "ERROR: flush_read_list(): d->client_cb->handle_data() returned " << r << dendl;
10561       break;
10562     }
10563   }
10564
10565   d->data_lock.Lock();
10566   d->put();
10567   if (r < 0) {
10568     d->set_cancelled(r);
10569   }
10570   d->data_lock.Unlock();
10571   return r;
10572 }
10573
10574 int RGWRados::get_obj_iterate_cb(RGWObjectCtx *ctx, RGWObjState *astate,
10575                          const RGWBucketInfo& bucket_info,
10576                          const rgw_obj& obj,
10577                          const rgw_raw_obj& read_obj,
10578                          off_t obj_ofs,
10579                          off_t read_ofs, off_t len,
10580                          bool is_head_obj, void *arg)
10581 {
10582   RGWObjectCtx *rctx = static_cast<RGWObjectCtx *>(ctx);
10583   ObjectReadOperation op;
10584   struct get_obj_data *d = (struct get_obj_data *)arg;
10585   string oid, key;
10586   bufferlist *pbl;
10587   AioCompletion *c;
10588
10589   int r;
10590
10591   if (is_head_obj) {
10592     /* only when reading from the head object do we need to do the atomic test */
10593     r = append_atomic_test(rctx, bucket_info, obj, op, &astate);
10594     if (r < 0)
10595       return r;
10596
10597     if (astate &&
10598         obj_ofs < astate->data.length()) {
10599       unsigned chunk_len = min((uint64_t)astate->data.length() - obj_ofs, (uint64_t)len);
10600
10601       d->data_lock.Lock();
10602       r = d->client_cb->handle_data(astate->data, obj_ofs, chunk_len);
10603       d->data_lock.Unlock();
10604       if (r < 0)
10605         return r;
10606
10607       d->lock.Lock();
10608       d->total_read += chunk_len;
10609       d->lock.Unlock();
10610         
10611       len -= chunk_len;
10612       read_ofs += chunk_len;
10613       obj_ofs += chunk_len;
10614       if (!len)
10615           return 0;
10616     }
10617   }
10618
10619   d->throttle.get(len);
10620   if (d->is_cancelled()) {
10621     return d->get_err_code();
10622   }
10623
10624   /* add io after we check that we're not cancelled, otherwise we're going to have trouble
10625    * cleaning up
10626    */
10627   d->add_io(obj_ofs, len, &pbl, &c);
10628
10629   ldout(cct, 20) << "rados->get_obj_iterate_cb oid=" << read_obj.oid << " obj-ofs=" << obj_ofs << " read_ofs=" << read_ofs << " len=" << len << dendl;
10630   op.read(read_ofs, len, pbl, NULL);
10631
10632   librados::IoCtx io_ctx(d->io_ctx);
10633   io_ctx.locator_set_key(read_obj.loc);
10634
10635   r = io_ctx.aio_operate(read_obj.oid, c, &op, NULL);
10636   if (r < 0) {
10637     ldout(cct, 0) << "rados->aio_operate r=" << r << dendl;
10638     goto done_err;
10639   }
10640
10641   // Flush data to client if there is any
10642   r = flush_read_list(d);
10643   if (r < 0)
10644     return r;
10645
10646   return 0;
10647
10648 done_err:
10649   ldout(cct, 20) << "cancelling io r=" << r << " obj_ofs=" << obj_ofs << dendl;
10650   d->set_cancelled(r);
10651   d->cancel_io(obj_ofs);
10652
10653   return r;
10654 }
10655
10656 int RGWRados::Object::Read::iterate(int64_t ofs, int64_t end, RGWGetDataCB *cb)
10657 {
10658   RGWRados *store = source->get_store();
10659   CephContext *cct = store->ctx();
10660
10661   struct get_obj_data *data = new get_obj_data(cct);
10662   bool done = false;
10663
10664   RGWObjectCtx& obj_ctx = source->get_ctx();
10665
10666   data->rados = store;
10667   data->io_ctx.dup(state.io_ctx);
10668   data->client_cb = cb;
10669
10670   int r = store->iterate_obj(obj_ctx, source->get_bucket_info(), state.obj, ofs, end, cct->_conf->rgw_get_obj_max_req_size, _get_obj_iterate_cb, (void *)data);
10671   if (r < 0) {
10672     data->cancel_all_io();
10673     goto done;
10674   }
10675
10676   while (!done) {
10677     r = data->wait_next_io(&done);
10678     if (r < 0) {
10679       dout(10) << "get_obj_iterate() r=" << r << ", canceling all io" << dendl;
10680       data->cancel_all_io();
10681       break;
10682     }
10683     r = store->flush_read_list(data);
10684     if (r < 0) {
10685       dout(10) << "get_obj_iterate() r=" << r << ", canceling all io" << dendl;
10686       data->cancel_all_io();
10687       break;
10688     }
10689   }
10690
10691 done:
10692   data->put();
10693   return r;
10694 }
10695
10696 int RGWRados::iterate_obj(RGWObjectCtx& obj_ctx,
10697                           const RGWBucketInfo& bucket_info, const rgw_obj& obj,
10698                           off_t ofs, off_t end,
10699                           uint64_t max_chunk_size,
10700                           int (*iterate_obj_cb)(const RGWBucketInfo&, const rgw_obj& obj,
10701                                                 const rgw_raw_obj&, off_t, off_t, off_t, bool,
10702                                                 RGWObjState *, void *),
10703                           void *arg)
10704 {
10705   rgw_raw_obj head_obj;
10706   rgw_raw_obj read_obj;
10707   uint64_t read_ofs = ofs;
10708   uint64_t len;
10709   bool reading_from_head = true;
10710   RGWObjState *astate = NULL;
10711
10712   obj_to_raw(bucket_info.placement_rule, obj, &head_obj);
10713
10714   int r = get_obj_state(&obj_ctx, bucket_info, obj, &astate, false);
10715   if (r < 0) {
10716     return r;
10717   }
10718
10719   if (end < 0)
10720     len = 0;
10721   else
10722     len = end - ofs + 1;
10723
10724   if (astate->has_manifest) {
10725     /* now get the relevant object stripe */
10726     RGWObjManifest::obj_iterator iter = astate->manifest.obj_find(ofs);
10727
10728     RGWObjManifest::obj_iterator obj_end = astate->manifest.obj_end();
10729
10730     for (; iter != obj_end && ofs <= end; ++iter) {
10731       off_t stripe_ofs = iter.get_stripe_ofs();
10732       off_t next_stripe_ofs = stripe_ofs + iter.get_stripe_size();
10733
10734       while (ofs < next_stripe_ofs && ofs <= end) {
10735         read_obj = iter.get_location().get_raw_obj(this);
10736         uint64_t read_len = min(len, iter.get_stripe_size() - (ofs - stripe_ofs));
10737         read_ofs = iter.location_ofs() + (ofs - stripe_ofs);
10738
10739         if (read_len > max_chunk_size) {
10740           read_len = max_chunk_size;
10741         }
10742
10743         reading_from_head = (read_obj == head_obj);
10744         r = iterate_obj_cb(bucket_info, obj, read_obj, ofs, read_ofs, read_len, reading_from_head, astate, arg);
10745         if (r < 0) {
10746           return r;
10747         }
10748
10749         len -= read_len;
10750         ofs += read_len;
10751       }
10752     }
10753   } else {
10754     while (ofs <= end) {
10755       read_obj = head_obj;
10756       uint64_t read_len = min(len, max_chunk_size);
10757
10758       r = iterate_obj_cb(bucket_info, obj, read_obj, ofs, ofs, read_len, reading_from_head, astate, arg);
10759       if (r < 0) {
10760         return r;
10761       }
10762
10763       len -= read_len;
10764       ofs += read_len;
10765     }
10766   }
10767
10768   return 0;
10769 }
10770
10771 int RGWRados::obj_operate(const RGWBucketInfo& bucket_info, const rgw_obj& obj, ObjectWriteOperation *op)
10772 {
10773   rgw_rados_ref ref;
10774   int r = get_obj_head_ref(bucket_info, obj, &ref);
10775   if (r < 0) {
10776     return r;
10777   }
10778
10779   return ref.ioctx.operate(ref.oid, op);
10780 }
10781
10782 int RGWRados::obj_operate(const RGWBucketInfo& bucket_info, const rgw_obj& obj, ObjectReadOperation *op)
10783 {
10784   rgw_rados_ref ref;
10785   int r = get_obj_head_ref(bucket_info, obj, &ref);
10786   if (r < 0) {
10787     return r;
10788   }
10789
10790   bufferlist outbl;
10791
10792   return ref.ioctx.operate(ref.oid, op, &outbl);
10793 }
10794
10795 int RGWRados::olh_init_modification_impl(const RGWBucketInfo& bucket_info, RGWObjState& state, const rgw_obj& olh_obj, string *op_tag)
10796 {
10797   ObjectWriteOperation op;
10798
10799   assert(olh_obj.key.instance.empty());
10800
10801   bool has_tag = (state.exists && has_olh_tag(state.attrset));
10802
10803   if (!state.exists) {
10804     op.create(true);
10805   } else {
10806     op.assert_exists();
10807   }
10808
10809   /*
10810    * 3 possible cases: olh object doesn't exist, it exists as an olh, it exists as a regular object.
10811    * If it exists as a regular object we'll need to transform it into an olh. We'll do it in two
10812    * steps, first change its tag and set the olh pending attrs. Once write is done we'll need to
10813    * truncate it, remove extra attrs, and send it to the garbage collection. The bucket index olh
10814    * log will reflect that.
10815    *
10816    * Need to generate separate olh and obj tags, as olh can be colocated with object data. obj_tag
10817    * is used for object data instance, olh_tag for olh instance.
10818    */
10819   if (has_tag) {
10820     /* guard against racing writes */
10821     bucket_index_guard_olh_op(state, op);
10822   }
10823
10824   if (!has_tag) {
10825     /* obj tag */
10826     string obj_tag;
10827     int ret = gen_rand_alphanumeric_lower(cct, &obj_tag, 32);
10828     if (ret < 0) {
10829       ldout(cct, 0) << "ERROR: gen_rand_alphanumeric_lower() returned ret=" << ret << dendl;
10830       return ret;
10831     }
10832     bufferlist bl;
10833     bl.append(obj_tag.c_str(), obj_tag.size());
10834     op.setxattr(RGW_ATTR_ID_TAG, bl);
10835
10836     state.attrset[RGW_ATTR_ID_TAG] = bl;
10837     state.obj_tag = bl;
10838
10839     /* olh tag */
10840     string olh_tag;
10841     ret = gen_rand_alphanumeric_lower(cct, &olh_tag, 32);
10842     if (ret < 0) {
10843       ldout(cct, 0) << "ERROR: gen_rand_alphanumeric_lower() returned ret=" << ret << dendl;
10844       return ret;
10845     }
10846     bufferlist olh_bl;
10847     olh_bl.append(olh_tag.c_str(), olh_tag.size());
10848     op.setxattr(RGW_ATTR_OLH_ID_TAG, olh_bl);
10849
10850     state.attrset[RGW_ATTR_OLH_ID_TAG] = olh_bl;
10851     state.olh_tag = olh_bl;
10852     state.is_olh = true;
10853
10854     bufferlist verbl;
10855     op.setxattr(RGW_ATTR_OLH_VER, verbl);
10856   }
10857
10858   bufferlist bl;
10859   RGWOLHPendingInfo pending_info;
10860   pending_info.time = real_clock::now();
10861   ::encode(pending_info, bl);
10862
10863 #define OLH_PENDING_TAG_LEN 32
10864   /* tag will start with current time epoch, this so that entries are sorted by time */
10865   char buf[32];
10866   utime_t ut(pending_info.time);
10867   snprintf(buf, sizeof(buf), "%016llx", (unsigned long long)ut.sec());
10868   *op_tag = buf;
10869
10870   string s;
10871   int ret = gen_rand_alphanumeric_lower(cct, &s, OLH_PENDING_TAG_LEN - op_tag->size());
10872   if (ret < 0) {
10873     ldout(cct, 0) << "ERROR: gen_rand_alphanumeric_lower() returned ret=" << ret << dendl;
10874     return ret;
10875   }
10876   op_tag->append(s);
10877
10878   string attr_name = RGW_ATTR_OLH_PENDING_PREFIX;
10879   attr_name.append(*op_tag);
10880
10881   op.setxattr(attr_name.c_str(), bl);
10882
10883   ret = obj_operate(bucket_info, olh_obj, &op);
10884   if (ret < 0) {
10885     return ret;
10886   }
10887
10888   state.exists = true;
10889   state.attrset[attr_name] = bl;
10890
10891   return 0;
10892 }
10893
10894 int RGWRados::olh_init_modification(const RGWBucketInfo& bucket_info, RGWObjState& state, const rgw_obj& obj, string *op_tag)
10895 {
10896   int ret;
10897
10898   ret = olh_init_modification_impl(bucket_info, state, obj, op_tag);
10899   if (ret == -EEXIST) {
10900     ret = -ECANCELED;
10901   }
10902
10903   return ret;
10904 }
10905
10906 int RGWRados::guard_reshard(BucketShard *bs, const rgw_obj& obj_instance, std::function<int(BucketShard *)> call)
10907 {
10908   rgw_obj obj;
10909   const rgw_obj *pobj = &obj_instance;
10910   int r;
10911
10912   for (int i = 0; i < NUM_RESHARD_RETRIES; ++i) {
10913     r = bs->init(pobj->bucket, *pobj);
10914     if (r < 0) {
10915       ldout(cct, 5) << "bs.init() returned ret=" << r << dendl;
10916       return r;
10917     }
10918     r = call(bs);
10919     if (r != -ERR_BUSY_RESHARDING) {
10920       break;
10921     }
10922     ldout(cct, 0) << "NOTICE: resharding operation on bucket index detected, blocking" << dendl;
10923     string new_bucket_id;
10924     r = block_while_resharding(bs, &new_bucket_id);
10925     if (r == -ERR_BUSY_RESHARDING) {
10926       continue;
10927     }
10928     if (r < 0) {
10929       return r;
10930     }
10931     ldout(cct, 20) << "reshard completion identified, new_bucket_id=" << new_bucket_id << dendl;
10932     i = 0; /* resharding is finished, make sure we can retry */
10933
10934     obj = *pobj;
10935     obj.bucket.update_bucket_id(new_bucket_id);
10936     pobj = &obj;
10937   }
10938
10939   if (r < 0) {
10940     return r;
10941   }
10942
10943   return 0;
10944 }
10945
10946 int RGWRados::block_while_resharding(RGWRados::BucketShard *bs, string *new_bucket_id)
10947 {
10948   std::shared_ptr<RGWReshardWait> waiter = reshard_wait;
10949
10950   return waiter->block_while_resharding(bs, new_bucket_id);
10951 }
10952
10953 int RGWRados::bucket_index_link_olh(const RGWBucketInfo& bucket_info, RGWObjState& olh_state, const rgw_obj& obj_instance,
10954                                     bool delete_marker,
10955                                     const string& op_tag,
10956                                     struct rgw_bucket_dir_entry_meta *meta,
10957                                     uint64_t olh_epoch,
10958                                     real_time unmod_since, bool high_precision_time, rgw_zone_set *_zones_trace)
10959 {
10960   rgw_rados_ref ref;
10961   int r = get_obj_head_ref(bucket_info, obj_instance, &ref);
10962   if (r < 0) {
10963     return r;
10964   }
10965
10966   rgw_zone_set zones_trace;
10967   if (_zones_trace) {
10968     zones_trace = *_zones_trace;
10969   } else {
10970     zones_trace.insert(get_zone().id);
10971   }
10972
10973   BucketShard bs(this);
10974
10975   cls_rgw_obj_key key(obj_instance.key.get_index_key_name(), obj_instance.key.instance);
10976   r = guard_reshard(&bs, obj_instance, [&](BucketShard *bs) -> int { 
10977                     librados::ObjectWriteOperation op;
10978                     cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
10979                     return cls_rgw_bucket_link_olh(bs->index_ctx, op,
10980                                                    bs->bucket_obj, key, olh_state.olh_tag, delete_marker, op_tag, meta, olh_epoch,
10981                                                    unmod_since, high_precision_time,
10982                                                    get_zone().log_data, zones_trace);
10983                     });
10984   if (r < 0) {
10985     ldout(cct, 20) << "cls_rgw_bucket_link_olh() returned r=" << r << dendl;
10986     return r;
10987   }
10988
10989   return 0;
10990 }
10991
10992 void RGWRados::bucket_index_guard_olh_op(RGWObjState& olh_state, ObjectOperation& op)
10993 {
10994   ldout(cct, 20) << __func__ << "(): olh_state.olh_tag=" << string(olh_state.olh_tag.c_str(), olh_state.olh_tag.length()) << dendl;
10995   op.cmpxattr(RGW_ATTR_OLH_ID_TAG, CEPH_OSD_CMPXATTR_OP_EQ, olh_state.olh_tag);
10996 }
10997
10998 int RGWRados::bucket_index_unlink_instance(const RGWBucketInfo& bucket_info, const rgw_obj& obj_instance,
10999                                            const string& op_tag, const string& olh_tag, uint64_t olh_epoch, rgw_zone_set *_zones_trace)
11000 {
11001   rgw_rados_ref ref;
11002   int r = get_obj_head_ref(bucket_info, obj_instance, &ref);
11003   if (r < 0) {
11004     return r;
11005   }
11006
11007   rgw_zone_set zones_trace;
11008   if (_zones_trace) {
11009     zones_trace = *_zones_trace;
11010   }
11011   zones_trace.insert(get_zone().id);
11012
11013   BucketShard bs(this);
11014
11015   cls_rgw_obj_key key(obj_instance.key.get_index_key_name(), obj_instance.key.instance);
11016   r = guard_reshard(&bs, obj_instance, [&](BucketShard *bs) -> int { 
11017                     librados::ObjectWriteOperation op;
11018                     cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
11019                     return cls_rgw_bucket_unlink_instance(bs->index_ctx, op, bs->bucket_obj, key, op_tag,
11020                                                           olh_tag, olh_epoch, get_zone().log_data, zones_trace);
11021                     });
11022   if (r < 0) {
11023     ldout(cct, 20) << "cls_rgw_bucket_link_olh() returned r=" << r << dendl;
11024     return r;
11025   }
11026
11027   return 0;
11028 }
11029
11030 int RGWRados::bucket_index_read_olh_log(const RGWBucketInfo& bucket_info, RGWObjState& state,
11031                                         const rgw_obj& obj_instance, uint64_t ver_marker,
11032                                         map<uint64_t, vector<rgw_bucket_olh_log_entry> > *log,
11033                                         bool *is_truncated)
11034 {
11035   rgw_rados_ref ref;
11036   int r = get_obj_head_ref(bucket_info, obj_instance, &ref);
11037   if (r < 0) {
11038     return r;
11039   }
11040
11041   BucketShard bs(this);
11042   int ret = bs.init(obj_instance.bucket, obj_instance);
11043   if (ret < 0) {
11044     ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
11045     return ret;
11046   }
11047
11048   string olh_tag(state.olh_tag.c_str(), state.olh_tag.length());
11049
11050   cls_rgw_obj_key key(obj_instance.key.get_index_key_name(), string());
11051
11052   ret = guard_reshard(&bs, obj_instance, [&](BucketShard *bs) -> int { 
11053                       ObjectReadOperation op;
11054                       cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
11055                       return cls_rgw_get_olh_log(bs->index_ctx, bs->bucket_obj, op,
11056                                                  key, ver_marker, olh_tag, log, is_truncated);
11057                     });
11058   if (ret < 0) {
11059     ldout(cct, 20) << "cls_rgw_get_olh_log() returned r=" << r << dendl;
11060     return ret;
11061   }
11062
11063   return 0;
11064 }
11065
11066 int RGWRados::bucket_index_trim_olh_log(const RGWBucketInfo& bucket_info, RGWObjState& state, const rgw_obj& obj_instance, uint64_t ver)
11067 {
11068   rgw_rados_ref ref;
11069   int r = get_obj_head_ref(bucket_info, obj_instance, &ref);
11070   if (r < 0) {
11071     return r;
11072   }
11073
11074   BucketShard bs(this);
11075   int ret = bs.init(obj_instance.bucket, obj_instance);
11076   if (ret < 0) {
11077     ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
11078     return ret;
11079   }
11080
11081   string olh_tag(state.olh_tag.c_str(), state.olh_tag.length());
11082
11083   cls_rgw_obj_key key(obj_instance.key.get_index_key_name(), string());
11084
11085   ret = guard_reshard(&bs, obj_instance, [&](BucketShard *pbs) -> int { 
11086                       ObjectWriteOperation op;
11087                       cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
11088                       cls_rgw_trim_olh_log(op, key, ver, olh_tag);
11089                       return pbs->index_ctx.operate(pbs->bucket_obj, &op);
11090                       });
11091   if (ret < 0) {
11092     ldout(cct, 20) << "cls_rgw_trim_olh_log() returned r=" << ret << dendl;
11093     return ret;
11094   }
11095
11096   return 0;
11097 }
11098
11099 int RGWRados::bucket_index_clear_olh(const RGWBucketInfo& bucket_info, RGWObjState& state, const rgw_obj& obj_instance)
11100 {
11101   rgw_rados_ref ref;
11102   int r = get_obj_head_ref(bucket_info, obj_instance, &ref);
11103   if (r < 0) {
11104     return r;
11105   }
11106
11107   BucketShard bs(this);
11108
11109   string olh_tag(state.olh_tag.c_str(), state.olh_tag.length());
11110
11111   cls_rgw_obj_key key(obj_instance.key.get_index_key_name(), string());
11112
11113   int ret = guard_reshard(&bs, obj_instance, [&](BucketShard *pbs) -> int { 
11114                           ObjectWriteOperation op;
11115                           cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
11116                           return cls_rgw_clear_olh(pbs->index_ctx, op, pbs->bucket_obj, key, olh_tag);
11117                           });
11118   if (ret < 0) {
11119     ldout(cct, 5) << "cls_rgw_clear_olh() returned ret=" << ret << dendl;
11120     return ret;
11121   }
11122
11123   return 0;
11124 }
11125
11126 int RGWRados::apply_olh_log(RGWObjectCtx& obj_ctx, RGWObjState& state, const RGWBucketInfo& bucket_info, const rgw_obj& obj,
11127                             bufferlist& olh_tag, map<uint64_t, vector<rgw_bucket_olh_log_entry> >& log,
11128                             uint64_t *plast_ver, rgw_zone_set* zones_trace)
11129 {
11130   if (log.empty()) {
11131     return 0;
11132   }
11133
11134   librados::ObjectWriteOperation op;
11135
11136   uint64_t last_ver = log.rbegin()->first;
11137   *plast_ver = last_ver;
11138
11139   map<uint64_t, vector<rgw_bucket_olh_log_entry> >::iterator iter = log.begin();
11140
11141   op.cmpxattr(RGW_ATTR_OLH_ID_TAG, CEPH_OSD_CMPXATTR_OP_EQ, olh_tag);
11142   op.cmpxattr(RGW_ATTR_OLH_VER, CEPH_OSD_CMPXATTR_OP_GT, last_ver);
11143
11144   bool need_to_link = false;
11145   cls_rgw_obj_key key;
11146   bool delete_marker = false;
11147   list<cls_rgw_obj_key> remove_instances;
11148   bool need_to_remove = false;
11149
11150   for (iter = log.begin(); iter != log.end(); ++iter) {
11151     vector<rgw_bucket_olh_log_entry>::iterator viter = iter->second.begin();
11152     for (; viter != iter->second.end(); ++viter) {
11153       rgw_bucket_olh_log_entry& entry = *viter;
11154
11155       ldout(cct, 20) << "olh_log_entry: op=" << (int)entry.op
11156                      << " key=" << entry.key.name << "[" << entry.key.instance << "] "
11157                      << (entry.delete_marker ? "(delete)" : "") << dendl;
11158       switch (entry.op) {
11159       case CLS_RGW_OLH_OP_REMOVE_INSTANCE:
11160         remove_instances.push_back(entry.key);
11161         break;
11162       case CLS_RGW_OLH_OP_LINK_OLH:
11163         need_to_link = true;
11164         need_to_remove = false;
11165         key = entry.key;
11166         delete_marker = entry.delete_marker;
11167         break;
11168       case CLS_RGW_OLH_OP_UNLINK_OLH:
11169         need_to_remove = true;
11170         need_to_link = false;
11171         break;
11172       default:
11173         ldout(cct, 0) << "ERROR: apply_olh_log: invalid op: " << (int)entry.op << dendl;
11174         return -EIO;
11175       }
11176       string attr_name = RGW_ATTR_OLH_PENDING_PREFIX;
11177       attr_name.append(entry.op_tag);
11178       op.rmxattr(attr_name.c_str());
11179     }
11180   }
11181
11182   rgw_rados_ref ref;
11183   int r = get_obj_head_ref(bucket_info, obj, &ref);
11184   if (r < 0) {
11185     return r;
11186   }
11187
11188   const rgw_bucket& bucket = obj.bucket;
11189
11190   if (need_to_link) {
11191     rgw_obj target(bucket, key);
11192     RGWOLHInfo info;
11193     info.target = target;
11194     info.removed = delete_marker;
11195     bufferlist bl;
11196     ::encode(info, bl);
11197     op.setxattr(RGW_ATTR_OLH_INFO, bl);
11198   }
11199
11200   /* first remove object instances */
11201   for (list<cls_rgw_obj_key>::iterator liter = remove_instances.begin();
11202        liter != remove_instances.end(); ++liter) {
11203     cls_rgw_obj_key& key = *liter;
11204     rgw_obj obj_instance(bucket, key);
11205     int ret = delete_obj(obj_ctx, bucket_info, obj_instance, 0, RGW_BILOG_FLAG_VERSIONED_OP, ceph::real_time(), zones_trace);
11206     if (ret < 0 && ret != -ENOENT) {
11207       ldout(cct, 0) << "ERROR: delete_obj() returned " << ret << " obj_instance=" << obj_instance << dendl;
11208       return ret;
11209     }
11210   }
11211
11212   /* update olh object */
11213   r = ref.ioctx.operate(ref.oid, &op);
11214   if (r == -ECANCELED) {
11215     r = 0;
11216   }
11217   if (r < 0) {
11218     ldout(cct, 0) << "ERROR: could not apply olh update, r=" << r << dendl;
11219     return r;
11220   }
11221
11222   r = bucket_index_trim_olh_log(bucket_info, state, obj, last_ver);
11223   if (r < 0) {
11224     ldout(cct, 0) << "ERROR: could not trim olh log, r=" << r << dendl;
11225     return r;
11226   }
11227
11228   if (need_to_remove) {
11229     ObjectWriteOperation rm_op;
11230
11231     rm_op.cmpxattr(RGW_ATTR_OLH_ID_TAG, CEPH_OSD_CMPXATTR_OP_EQ, olh_tag);
11232     rm_op.cmpxattr(RGW_ATTR_OLH_VER, CEPH_OSD_CMPXATTR_OP_GT, last_ver);
11233     cls_obj_check_prefix_exist(rm_op, RGW_ATTR_OLH_PENDING_PREFIX, true); /* fail if found one of these, pending modification */
11234     rm_op.remove();
11235
11236     r = ref.ioctx.operate(ref.oid, &rm_op);
11237     if (r == -ECANCELED) {
11238       return 0; /* someone else won this race */
11239     } else {
11240       /* 
11241        * only clear if was successful, otherwise we might clobber pending operations on this object
11242        */
11243       r = bucket_index_clear_olh(bucket_info, state, obj);
11244       if (r < 0) {
11245         ldout(cct, 0) << "ERROR: could not clear bucket index olh entries r=" << r << dendl;
11246         return r;
11247       }
11248     }
11249   }
11250
11251   return 0;
11252 }
11253
11254 /*
11255  * read olh log and apply it
11256  */
11257 int RGWRados::update_olh(RGWObjectCtx& obj_ctx, RGWObjState *state, const RGWBucketInfo& bucket_info, const rgw_obj& obj, rgw_zone_set *zones_trace)
11258 {
11259   map<uint64_t, vector<rgw_bucket_olh_log_entry> > log;
11260   bool is_truncated;
11261   uint64_t ver_marker = 0;
11262
11263   do {
11264     int ret = bucket_index_read_olh_log(bucket_info, *state, obj, ver_marker, &log, &is_truncated);
11265     if (ret < 0) {
11266       return ret;
11267     }
11268     ret = apply_olh_log(obj_ctx, *state, bucket_info, obj, state->olh_tag, log, &ver_marker, zones_trace);
11269     if (ret < 0) {
11270       return ret;
11271     }
11272   } while (is_truncated);
11273
11274   return 0;
11275 }
11276
11277 int RGWRados::set_olh(RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, const rgw_obj& target_obj, bool delete_marker, rgw_bucket_dir_entry_meta *meta,
11278                       uint64_t olh_epoch, real_time unmod_since, bool high_precision_time, rgw_zone_set *zones_trace)
11279 {
11280   string op_tag;
11281
11282   rgw_obj olh_obj = target_obj;
11283   olh_obj.key.instance.clear();
11284
11285   RGWObjState *state = NULL;
11286
11287   int ret = 0;
11288   int i;
11289   
11290 #define MAX_ECANCELED_RETRY 100
11291   for (i = 0; i < MAX_ECANCELED_RETRY; i++) {
11292     if (ret == -ECANCELED) {
11293       obj_ctx.obj.invalidate(olh_obj);
11294     }
11295
11296     ret = get_obj_state(&obj_ctx, bucket_info, olh_obj, &state, false); /* don't follow olh */
11297     if (ret < 0) {
11298       return ret;
11299     }
11300
11301     ret = olh_init_modification(bucket_info, *state, olh_obj, &op_tag);
11302     if (ret < 0) {
11303       ldout(cct, 20) << "olh_init_modification() target_obj=" << target_obj << " delete_marker=" << (int)delete_marker << " returned " << ret << dendl;
11304       if (ret == -ECANCELED) {
11305         continue;
11306       }
11307       return ret;
11308     }
11309     ret = bucket_index_link_olh(bucket_info, *state, target_obj, delete_marker, op_tag, meta, olh_epoch, unmod_since, high_precision_time, zones_trace);
11310     if (ret < 0) {
11311       ldout(cct, 20) << "bucket_index_link_olh() target_obj=" << target_obj << " delete_marker=" << (int)delete_marker << " returned " << ret << dendl;
11312       if (ret == -ECANCELED) {
11313         continue;
11314       }
11315       return ret;
11316     }
11317     break;
11318   }
11319
11320   if (i == MAX_ECANCELED_RETRY) {
11321     ldout(cct, 0) << "ERROR: exceeded max ECANCELED retries, aborting (EIO)" << dendl;
11322     return -EIO;
11323   }
11324
11325   ret = update_olh(obj_ctx, state, bucket_info, olh_obj);
11326   if (ret == -ECANCELED) { /* already did what we needed, no need to retry, raced with another user */
11327     ret = 0;
11328   }
11329   if (ret < 0) {
11330     ldout(cct, 20) << "update_olh() target_obj=" << target_obj << " returned " << ret << dendl;
11331     return ret;
11332   }
11333
11334   return 0;
11335 }
11336
11337 int RGWRados::unlink_obj_instance(RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, const rgw_obj& target_obj,
11338                                   uint64_t olh_epoch, rgw_zone_set *zones_trace)
11339 {
11340   string op_tag;
11341
11342   rgw_obj olh_obj = target_obj;
11343   olh_obj.key.instance.clear();
11344
11345   RGWObjState *state = NULL;
11346
11347   int ret = 0;
11348   int i;
11349
11350   for (i = 0; i < MAX_ECANCELED_RETRY; i++) {
11351     if (ret == -ECANCELED) {
11352       obj_ctx.obj.invalidate(olh_obj);
11353     }
11354
11355     ret = get_obj_state(&obj_ctx, bucket_info, olh_obj, &state, false); /* don't follow olh */
11356     if (ret < 0)
11357       return ret;
11358
11359     ret = olh_init_modification(bucket_info, *state, olh_obj, &op_tag);
11360     if (ret < 0) {
11361       ldout(cct, 20) << "olh_init_modification() target_obj=" << target_obj << " returned " << ret << dendl;
11362       if (ret == -ECANCELED) {
11363         continue;
11364       }
11365       return ret;
11366     }
11367
11368     string olh_tag(state->olh_tag.c_str(), state->olh_tag.length());
11369
11370     ret = bucket_index_unlink_instance(bucket_info, target_obj, op_tag, olh_tag, olh_epoch, zones_trace);
11371     if (ret < 0) {
11372       ldout(cct, 20) << "bucket_index_unlink_instance() target_obj=" << target_obj << " returned " << ret << dendl;
11373       if (ret == -ECANCELED) {
11374         continue;
11375       }
11376       return ret;
11377     }
11378     break;
11379   }
11380
11381   if (i == MAX_ECANCELED_RETRY) {
11382     ldout(cct, 0) << "ERROR: exceeded max ECANCELED retries, aborting (EIO)" << dendl;
11383     return -EIO;
11384   }
11385
11386   ret = update_olh(obj_ctx, state, bucket_info, olh_obj, zones_trace);
11387   if (ret == -ECANCELED) { /* already did what we needed, no need to retry, raced with another user */
11388     return 0;
11389   }
11390   if (ret < 0) {
11391     ldout(cct, 20) << "update_olh() target_obj=" << target_obj << " returned " << ret << dendl;
11392     return ret;
11393   }
11394
11395   return 0;
11396 }
11397
11398 void RGWRados::gen_rand_obj_instance_name(rgw_obj *target_obj)
11399 {
11400 #define OBJ_INSTANCE_LEN 32
11401   char buf[OBJ_INSTANCE_LEN + 1];
11402
11403   gen_rand_alphanumeric_no_underscore(cct, buf, OBJ_INSTANCE_LEN); /* don't want it to get url escaped,
11404                                                                       no underscore for instance name due to the way we encode the raw keys */
11405
11406   target_obj->key.set_instance(buf);
11407 }
11408
11409 static void filter_attrset(map<string, bufferlist>& unfiltered_attrset, const string& check_prefix,
11410                            map<string, bufferlist> *attrset)
11411 {
11412   attrset->clear();
11413   map<string, bufferlist>::iterator iter;
11414   for (iter = unfiltered_attrset.lower_bound(check_prefix);
11415        iter != unfiltered_attrset.end(); ++iter) {
11416     if (!boost::algorithm::starts_with(iter->first, check_prefix))
11417       break;
11418     (*attrset)[iter->first] = iter->second;
11419   }
11420 }
11421
11422 int RGWRados::get_olh(const RGWBucketInfo& bucket_info, const rgw_obj& obj, RGWOLHInfo *olh)
11423 {
11424   map<string, bufferlist> unfiltered_attrset;
11425
11426   ObjectReadOperation op;
11427   op.getxattrs(&unfiltered_attrset, NULL);
11428
11429   bufferlist outbl;
11430   int r = obj_operate(bucket_info, obj, &op);
11431
11432   if (r < 0) {
11433     return r;
11434   }
11435   map<string, bufferlist> attrset;
11436
11437   filter_attrset(unfiltered_attrset, RGW_ATTR_OLH_PREFIX, &attrset);
11438
11439   map<string, bufferlist>::iterator iter = attrset.find(RGW_ATTR_OLH_INFO);
11440   if (iter == attrset.end()) { /* not an olh */
11441     return -EINVAL;
11442   }
11443
11444   try {
11445     bufferlist::iterator biter = iter->second.begin();
11446     ::decode(*olh, biter);
11447   } catch (buffer::error& err) {
11448     ldout(cct, 0) << "ERROR: failed to decode olh info" << dendl;
11449     return -EIO;
11450   }
11451
11452   return 0;
11453 }
11454
11455 void RGWRados::check_pending_olh_entries(map<string, bufferlist>& pending_entries, 
11456                                          map<string, bufferlist> *rm_pending_entries)
11457 {
11458   map<string, bufferlist>::iterator iter = pending_entries.begin();
11459
11460   real_time now = real_clock::now();
11461
11462   while (iter != pending_entries.end()) {
11463     bufferlist::iterator biter = iter->second.begin();
11464     RGWOLHPendingInfo pending_info;
11465     try {
11466       ::decode(pending_info, biter);
11467     } catch (buffer::error& err) {
11468       /* skipping bad entry, we could remove it but it might hide a bug */
11469       ldout(cct, 0) << "ERROR: failed to decode pending entry " << iter->first << dendl;
11470       ++iter;
11471       continue;
11472     }
11473
11474     map<string, bufferlist>::iterator cur_iter = iter;
11475     ++iter;
11476     if (now - pending_info.time >= make_timespan(cct->_conf->rgw_olh_pending_timeout_sec)) {
11477       (*rm_pending_entries)[cur_iter->first] = cur_iter->second;
11478       pending_entries.erase(cur_iter);
11479     } else {
11480       /* entries names are sorted by time (rounded to a second) */
11481       break;
11482     }
11483   }
11484 }
11485
11486 int RGWRados::remove_olh_pending_entries(const RGWBucketInfo& bucket_info, RGWObjState& state, const rgw_obj& olh_obj, map<string, bufferlist>& pending_attrs)
11487 {
11488   ObjectWriteOperation op;
11489
11490   bucket_index_guard_olh_op(state, op);
11491
11492   for (map<string, bufferlist>::iterator iter = pending_attrs.begin(); iter != pending_attrs.end(); ++iter) {
11493     op.rmxattr(iter->first.c_str());
11494   }
11495
11496   rgw_rados_ref ref;
11497   int r = get_obj_head_ref(bucket_info, olh_obj, &ref);
11498   if (r < 0) {
11499     return r;
11500   }
11501
11502   /* update olh object */
11503   r = ref.ioctx.operate(ref.oid, &op);
11504   if (r == -ENOENT || r == -ECANCELED) {
11505     /* raced with some other change, shouldn't sweat about it */
11506     r = 0;
11507   }
11508   if (r < 0) {
11509     ldout(cct, 0) << "ERROR: could not apply olh update, r=" << r << dendl;
11510     return r;
11511   }
11512
11513   return 0;
11514 }
11515
11516 int RGWRados::follow_olh(const RGWBucketInfo& bucket_info, RGWObjectCtx& obj_ctx, RGWObjState *state, const rgw_obj& olh_obj, rgw_obj *target)
11517 {
11518   map<string, bufferlist> pending_entries;
11519   filter_attrset(state->attrset, RGW_ATTR_OLH_PENDING_PREFIX, &pending_entries);
11520
11521   map<string, bufferlist> rm_pending_entries;
11522   check_pending_olh_entries(pending_entries, &rm_pending_entries);
11523
11524   if (!rm_pending_entries.empty()) {
11525     int ret = remove_olh_pending_entries(bucket_info, *state, olh_obj, rm_pending_entries);
11526     if (ret < 0) {
11527       ldout(cct, 20) << "ERROR: rm_pending_entries returned ret=" << ret << dendl;
11528       return ret;
11529     }
11530   }
11531   if (!pending_entries.empty()) {
11532     ldout(cct, 20) << __func__ << "(): found pending entries, need to update_olh() on bucket=" << olh_obj.bucket << dendl;
11533
11534     int ret = update_olh(obj_ctx, state, bucket_info, olh_obj);
11535     if (ret < 0) {
11536       return ret;
11537     }
11538   }
11539
11540   map<string, bufferlist>::iterator iter = state->attrset.find(RGW_ATTR_OLH_INFO);
11541   assert(iter != state->attrset.end());
11542   RGWOLHInfo olh;
11543   try {
11544     bufferlist::iterator biter = iter->second.begin();
11545     ::decode(olh, biter);
11546   } catch (buffer::error& err) {
11547     ldout(cct, 0) << "ERROR: failed to decode olh info" << dendl;
11548     return -EIO;
11549   }
11550
11551   if (olh.removed) {
11552     return -ENOENT;
11553   }
11554
11555   *target = olh.target;
11556
11557   return 0;
11558 }
11559
11560 int RGWRados::raw_obj_stat(rgw_raw_obj& obj, uint64_t *psize, real_time *pmtime, uint64_t *epoch,
11561                            map<string, bufferlist> *attrs, bufferlist *first_chunk,
11562                            RGWObjVersionTracker *objv_tracker)
11563 {
11564   rgw_rados_ref ref;
11565   int r = get_raw_obj_ref(obj, &ref);
11566   if (r < 0) {
11567     return r;
11568   }
11569
11570   map<string, bufferlist> unfiltered_attrset;
11571   uint64_t size = 0;
11572   struct timespec mtime_ts;
11573
11574   ObjectReadOperation op;
11575   if (objv_tracker) {
11576     objv_tracker->prepare_op_for_read(&op);
11577   }
11578   if (attrs) {
11579     op.getxattrs(&unfiltered_attrset, NULL);
11580   }
11581   if (psize || pmtime) {
11582     op.stat2(&size, &mtime_ts, NULL);
11583   }
11584   if (first_chunk) {
11585     op.read(0, cct->_conf->rgw_max_chunk_size, first_chunk, NULL);
11586   }
11587   bufferlist outbl;
11588   r = ref.ioctx.operate(ref.oid, &op, &outbl);
11589
11590   if (epoch) {
11591     *epoch = ref.ioctx.get_last_version();
11592   }
11593
11594   if (r < 0)
11595     return r;
11596
11597   if (psize)
11598     *psize = size;
11599   if (pmtime)
11600     *pmtime = ceph::real_clock::from_timespec(mtime_ts);
11601   if (attrs) {
11602     filter_attrset(unfiltered_attrset, RGW_ATTR_PREFIX, attrs);
11603   }
11604
11605   return 0;
11606 }
11607
11608 int RGWRados::get_bucket_stats(RGWBucketInfo& bucket_info, int shard_id, string *bucket_ver, string *master_ver,
11609     map<RGWObjCategory, RGWStorageStats>& stats, string *max_marker, bool *syncstopped)
11610 {
11611   map<string, rgw_bucket_dir_header> headers;
11612   map<int, string> bucket_instance_ids;
11613   int r = cls_bucket_head(bucket_info, shard_id, headers, &bucket_instance_ids);
11614   if (r < 0) {
11615     return r;
11616   }
11617
11618   assert(headers.size() == bucket_instance_ids.size());
11619
11620   map<string, rgw_bucket_dir_header>::iterator iter = headers.begin();
11621   map<int, string>::iterator viter = bucket_instance_ids.begin();
11622   BucketIndexShardsManager ver_mgr;
11623   BucketIndexShardsManager master_ver_mgr;
11624   BucketIndexShardsManager marker_mgr;
11625   char buf[64];
11626   for(; iter != headers.end(); ++iter, ++viter) {
11627     accumulate_raw_stats(iter->second, stats);
11628     snprintf(buf, sizeof(buf), "%lu", (unsigned long)iter->second.ver);
11629     ver_mgr.add(viter->first, string(buf));
11630     snprintf(buf, sizeof(buf), "%lu", (unsigned long)iter->second.master_ver);
11631     master_ver_mgr.add(viter->first, string(buf));
11632     if (shard_id >= 0) {
11633       *max_marker = iter->second.max_marker;
11634     } else {
11635       marker_mgr.add(viter->first, iter->second.max_marker);
11636     }
11637     if (syncstopped != NULL)
11638       *syncstopped = iter->second.syncstopped;
11639   }
11640   ver_mgr.to_string(bucket_ver);
11641   master_ver_mgr.to_string(master_ver);
11642   if (shard_id < 0) {
11643     marker_mgr.to_string(max_marker);
11644   }
11645   return 0;
11646 }
11647
11648 int RGWRados::get_bi_log_status(RGWBucketInfo& bucket_info, int shard_id,
11649     map<int, string>& markers)
11650 {
11651   map<string, rgw_bucket_dir_header> headers;
11652   map<int, string> bucket_instance_ids;
11653   int r = cls_bucket_head(bucket_info, shard_id, headers, &bucket_instance_ids);
11654   if (r < 0)
11655     return r;
11656
11657   assert(headers.size() == bucket_instance_ids.size());
11658
11659   map<string, rgw_bucket_dir_header>::iterator iter = headers.begin();
11660   map<int, string>::iterator viter = bucket_instance_ids.begin();
11661
11662   for(; iter != headers.end(); ++iter, ++viter) {
11663     if (shard_id >= 0) {
11664       markers[shard_id] = iter->second.max_marker;
11665     } else {
11666       markers[viter->first] = iter->second.max_marker;
11667     }
11668   }
11669   return 0;
11670 }
11671
11672 class RGWGetBucketStatsContext : public RGWGetDirHeader_CB {
11673   RGWGetBucketStats_CB *cb;
11674   uint32_t pendings;
11675   map<RGWObjCategory, RGWStorageStats> stats;
11676   int ret_code;
11677   bool should_cb;
11678   Mutex lock;
11679
11680 public:
11681   RGWGetBucketStatsContext(RGWGetBucketStats_CB *_cb, uint32_t _pendings)
11682     : cb(_cb), pendings(_pendings), stats(), ret_code(0), should_cb(true),
11683     lock("RGWGetBucketStatsContext") {}
11684
11685   void handle_response(int r, rgw_bucket_dir_header& header) override {
11686     Mutex::Locker l(lock);
11687     if (should_cb) {
11688       if ( r >= 0) {
11689         accumulate_raw_stats(header, stats);
11690       } else {
11691         ret_code = r;
11692       }
11693
11694       // Are we all done?
11695       if (--pendings == 0) {
11696         if (!ret_code) {
11697           cb->set_response(&stats);
11698         }
11699         cb->handle_response(ret_code);
11700         cb->put();
11701       }
11702     }
11703   }
11704
11705   void unset_cb() {
11706     Mutex::Locker l(lock);
11707     should_cb = false;
11708   }
11709 };
11710
11711 int RGWRados::get_bucket_stats_async(RGWBucketInfo& bucket_info, int shard_id, RGWGetBucketStats_CB *ctx)
11712 {
11713   int num_aio = 0;
11714   RGWGetBucketStatsContext *get_ctx = new RGWGetBucketStatsContext(ctx, bucket_info.num_shards ? : 1);
11715   assert(get_ctx);
11716   int r = cls_bucket_head_async(bucket_info, shard_id, get_ctx, &num_aio);
11717   if (r < 0) {
11718     ctx->put();
11719     if (num_aio) {
11720       get_ctx->unset_cb();
11721     }
11722   }
11723   get_ctx->put();
11724   return r;
11725 }
11726
11727 class RGWGetUserStatsContext : public RGWGetUserHeader_CB {
11728   RGWGetUserStats_CB *cb;
11729
11730 public:
11731   explicit RGWGetUserStatsContext(RGWGetUserStats_CB * const cb)
11732     : cb(cb) {}
11733
11734   void handle_response(int r, cls_user_header& header) override {
11735     const cls_user_stats& hs = header.stats;
11736     if (r >= 0) {
11737       RGWStorageStats stats;
11738
11739       stats.size = hs.total_bytes;
11740       stats.size_rounded = hs.total_bytes_rounded;
11741       stats.num_objects = hs.total_entries;
11742
11743       cb->set_response(stats);
11744     }
11745
11746     cb->handle_response(r);
11747
11748     cb->put();
11749   }
11750 };
11751
11752 int RGWRados::get_user_stats(const rgw_user& user, RGWStorageStats& stats)
11753 {
11754   string user_str = user.to_str();
11755
11756   cls_user_header header;
11757   int r = cls_user_get_header(user_str, &header);
11758   if (r < 0)
11759     return r;
11760
11761   const cls_user_stats& hs = header.stats;
11762
11763   stats.size = hs.total_bytes;
11764   stats.size_rounded = hs.total_bytes_rounded;
11765   stats.num_objects = hs.total_entries;
11766
11767   return 0;
11768 }
11769
11770 int RGWRados::get_user_stats_async(const rgw_user& user, RGWGetUserStats_CB *ctx)
11771 {
11772   string user_str = user.to_str();
11773
11774   RGWGetUserStatsContext *get_ctx = new RGWGetUserStatsContext(ctx);
11775   int r = cls_user_get_header_async(user_str, get_ctx);
11776   if (r < 0) {
11777     ctx->put();
11778     delete get_ctx;
11779     return r;
11780   }
11781
11782   return 0;
11783 }
11784
11785 void RGWRados::get_bucket_meta_oid(const rgw_bucket& bucket, string& oid)
11786 {
11787   oid = RGW_BUCKET_INSTANCE_MD_PREFIX + bucket.get_key(':');
11788 }
11789
11790 void RGWRados::get_bucket_instance_obj(const rgw_bucket& bucket, rgw_raw_obj& obj)
11791 {
11792   if (!bucket.oid.empty()) {
11793     obj.init(get_zone_params().domain_root, bucket.oid);
11794   } else {
11795     string oid;
11796     get_bucket_meta_oid(bucket, oid);
11797     obj.init(get_zone_params().domain_root, oid);
11798   }
11799 }
11800
11801 int RGWRados::get_bucket_instance_info(RGWObjectCtx& obj_ctx, const string& meta_key, RGWBucketInfo& info,
11802                                        real_time *pmtime, map<string, bufferlist> *pattrs)
11803 {
11804   size_t pos = meta_key.find(':');
11805   if (pos == string::npos) {
11806     return -EINVAL;
11807   }
11808   string oid = RGW_BUCKET_INSTANCE_MD_PREFIX + meta_key;
11809   rgw_bucket_instance_key_to_oid(oid);
11810
11811   return get_bucket_instance_from_oid(obj_ctx, oid, info, pmtime, pattrs);
11812 }
11813
11814 int RGWRados::get_bucket_instance_info(RGWObjectCtx& obj_ctx, const rgw_bucket& bucket, RGWBucketInfo& info,
11815                                        real_time *pmtime, map<string, bufferlist> *pattrs)
11816 {
11817   string oid;
11818   if (bucket.oid.empty()) {
11819     get_bucket_meta_oid(bucket, oid);
11820   } else {
11821     oid = bucket.oid;
11822   }
11823
11824   return get_bucket_instance_from_oid(obj_ctx, oid, info, pmtime, pattrs);
11825 }
11826
11827 int RGWRados::get_bucket_instance_from_oid(RGWObjectCtx& obj_ctx, const string& oid, RGWBucketInfo& info,
11828                                            real_time *pmtime, map<string, bufferlist> *pattrs,
11829                                            rgw_cache_entry_info *cache_info)
11830 {
11831   ldout(cct, 20) << "reading from " << get_zone_params().domain_root << ":" << oid << dendl;
11832
11833   bufferlist epbl;
11834
11835   int ret = rgw_get_system_obj(this, obj_ctx, get_zone_params().domain_root, oid, epbl, &info.objv_tracker, pmtime, pattrs, cache_info);
11836   if (ret < 0) {
11837     return ret;
11838   }
11839
11840   bufferlist::iterator iter = epbl.begin();
11841   try {
11842     ::decode(info, iter);
11843   } catch (buffer::error& err) {
11844     ldout(cct, 0) << "ERROR: could not decode buffer info, caught buffer::error" << dendl;
11845     return -EIO;
11846   }
11847   info.bucket.oid = oid;
11848   return 0;
11849 }
11850
11851 int RGWRados::get_bucket_entrypoint_info(RGWObjectCtx& obj_ctx,
11852                                          const string& tenant_name,
11853                                          const string& bucket_name,
11854                                          RGWBucketEntryPoint& entry_point,
11855                                          RGWObjVersionTracker *objv_tracker,
11856                                          real_time *pmtime,
11857                                          map<string, bufferlist> *pattrs,
11858                                          rgw_cache_entry_info *cache_info)
11859 {
11860   bufferlist bl;
11861   string bucket_entry;
11862
11863   rgw_make_bucket_entry_name(tenant_name, bucket_name, bucket_entry);
11864   int ret = rgw_get_system_obj(this, obj_ctx, get_zone_params().domain_root, bucket_entry, bl, objv_tracker, pmtime, pattrs, cache_info);
11865   if (ret < 0) {
11866     return ret;
11867   }
11868
11869   bufferlist::iterator iter = bl.begin();
11870   try {
11871     ::decode(entry_point, iter);
11872   } catch (buffer::error& err) {
11873     ldout(cct, 0) << "ERROR: could not decode buffer info, caught buffer::error" << dendl;
11874     return -EIO;
11875   }
11876   return 0;
11877 }
11878
11879 int RGWRados::convert_old_bucket_info(RGWObjectCtx& obj_ctx,
11880                                       const string& tenant_name,
11881                                       const string& bucket_name)
11882 {
11883   RGWBucketEntryPoint entry_point;
11884   real_time ep_mtime;
11885   RGWObjVersionTracker ot;
11886   map<string, bufferlist> attrs;
11887   RGWBucketInfo info;
11888
11889   ldout(cct, 10) << "RGWRados::convert_old_bucket_info(): bucket=" << bucket_name << dendl;
11890
11891   int ret = get_bucket_entrypoint_info(obj_ctx, tenant_name, bucket_name, entry_point, &ot, &ep_mtime, &attrs);
11892   if (ret < 0) {
11893     ldout(cct, 0) << "ERROR: get_bucket_entrypoint_info() returned " << ret << " bucket=" << bucket_name << dendl;
11894     return ret;
11895   }
11896
11897   if (!entry_point.has_bucket_info) {
11898     /* already converted! */
11899     return 0;
11900   }
11901
11902   info = entry_point.old_bucket_info;
11903   info.bucket.oid = bucket_name;
11904   info.ep_objv = ot.read_version;
11905
11906   ot.generate_new_write_ver(cct);
11907
11908   ret = put_linked_bucket_info(info, false, ep_mtime, &ot.write_version, &attrs, true);
11909   if (ret < 0) {
11910     ldout(cct, 0) << "ERROR: failed to put_linked_bucket_info(): " << ret << dendl;
11911     return ret;
11912   }
11913
11914   return 0;
11915 }
11916
11917 int RGWRados::get_bucket_info(RGWObjectCtx& obj_ctx,
11918                               const string& tenant, const string& bucket_name, RGWBucketInfo& info,
11919                               real_time *pmtime, map<string, bufferlist> *pattrs)
11920 {
11921   bucket_info_entry e;
11922   string bucket_entry;
11923   rgw_make_bucket_entry_name(tenant, bucket_name, bucket_entry);
11924
11925   if (binfo_cache->find(bucket_entry, &e)) {
11926     info = e.info;
11927     if (pattrs)
11928       *pattrs = e.attrs;
11929     if (pmtime)
11930       *pmtime = e.mtime;
11931     return 0;
11932   }
11933
11934   RGWBucketEntryPoint entry_point;
11935   real_time ep_mtime;
11936   RGWObjVersionTracker ot;
11937   rgw_cache_entry_info entry_cache_info;
11938   int ret = get_bucket_entrypoint_info(obj_ctx, tenant, bucket_name, entry_point, &ot, &ep_mtime, pattrs, &entry_cache_info);
11939   if (ret < 0) {
11940     /* only init these fields */
11941     info.bucket.tenant = tenant;
11942     info.bucket.name = bucket_name;
11943     return ret;
11944   }
11945
11946   if (entry_point.has_bucket_info) {
11947     info = entry_point.old_bucket_info;
11948     info.bucket.oid = bucket_name;
11949     info.bucket.tenant = tenant;
11950     info.ep_objv = ot.read_version;
11951     ldout(cct, 20) << "rgw_get_bucket_info: old bucket info, bucket=" << info.bucket << " owner " << info.owner << dendl;
11952     return 0;
11953   }
11954
11955   /* data is in the bucket instance object, we need to get attributes from there, clear everything
11956    * that we got
11957    */
11958   if (pattrs) {
11959     pattrs->clear();
11960   }
11961
11962   ldout(cct, 20) << "rgw_get_bucket_info: bucket instance: " << entry_point.bucket << dendl;
11963
11964
11965   /* read bucket instance info */
11966
11967   string oid;
11968   get_bucket_meta_oid(entry_point.bucket, oid);
11969
11970   rgw_cache_entry_info cache_info;
11971
11972   ret = get_bucket_instance_from_oid(obj_ctx, oid, e.info, &e.mtime, &e.attrs, &cache_info);
11973   e.info.ep_objv = ot.read_version;
11974   info = e.info;
11975   if (ret < 0) {
11976     info.bucket.tenant = tenant;
11977     info.bucket.name = bucket_name;
11978     // XXX and why return anything in case of an error anyway?
11979     return ret;
11980   }
11981
11982   if (pmtime)
11983     *pmtime = e.mtime;
11984   if (pattrs)
11985     *pattrs = e.attrs;
11986
11987   list<rgw_cache_entry_info *> cache_info_entries;
11988   cache_info_entries.push_back(&entry_cache_info);
11989   cache_info_entries.push_back(&cache_info);
11990
11991
11992   /* chain to both bucket entry point and bucket instance */
11993   if (!binfo_cache->put(this, bucket_entry, &e, cache_info_entries)) {
11994     ldout(cct, 20) << "couldn't put binfo cache entry, might have raced with data changes" << dendl;
11995   }
11996
11997   return 0;
11998 }
11999
12000 int RGWRados::put_bucket_entrypoint_info(const string& tenant_name, const string& bucket_name, RGWBucketEntryPoint& entry_point,
12001                                          bool exclusive, RGWObjVersionTracker& objv_tracker, real_time mtime,
12002                                          map<string, bufferlist> *pattrs)
12003 {
12004   bufferlist epbl;
12005   ::encode(entry_point, epbl);
12006   string bucket_entry;
12007   rgw_make_bucket_entry_name(tenant_name, bucket_name, bucket_entry);
12008   return rgw_bucket_store_info(this, bucket_entry, epbl, exclusive, pattrs, &objv_tracker, mtime);
12009 }
12010
12011 int RGWRados::put_bucket_instance_info(RGWBucketInfo& info, bool exclusive,
12012                               real_time mtime, map<string, bufferlist> *pattrs)
12013 {
12014   info.has_instance_obj = true;
12015   bufferlist bl;
12016
12017   ::encode(info, bl);
12018
12019   string key = info.bucket.get_key(); /* when we go through meta api, we don't use oid directly */
12020   int ret = rgw_bucket_instance_store_info(this, key, bl, exclusive, pattrs, &info.objv_tracker, mtime);
12021   if (ret == -EEXIST) {
12022     /* well, if it's exclusive we shouldn't overwrite it, because we might race with another
12023      * bucket operation on this specific bucket (e.g., being synced from the master), but
12024      * since bucket instace meta object is unique for this specific bucket instace, we don't
12025      * need to return an error.
12026      * A scenario where we'd get -EEXIST here, is in a multi-zone config, we're not on the
12027      * master, creating a bucket, sending bucket creation to the master, we create the bucket
12028      * locally, while in the sync thread we sync the new bucket.
12029      */
12030     ret = 0;
12031   }
12032   return ret;
12033 }
12034
12035 int RGWRados::put_linked_bucket_info(RGWBucketInfo& info, bool exclusive, real_time mtime, obj_version *pep_objv,
12036                                      map<string, bufferlist> *pattrs, bool create_entry_point)
12037 {
12038   bool create_head = !info.has_instance_obj || create_entry_point;
12039
12040   int ret = put_bucket_instance_info(info, exclusive, mtime, pattrs);
12041   if (ret < 0) {
12042     return ret;
12043   }
12044
12045   if (!create_head)
12046     return 0; /* done! */
12047
12048   RGWBucketEntryPoint entry_point;
12049   entry_point.bucket = info.bucket;
12050   entry_point.owner = info.owner;
12051   entry_point.creation_time = info.creation_time;
12052   entry_point.linked = true;
12053   RGWObjVersionTracker ot;
12054   if (pep_objv && !pep_objv->tag.empty()) {
12055     ot.write_version = *pep_objv;
12056   } else {
12057     ot.generate_new_write_ver(cct);
12058     if (pep_objv) {
12059       *pep_objv = ot.write_version;
12060     }
12061   }
12062   ret = put_bucket_entrypoint_info(info.bucket.tenant, info.bucket.name, entry_point, exclusive, ot, mtime, NULL); 
12063   if (ret < 0)
12064     return ret;
12065
12066   return 0;
12067 }
12068
12069 int RGWRados::omap_get_vals(rgw_raw_obj& obj, bufferlist& header, const string& marker, uint64_t count, std::map<string, bufferlist>& m)
12070 {
12071   rgw_rados_ref ref;
12072   int r = get_raw_obj_ref(obj, &ref);
12073   if (r < 0) {
12074     return r;
12075   }
12076
12077   r = ref.ioctx.omap_get_vals(ref.oid, marker, count, &m);
12078   if (r < 0)
12079     return r;
12080
12081   return 0;
12082  
12083 }
12084
12085 int RGWRados::omap_get_all(rgw_raw_obj& obj, bufferlist& header,
12086                            std::map<string, bufferlist>& m)
12087 {
12088   rgw_rados_ref ref;
12089   int r = get_raw_obj_ref(obj, &ref);
12090   if (r < 0) {
12091     return r;
12092   }
12093
12094 #define MAX_OMAP_GET_ENTRIES 1024
12095   const int count = MAX_OMAP_GET_ENTRIES;
12096   string start_after;
12097
12098   while (true) {
12099     std::map<string, bufferlist> t;
12100     r = ref.ioctx.omap_get_vals(ref.oid, start_after, count, &t);
12101     if (r < 0) {
12102       return r;
12103     }
12104     if (t.empty()) {
12105       break;
12106     }
12107     start_after = t.rbegin()->first;
12108     m.insert(t.begin(), t.end());
12109   }
12110   return 0;
12111 }
12112
12113 int RGWRados::omap_set(rgw_raw_obj& obj, const std::string& key, bufferlist& bl)
12114 {
12115   rgw_rados_ref ref;
12116   int r = get_raw_obj_ref(obj, &ref);
12117   if (r < 0) {
12118     return r;
12119   }
12120   ldout(cct, 15) << "omap_set obj=" << obj << " key=" << key << dendl;
12121
12122   map<string, bufferlist> m;
12123   m[key] = bl;
12124
12125   r = ref.ioctx.omap_set(ref.oid, m);
12126
12127   return r;
12128 }
12129
12130 int RGWRados::omap_set(rgw_raw_obj& obj, std::map<std::string, bufferlist>& m)
12131 {
12132   rgw_rados_ref ref;
12133   int r = get_raw_obj_ref(obj, &ref);
12134   if (r < 0) {
12135     return r;
12136   }
12137
12138   r = ref.ioctx.omap_set(ref.oid, m);
12139
12140   return r;
12141 }
12142
12143 int RGWRados::omap_del(rgw_raw_obj& obj, const std::string& key)
12144 {
12145   rgw_rados_ref ref;
12146   int r = get_raw_obj_ref(obj, &ref);
12147   if (r < 0) {
12148     return r;
12149   }
12150
12151   set<string> k;
12152   k.insert(key);
12153
12154   r = ref.ioctx.omap_rm_keys(ref.oid, k);
12155   return r;
12156 }
12157
12158 int RGWRados::update_containers_stats(map<string, RGWBucketEnt>& m)
12159 {
12160   RGWObjectCtx obj_ctx(this);
12161
12162   map<string, RGWBucketEnt>::iterator iter;
12163   for (iter = m.begin(); iter != m.end(); ++iter) {
12164     RGWBucketEnt& ent = iter->second;
12165     rgw_bucket& bucket = ent.bucket;
12166     ent.count = 0;
12167     ent.size = 0;
12168     ent.size_rounded = 0;
12169
12170     map<string, rgw_bucket_dir_header> headers;
12171
12172     RGWBucketInfo bucket_info;
12173     int ret = get_bucket_instance_info(obj_ctx, bucket, bucket_info, NULL, NULL);
12174     if (ret < 0) {
12175       return ret;
12176     }
12177
12178     int r = cls_bucket_head(bucket_info, RGW_NO_SHARD, headers);
12179     if (r < 0)
12180       return r;
12181
12182     map<string, rgw_bucket_dir_header>::iterator hiter = headers.begin();
12183     for (; hiter != headers.end(); ++hiter) {
12184       RGWObjCategory category = main_category;
12185       map<uint8_t, struct rgw_bucket_category_stats>::iterator iter = (hiter->second.stats).find((uint8_t)category);
12186       if (iter != hiter->second.stats.end()) {
12187         struct rgw_bucket_category_stats& stats = iter->second;
12188         ent.count += stats.num_entries;
12189         ent.size += stats.total_size;
12190         ent.size_rounded += stats.total_size_rounded;
12191       }
12192     }
12193
12194     // fill in placement_rule from the bucket instance for use in swift's
12195     // per-storage policy statistics
12196     ent.placement_rule = std::move(bucket_info.placement_rule);
12197   }
12198
12199   return m.size();
12200 }
12201
12202 int RGWRados::append_async(rgw_raw_obj& obj, size_t size, bufferlist& bl)
12203 {
12204   rgw_rados_ref ref;
12205   int r = get_raw_obj_ref(obj, &ref);
12206   if (r < 0) {
12207     return r;
12208   }
12209   librados::Rados *rad = get_rados_handle();
12210   librados::AioCompletion *completion = rad->aio_create_completion(NULL, NULL, NULL);
12211
12212   r = ref.ioctx.aio_append(ref.oid, completion, bl, size);
12213   completion->release();
12214   return r;
12215 }
12216
12217 int RGWRados::distribute(const string& key, bufferlist& bl)
12218 {
12219   /*
12220    * we were called before watch was initialized. This can only happen if we're updating some system
12221    * config object (e.g., zone info) during init. Don't try to distribute the cache info for these
12222    * objects, they're currently only read on startup anyway.
12223    */
12224   if (!watch_initialized)
12225     return 0;
12226
12227   string notify_oid;
12228   pick_control_oid(key, notify_oid);
12229
12230   ldout(cct, 10) << "distributing notification oid=" << notify_oid << " bl.length()=" << bl.length() << dendl;
12231   return control_pool_ctx.notify2(notify_oid, bl, 0, NULL);
12232 }
12233
12234 int RGWRados::pool_iterate_begin(const rgw_pool& pool, RGWPoolIterCtx& ctx)
12235 {
12236   librados::IoCtx& io_ctx = ctx.io_ctx;
12237   librados::NObjectIterator& iter = ctx.iter;
12238
12239   int r = open_pool_ctx(pool, io_ctx);
12240   if (r < 0)
12241     return r;
12242
12243   iter = io_ctx.nobjects_begin();
12244
12245   return 0;
12246 }
12247
12248 int RGWRados::pool_iterate_begin(const rgw_pool& pool, const string& cursor, RGWPoolIterCtx& ctx)
12249 {
12250   librados::IoCtx& io_ctx = ctx.io_ctx;
12251   librados::NObjectIterator& iter = ctx.iter;
12252
12253   int r = open_pool_ctx(pool, io_ctx);
12254   if (r < 0)
12255     return r;
12256
12257   librados::ObjectCursor oc;
12258   if (!oc.from_str(cursor)) {
12259     ldout(cct, 10) << "failed to parse cursor: " << cursor << dendl;
12260     return -EINVAL;
12261   }
12262
12263   iter = io_ctx.nobjects_begin(oc);
12264
12265   return 0;
12266 }
12267
12268 string RGWRados::pool_iterate_get_cursor(RGWPoolIterCtx& ctx)
12269 {
12270   return ctx.iter.get_cursor().to_str();
12271 }
12272
12273 int RGWRados::pool_iterate(RGWPoolIterCtx& ctx, uint32_t num, vector<rgw_bucket_dir_entry>& objs,
12274                            bool *is_truncated, RGWAccessListFilter *filter)
12275 {
12276   librados::IoCtx& io_ctx = ctx.io_ctx;
12277   librados::NObjectIterator& iter = ctx.iter;
12278
12279   if (iter == io_ctx.nobjects_end())
12280     return -ENOENT;
12281
12282   uint32_t i;
12283
12284   for (i = 0; i < num && iter != io_ctx.nobjects_end(); ++i, ++iter) {
12285     rgw_bucket_dir_entry e;
12286
12287     string oid = iter->get_oid();
12288     ldout(cct, 20) << "RGWRados::pool_iterate: got " << oid << dendl;
12289
12290     // fill it in with initial values; we may correct later
12291     if (filter && !filter->filter(oid, oid))
12292       continue;
12293
12294     e.key = oid;
12295     objs.push_back(e);
12296   }
12297
12298   if (is_truncated)
12299     *is_truncated = (iter != io_ctx.nobjects_end());
12300
12301   return objs.size();
12302 }
12303 struct RGWAccessListFilterPrefix : public RGWAccessListFilter {
12304   string prefix;
12305
12306   explicit RGWAccessListFilterPrefix(const string& _prefix) : prefix(_prefix) {}
12307   bool filter(string& name, string& key) override {
12308     return (prefix.compare(key.substr(0, prefix.size())) == 0);
12309   }
12310 };
12311
12312 int RGWRados::list_raw_objects_init(const rgw_pool& pool, const string& marker, RGWListRawObjsCtx *ctx)
12313 {
12314   if (!ctx->initialized) {
12315     int r = pool_iterate_begin(pool, marker, ctx->iter_ctx);
12316     if (r < 0) {
12317       ldout(cct, 10) << "failed to list objects pool_iterate_begin() returned r=" << r << dendl;
12318       return r;
12319     }
12320     ctx->initialized = true;
12321   }
12322   return 0;
12323 }
12324
12325 int RGWRados::list_raw_objects_next(const string& prefix_filter, int max,
12326                                     RGWListRawObjsCtx& ctx, list<string>& oids,
12327                                     bool *is_truncated)
12328 {
12329   if (!ctx.initialized) {
12330     return -EINVAL;
12331   }
12332   RGWAccessListFilterPrefix filter(prefix_filter);
12333   vector<rgw_bucket_dir_entry> objs;
12334   int r = pool_iterate(ctx.iter_ctx, max, objs, is_truncated, &filter);
12335   if (r < 0) {
12336     if(r != -ENOENT)
12337       ldout(cct, 10) << "failed to list objects pool_iterate returned r=" << r << dendl;
12338     return r;
12339   }
12340
12341   vector<rgw_bucket_dir_entry>::iterator iter;
12342   for (iter = objs.begin(); iter != objs.end(); ++iter) {
12343     oids.push_back(iter->key.name);
12344   }
12345
12346   return oids.size();
12347 }
12348
12349 int RGWRados::list_raw_objects(const rgw_pool& pool, const string& prefix_filter,
12350                                int max, RGWListRawObjsCtx& ctx, list<string>& oids,
12351                                bool *is_truncated)
12352 {
12353   if (!ctx.initialized) {
12354     int r = list_raw_objects_init(pool, string(), &ctx);
12355     if (r < 0) {
12356       return r;
12357     }
12358   }
12359
12360   return list_raw_objects_next(prefix_filter, max, ctx, oids, is_truncated);
12361 }
12362
12363 string RGWRados::list_raw_objs_get_cursor(RGWListRawObjsCtx& ctx)
12364 {
12365   return pool_iterate_get_cursor(ctx.iter_ctx);
12366 }
12367
12368 int RGWRados::list_bi_log_entries(RGWBucketInfo& bucket_info, int shard_id, string& marker, uint32_t max,
12369                                   std::list<rgw_bi_log_entry>& result, bool *truncated)
12370 {
12371   ldout(cct, 20) << __func__ << ": " << bucket_info.bucket << " marker " << marker << " shard_id=" << shard_id << " max " << max << dendl;
12372   result.clear();
12373
12374   librados::IoCtx index_ctx;
12375   map<int, string> oids;
12376   map<int, cls_rgw_bi_log_list_ret> bi_log_lists;
12377   map<int, string> bucket_instance_ids;
12378   int r = open_bucket_index(bucket_info, index_ctx, oids, shard_id, &bucket_instance_ids);
12379   if (r < 0)
12380     return r;
12381
12382   BucketIndexShardsManager marker_mgr;
12383   bool has_shards = (oids.size() > 1 || shard_id >= 0);
12384   // If there are multiple shards for the bucket index object, the marker
12385   // should have the pattern '{shard_id_1}#{shard_marker_1},{shard_id_2}#
12386   // {shard_marker_2}...', if there is no sharding, the bi_log_list should
12387   // only contain one record, and the key is the bucket instance id.
12388   r = marker_mgr.from_string(marker, shard_id);
12389   if (r < 0)
12390     return r;
12391  
12392   r = CLSRGWIssueBILogList(index_ctx, marker_mgr, max, oids, bi_log_lists, cct->_conf->rgw_bucket_index_max_aio)();
12393   if (r < 0)
12394     return r;
12395
12396   map<int, list<rgw_bi_log_entry>::iterator> vcurrents;
12397   map<int, list<rgw_bi_log_entry>::iterator> vends;
12398   if (truncated) {
12399     *truncated = false;
12400   }
12401   map<int, cls_rgw_bi_log_list_ret>::iterator miter = bi_log_lists.begin();
12402   for (; miter != bi_log_lists.end(); ++miter) {
12403     int shard_id = miter->first;
12404     vcurrents[shard_id] = miter->second.entries.begin();
12405     vends[shard_id] = miter->second.entries.end();
12406     if (truncated) {
12407       *truncated = (*truncated || miter->second.truncated);
12408     }
12409   }
12410
12411   size_t total = 0;
12412   bool has_more = true;
12413   map<int, list<rgw_bi_log_entry>::iterator>::iterator viter;
12414   map<int, list<rgw_bi_log_entry>::iterator>::iterator eiter;
12415   while (total < max && has_more) {
12416     has_more = false;
12417
12418     viter = vcurrents.begin();
12419     eiter = vends.begin();
12420
12421     for (; total < max && viter != vcurrents.end(); ++viter, ++eiter) {
12422       assert (eiter != vends.end());
12423
12424       int shard_id = viter->first;
12425       list<rgw_bi_log_entry>::iterator& liter = viter->second;
12426
12427       if (liter == eiter->second){
12428         continue;
12429       }
12430       rgw_bi_log_entry& entry = *(liter);
12431       if (has_shards) {
12432         char buf[16];
12433         snprintf(buf, sizeof(buf), "%d", shard_id);
12434         string tmp_id;
12435         build_bucket_index_marker(buf, entry.id, &tmp_id);
12436         entry.id.swap(tmp_id);
12437       }
12438       marker_mgr.add(shard_id, entry.id);
12439       result.push_back(entry);
12440       total++;
12441       has_more = true;
12442       ++liter;
12443     }
12444   }
12445
12446   if (truncated) {
12447     for (viter = vcurrents.begin(), eiter = vends.begin(); viter != vcurrents.end(); ++viter, ++eiter) {
12448       assert (eiter != vends.end());
12449       *truncated = (*truncated || (viter->second != eiter->second));
12450     }
12451   }
12452
12453   // Refresh marker, if there are multiple shards, the output will look like
12454   // '{shard_oid_1}#{shard_marker_1},{shard_oid_2}#{shard_marker_2}...',
12455   // if there is no sharding, the simply marker (without oid) is returned
12456   if (has_shards) {
12457     marker_mgr.to_string(&marker);
12458   } else {
12459     if (!result.empty()) {
12460       marker = result.rbegin()->id;
12461     }
12462   }
12463
12464   return 0;
12465 }
12466
12467 int RGWRados::trim_bi_log_entries(RGWBucketInfo& bucket_info, int shard_id, string& start_marker, string& end_marker)
12468 {
12469   librados::IoCtx index_ctx;
12470   map<int, string> bucket_objs;
12471
12472   BucketIndexShardsManager start_marker_mgr;
12473   BucketIndexShardsManager end_marker_mgr;
12474
12475   int r = open_bucket_index(bucket_info, index_ctx, bucket_objs, shard_id);
12476   if (r < 0) {
12477     return r;
12478   }
12479
12480   r = start_marker_mgr.from_string(start_marker, shard_id);
12481   if (r < 0) {
12482     return r;
12483   }
12484
12485   r = end_marker_mgr.from_string(end_marker, shard_id);
12486   if (r < 0) {
12487     return r;
12488   }
12489
12490   return CLSRGWIssueBILogTrim(index_ctx, start_marker_mgr, end_marker_mgr, bucket_objs,
12491                               cct->_conf->rgw_bucket_index_max_aio)();
12492
12493   return r;
12494 }
12495
12496 int RGWRados::resync_bi_log_entries(RGWBucketInfo& bucket_info, int shard_id)
12497 {
12498   librados::IoCtx index_ctx;
12499   map<int, string> bucket_objs;
12500   int r = open_bucket_index(bucket_info, index_ctx, bucket_objs, shard_id);
12501   if (r < 0)
12502     return r;
12503
12504   return CLSRGWIssueResyncBucketBILog(index_ctx, bucket_objs, cct->_conf->rgw_bucket_index_max_aio)();
12505 }
12506
12507 int RGWRados::stop_bi_log_entries(RGWBucketInfo& bucket_info, int shard_id)
12508 {
12509   librados::IoCtx index_ctx;
12510   map<int, string> bucket_objs;
12511   int r = open_bucket_index(bucket_info, index_ctx, bucket_objs, shard_id);
12512   if (r < 0)
12513     return r;
12514
12515   return CLSRGWIssueBucketBILogStop(index_ctx, bucket_objs, cct->_conf->rgw_bucket_index_max_aio)();
12516 }
12517
12518 int RGWRados::bi_get_instance(const RGWBucketInfo& bucket_info, rgw_obj& obj, rgw_bucket_dir_entry *dirent)
12519 {
12520   rgw_rados_ref ref;
12521   int r = get_obj_head_ref(bucket_info, obj, &ref);
12522   if (r < 0) {
12523     return r;
12524   }
12525
12526   rgw_cls_bi_entry bi_entry;
12527   r = bi_get(obj.bucket, obj, InstanceIdx, &bi_entry);
12528   if (r < 0 && r != -ENOENT) {
12529     ldout(cct, 0) << "ERROR: bi_get() returned r=" << r << dendl;
12530   }
12531   if (r < 0) {
12532     return r;
12533   }
12534   bufferlist::iterator iter = bi_entry.data.begin();
12535   try {
12536     ::decode(*dirent, iter);
12537   } catch (buffer::error& err) {
12538     ldout(cct, 0) << "ERROR: failed to decode bi_entry()" << dendl;
12539     return -EIO;
12540   }
12541
12542   return 0;
12543 }
12544
12545 int RGWRados::bi_get(rgw_bucket& bucket, rgw_obj& obj, BIIndexType index_type, rgw_cls_bi_entry *entry)
12546 {
12547   BucketShard bs(this);
12548   int ret = bs.init(bucket, obj);
12549   if (ret < 0) {
12550     ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
12551     return ret;
12552   }
12553
12554   cls_rgw_obj_key key(obj.key.get_index_key_name(), obj.key.instance);
12555   
12556   ret = cls_rgw_bi_get(bs.index_ctx, bs.bucket_obj, index_type, key, entry);
12557   if (ret < 0)
12558     return ret;
12559
12560   return 0;
12561 }
12562
12563 void RGWRados::bi_put(ObjectWriteOperation& op, BucketShard& bs, rgw_cls_bi_entry& entry)
12564 {
12565   cls_rgw_bi_put(op, bs.bucket_obj, entry);
12566 }
12567
12568 int RGWRados::bi_put(BucketShard& bs, rgw_cls_bi_entry& entry)
12569 {
12570   int ret = cls_rgw_bi_put(bs.index_ctx, bs.bucket_obj, entry);
12571   if (ret < 0)
12572     return ret;
12573
12574   return 0;
12575 }
12576
12577 int RGWRados::bi_put(rgw_bucket& bucket, rgw_obj& obj, rgw_cls_bi_entry& entry)
12578 {
12579   BucketShard bs(this);
12580   int ret = bs.init(bucket, obj);
12581   if (ret < 0) {
12582     ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
12583     return ret;
12584   }
12585
12586   return bi_put(bs, entry);
12587 }
12588
12589 int RGWRados::bi_list(rgw_bucket& bucket, const string& obj_name, const string& marker, uint32_t max, list<rgw_cls_bi_entry> *entries, bool *is_truncated)
12590 {
12591   rgw_obj obj(bucket, obj_name);
12592   BucketShard bs(this);
12593   int ret = bs.init(bucket, obj);
12594   if (ret < 0) {
12595     ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
12596     return ret;
12597   }
12598
12599   ret = cls_rgw_bi_list(bs.index_ctx, bs.bucket_obj, obj_name, marker, max, entries, is_truncated);
12600   if (ret == -ENOENT) {
12601     *is_truncated = false;
12602   }
12603   if (ret < 0)
12604     return ret;
12605
12606   return 0;
12607 }
12608
12609 int RGWRados::bi_list(BucketShard& bs, const string& filter_obj, const string& marker, uint32_t max, list<rgw_cls_bi_entry> *entries, bool *is_truncated)
12610 {
12611   int ret = cls_rgw_bi_list(bs.index_ctx, bs.bucket_obj, filter_obj, marker, max, entries, is_truncated);
12612   if (ret < 0)
12613     return ret;
12614
12615   return 0;
12616 }
12617
12618 int RGWRados::bi_remove(BucketShard& bs)
12619 {
12620   int ret = bs.index_ctx.remove(bs.bucket_obj);
12621   if (ret == -ENOENT) {
12622     ret = 0;
12623   }
12624   if (ret < 0) {
12625     ldout(cct, 5) << "bs.index_ctx.remove(" << bs.bucket_obj << ") returned ret=" << ret << dendl;
12626     return ret;
12627   }
12628
12629   return 0;
12630 }
12631
12632 int RGWRados::bi_list(rgw_bucket& bucket, int shard_id, const string& filter_obj, const string& marker, uint32_t max, list<rgw_cls_bi_entry> *entries, bool *is_truncated)
12633 {
12634   BucketShard bs(this);
12635   int ret = bs.init(bucket, shard_id);
12636   if (ret < 0) {
12637     ldout(cct, 5) << "bs.init() returned ret=" << ret << dendl;
12638     return ret;
12639   }
12640
12641   return bi_list(bs, filter_obj, marker, max, entries, is_truncated);
12642 }
12643
12644 int RGWRados::gc_operate(string& oid, librados::ObjectWriteOperation *op)
12645 {
12646   return gc_pool_ctx.operate(oid, op);
12647 }
12648
12649 int RGWRados::gc_aio_operate(string& oid, librados::ObjectWriteOperation *op)
12650 {
12651   AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL);
12652   int r = gc_pool_ctx.aio_operate(oid, c, op);
12653   c->release();
12654   return r;
12655 }
12656
12657 int RGWRados::gc_operate(string& oid, librados::ObjectReadOperation *op, bufferlist *pbl)
12658 {
12659   return gc_pool_ctx.operate(oid, op, pbl);
12660 }
12661
12662 int RGWRados::list_gc_objs(int *index, string& marker, uint32_t max, bool expired_only, std::list<cls_rgw_gc_obj_info>& result, bool *truncated)
12663 {
12664   return gc->list(index, marker, max, expired_only, result, truncated);
12665 }
12666
12667 int RGWRados::process_gc()
12668 {
12669   return gc->process();
12670 }
12671
12672 int RGWRados::list_lc_progress(const string& marker, uint32_t max_entries, map<string, int> *progress_map)
12673 {
12674   return lc->list_lc_progress(marker, max_entries, progress_map);
12675 }
12676
12677 int RGWRados::process_lc()
12678 {
12679   return lc->process();
12680 }
12681
12682 int RGWRados::process_expire_objects()
12683 {
12684   obj_expirer->inspect_all_shards(utime_t(), ceph_clock_now());
12685   return 0;
12686 }
12687
12688 int RGWRados::cls_rgw_init_index(librados::IoCtx& index_ctx, librados::ObjectWriteOperation& op, string& oid)
12689 {
12690   bufferlist in;
12691   cls_rgw_bucket_init(op);
12692   return index_ctx.operate(oid, &op);
12693 }
12694
12695 int RGWRados::cls_obj_prepare_op(BucketShard& bs, RGWModifyOp op, string& tag,
12696                                  rgw_obj& obj, uint16_t bilog_flags, rgw_zone_set *_zones_trace)
12697 {
12698   rgw_zone_set zones_trace;
12699   if (_zones_trace) {
12700     zones_trace = *_zones_trace;
12701   }
12702   else {
12703     zones_trace.insert(get_zone().id);
12704   }
12705   
12706   ObjectWriteOperation o;
12707   cls_rgw_obj_key key(obj.key.get_index_key_name(), obj.key.instance);
12708   cls_rgw_guard_bucket_resharding(o, -ERR_BUSY_RESHARDING);
12709   cls_rgw_bucket_prepare_op(o, op, tag, key, obj.key.get_loc(), get_zone().log_data, bilog_flags, zones_trace);
12710   return bs.index_ctx.operate(bs.bucket_obj, &o);
12711 }
12712
12713 int RGWRados::cls_obj_complete_op(BucketShard& bs, const rgw_obj& obj, RGWModifyOp op, string& tag,
12714                                   int64_t pool, uint64_t epoch,
12715                                   rgw_bucket_dir_entry& ent, RGWObjCategory category,
12716                                   list<rgw_obj_index_key> *remove_objs, uint16_t bilog_flags, rgw_zone_set *_zones_trace)
12717 {
12718   ObjectWriteOperation o;
12719   rgw_bucket_dir_entry_meta dir_meta;
12720   dir_meta = ent.meta;
12721   dir_meta.category = category;
12722
12723   rgw_bucket_entry_ver ver;
12724   ver.pool = pool;
12725   ver.epoch = epoch;
12726   cls_rgw_obj_key key(ent.key.name, ent.key.instance);
12727   cls_rgw_guard_bucket_resharding(o, -ERR_BUSY_RESHARDING);
12728   cls_rgw_bucket_complete_op(o, op, tag, ver, key, dir_meta, remove_objs,
12729                              get_zone().log_data, bilog_flags, _zones_trace);
12730   complete_op_data *arg;
12731   index_completion_manager->create_completion(obj, op, tag, ver, key, dir_meta, remove_objs,
12732                                               get_zone().log_data, bilog_flags, _zones_trace, &arg);
12733   librados::AioCompletion *completion = arg->rados_completion;
12734   int ret = bs.index_ctx.aio_operate(bs.bucket_obj, arg->rados_completion, &o);
12735   completion->release(); /* can't reference arg here, as it might have already been released */
12736   return ret;
12737 }
12738
12739 int RGWRados::cls_obj_complete_add(BucketShard& bs, const rgw_obj& obj, string& tag,
12740                                    int64_t pool, uint64_t epoch,
12741                                    rgw_bucket_dir_entry& ent, RGWObjCategory category,
12742                                    list<rgw_obj_index_key> *remove_objs, uint16_t bilog_flags, rgw_zone_set *zones_trace)
12743 {
12744   return cls_obj_complete_op(bs, obj, CLS_RGW_OP_ADD, tag, pool, epoch, ent, category, remove_objs, bilog_flags, zones_trace);
12745 }
12746
12747 int RGWRados::cls_obj_complete_del(BucketShard& bs, string& tag,
12748                                    int64_t pool, uint64_t epoch,
12749                                    rgw_obj& obj,
12750                                    real_time& removed_mtime,
12751                                    list<rgw_obj_index_key> *remove_objs,
12752                                    uint16_t bilog_flags,
12753                                    rgw_zone_set *zones_trace)
12754 {
12755   rgw_bucket_dir_entry ent;
12756   ent.meta.mtime = removed_mtime;
12757   obj.key.get_index_key(&ent.key);
12758   return cls_obj_complete_op(bs, obj, CLS_RGW_OP_DEL, tag, pool, epoch, ent, RGW_OBJ_CATEGORY_NONE, remove_objs, bilog_flags, zones_trace);
12759 }
12760
12761 int RGWRados::cls_obj_complete_cancel(BucketShard& bs, string& tag, rgw_obj& obj, uint16_t bilog_flags, rgw_zone_set *zones_trace)
12762 {
12763   rgw_bucket_dir_entry ent;
12764   obj.key.get_index_key(&ent.key);
12765   return cls_obj_complete_op(bs, obj, CLS_RGW_OP_CANCEL, tag, -1 /* pool id */, 0, ent, RGW_OBJ_CATEGORY_NONE, NULL, bilog_flags, zones_trace);
12766 }
12767
12768 int RGWRados::cls_obj_set_bucket_tag_timeout(RGWBucketInfo& bucket_info, uint64_t timeout)
12769 {
12770   librados::IoCtx index_ctx;
12771   map<int, string> bucket_objs;
12772   int r = open_bucket_index(bucket_info, index_ctx, bucket_objs);
12773   if (r < 0)
12774     return r;
12775
12776   return CLSRGWIssueSetTagTimeout(index_ctx, bucket_objs, cct->_conf->rgw_bucket_index_max_aio, timeout)();
12777 }
12778
12779 int RGWRados::cls_bucket_list(RGWBucketInfo& bucket_info, int shard_id, rgw_obj_index_key& start, const string& prefix,
12780                               uint32_t num_entries, bool list_versions, map<string, rgw_bucket_dir_entry>& m,
12781                               bool *is_truncated, rgw_obj_index_key *last_entry,
12782                               bool (*force_check_filter)(const string&  name))
12783 {
12784   ldout(cct, 10) << "cls_bucket_list " << bucket_info.bucket << " start " << start.name << "[" << start.instance << "] num_entries " << num_entries << dendl;
12785
12786   librados::IoCtx index_ctx;
12787   // key   - oid (for different shards if there is any)
12788   // value - list result for the corresponding oid (shard), it is filled by the AIO callback
12789   map<int, string> oids;
12790   map<int, struct rgw_cls_list_ret> list_results;
12791   int r = open_bucket_index(bucket_info, index_ctx, oids, shard_id);
12792   if (r < 0)
12793     return r;
12794
12795   cls_rgw_obj_key start_key(start.name, start.instance);
12796   r = CLSRGWIssueBucketList(index_ctx, start_key, prefix, num_entries, list_versions,
12797                             oids, list_results, cct->_conf->rgw_bucket_index_max_aio)();
12798   if (r < 0)
12799     return r;
12800
12801   // Create a list of iterators that are used to iterate each shard
12802   vector<map<string, struct rgw_bucket_dir_entry>::iterator> vcurrents(list_results.size());
12803   vector<map<string, struct rgw_bucket_dir_entry>::iterator> vends(list_results.size());
12804   vector<string> vnames(list_results.size());
12805   map<int, struct rgw_cls_list_ret>::iterator iter = list_results.begin();
12806   *is_truncated = false;
12807   for (; iter != list_results.end(); ++iter) {
12808     vcurrents.push_back(iter->second.dir.m.begin());
12809     vends.push_back(iter->second.dir.m.end());
12810     vnames.push_back(oids[iter->first]);
12811     *is_truncated = (*is_truncated || iter->second.is_truncated);
12812   }
12813
12814   // Create a map to track the next candidate entry from each shard, if the entry
12815   // from a specified shard is selected/erased, the next entry from that shard will
12816   // be inserted for next round selection
12817   map<string, size_t> candidates;
12818   for (size_t i = 0; i < vcurrents.size(); ++i) {
12819     if (vcurrents[i] != vends[i]) {
12820       candidates[vcurrents[i]->first] = i;
12821     }
12822   }
12823
12824   map<string, bufferlist> updates;
12825   uint32_t count = 0;
12826   while (count < num_entries && !candidates.empty()) {
12827     r = 0;
12828     // Select the next one
12829     int pos = candidates.begin()->second;
12830     const string& name = vcurrents[pos]->first;
12831     struct rgw_bucket_dir_entry& dirent = vcurrents[pos]->second;
12832
12833     bool force_check = force_check_filter &&
12834         force_check_filter(dirent.key.name);
12835     if ((!dirent.exists && !dirent.is_delete_marker()) ||
12836         !dirent.pending_map.empty() ||
12837         force_check) {
12838       /* there are uncommitted ops. We need to check the current state,
12839        * and if the tags are old we need to do cleanup as well. */
12840       librados::IoCtx sub_ctx;
12841       sub_ctx.dup(index_ctx);
12842       r = check_disk_state(sub_ctx, bucket_info, dirent, dirent, updates[vnames[pos]]);
12843       if (r < 0 && r != -ENOENT) {
12844           return r;
12845       }
12846     }
12847     if (r >= 0) {
12848       ldout(cct, 10) << "RGWRados::cls_bucket_list: got " << dirent.key.name << "[" << dirent.key.instance << "]" << dendl;
12849       m[name] = std::move(dirent);
12850       ++count;
12851     }
12852
12853     // Refresh the candidates map
12854     candidates.erase(candidates.begin());
12855     ++vcurrents[pos];
12856     if (vcurrents[pos] != vends[pos]) {
12857       candidates[vcurrents[pos]->first] = pos;
12858     }
12859   }
12860
12861   // Suggest updates if there is any
12862   map<string, bufferlist>::iterator miter = updates.begin();
12863   for (; miter != updates.end(); ++miter) {
12864     if (miter->second.length()) {
12865       ObjectWriteOperation o;
12866       cls_rgw_suggest_changes(o, miter->second);
12867       // we don't care if we lose suggested updates, send them off blindly
12868       AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL);
12869       index_ctx.aio_operate(miter->first, c, &o);
12870         c->release();
12871     }
12872   }
12873
12874   // Check if all the returned entries are consumed or not
12875   for (size_t i = 0; i < vcurrents.size(); ++i) {
12876     if (vcurrents[i] != vends[i])
12877       *is_truncated = true;
12878   }
12879   if (!m.empty())
12880     *last_entry = m.rbegin()->first;
12881
12882   return 0;
12883 }
12884
12885 int RGWRados::cls_obj_usage_log_add(const string& oid, rgw_usage_log_info& info)
12886 {
12887   rgw_raw_obj obj(get_zone_params().usage_log_pool, oid);
12888
12889   rgw_rados_ref ref;
12890   int r = get_raw_obj_ref(obj, &ref);
12891   if (r < 0) {
12892     return r;
12893   }
12894
12895   ObjectWriteOperation op;
12896   cls_rgw_usage_log_add(op, info);
12897
12898   r = ref.ioctx.operate(ref.oid, &op);
12899   return r;
12900 }
12901
12902 int RGWRados::cls_obj_usage_log_read(string& oid, string& user, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries,
12903                                      string& read_iter, map<rgw_user_bucket, rgw_usage_log_entry>& usage, bool *is_truncated)
12904 {
12905   rgw_raw_obj obj(get_zone_params().usage_log_pool, oid);
12906
12907   rgw_rados_ref ref;
12908   int r = get_raw_obj_ref(obj, &ref);
12909   if (r < 0) {
12910     return r;
12911   }
12912
12913   *is_truncated = false;
12914
12915   r = cls_rgw_usage_log_read(ref.ioctx, ref.oid, user, start_epoch, end_epoch,
12916                              max_entries, read_iter, usage, is_truncated);
12917
12918   return r;
12919 }
12920
12921 int RGWRados::cls_obj_usage_log_trim(string& oid, string& user, uint64_t start_epoch, uint64_t end_epoch)
12922 {
12923   rgw_raw_obj obj(get_zone_params().usage_log_pool, oid);
12924
12925   rgw_rados_ref ref;
12926   int r = get_raw_obj_ref(obj, &ref);
12927   if (r < 0) {
12928     return r;
12929   }
12930
12931   ObjectWriteOperation op;
12932   cls_rgw_usage_log_trim(op, user, start_epoch, end_epoch);
12933
12934   r = ref.ioctx.operate(ref.oid, &op);
12935   return r;
12936 }
12937
12938 int RGWRados::remove_objs_from_index(RGWBucketInfo& bucket_info, list<rgw_obj_index_key>& oid_list)
12939 {
12940   librados::IoCtx index_ctx;
12941   string dir_oid;
12942
12943   uint8_t suggest_flag = (get_zone().log_data ? CEPH_RGW_DIR_SUGGEST_LOG_OP : 0);
12944
12945   int r = open_bucket_index(bucket_info, index_ctx, dir_oid);
12946   if (r < 0)
12947     return r;
12948
12949   bufferlist updates;
12950
12951   for (auto iter = oid_list.begin(); iter != oid_list.end(); ++iter) {
12952     rgw_bucket_dir_entry entry;
12953     entry.key = *iter;
12954     dout(2) << "RGWRados::remove_objs_from_index bucket=" << bucket_info.bucket << " obj=" << entry.key.name << ":" << entry.key.instance << dendl;
12955     entry.ver.epoch = (uint64_t)-1; // ULLONG_MAX, needed to that objclass doesn't skip out request
12956     updates.append(CEPH_RGW_REMOVE | suggest_flag);
12957     ::encode(entry, updates);
12958   }
12959
12960   bufferlist out;
12961
12962   r = index_ctx.exec(dir_oid, RGW_CLASS, RGW_DIR_SUGGEST_CHANGES, updates, out);
12963
12964   return r;
12965 }
12966
12967 int RGWRados::check_disk_state(librados::IoCtx io_ctx,
12968                                const RGWBucketInfo& bucket_info,
12969                                rgw_bucket_dir_entry& list_state,
12970                                rgw_bucket_dir_entry& object,
12971                                bufferlist& suggested_updates)
12972 {
12973   const rgw_bucket& bucket = bucket_info.bucket;
12974   uint8_t suggest_flag = (get_zone().log_data ? CEPH_RGW_DIR_SUGGEST_LOG_OP : 0);
12975
12976   std::string loc;
12977
12978   rgw_obj obj(bucket, list_state.key);
12979
12980   string oid;
12981   get_obj_bucket_and_oid_loc(obj, oid, loc);
12982
12983   if (loc != list_state.locator) {
12984     ldout(cct, 0) << "WARNING: generated locator (" << loc << ") is different from listed locator (" << list_state.locator << ")" << dendl;
12985   }
12986
12987   io_ctx.locator_set_key(list_state.locator);
12988
12989   RGWObjState *astate = NULL;
12990   RGWObjectCtx rctx(this);
12991   int r = get_obj_state(&rctx, bucket_info, obj, &astate, false);
12992   if (r < 0)
12993     return r;
12994
12995   list_state.pending_map.clear(); // we don't need this and it inflates size
12996   if (!astate->exists) {
12997       /* object doesn't exist right now -- hopefully because it's
12998        * marked as !exists and got deleted */
12999     if (list_state.exists) {
13000       /* FIXME: what should happen now? Work out if there are any
13001        * non-bad ways this could happen (there probably are, but annoying
13002        * to handle!) */
13003     }
13004     // encode a suggested removal of that key
13005     list_state.ver.epoch = io_ctx.get_last_version();
13006     list_state.ver.pool = io_ctx.get_id();
13007     cls_rgw_encode_suggestion(CEPH_RGW_REMOVE, list_state, suggested_updates);
13008     return -ENOENT;
13009   }
13010
13011   string etag;
13012   string content_type;
13013   ACLOwner owner;
13014
13015   object.meta.size = astate->size;
13016   object.meta.accounted_size = astate->accounted_size;
13017   object.meta.mtime = astate->mtime;
13018
13019   map<string, bufferlist>::iterator iter = astate->attrset.find(RGW_ATTR_ETAG);
13020   if (iter != astate->attrset.end()) {
13021     etag = iter->second.c_str();
13022   }
13023   iter = astate->attrset.find(RGW_ATTR_CONTENT_TYPE);
13024   if (iter != astate->attrset.end()) {
13025     content_type = iter->second.c_str();
13026   }
13027   iter = astate->attrset.find(RGW_ATTR_ACL);
13028   if (iter != astate->attrset.end()) {
13029     r = decode_policy(iter->second, &owner);
13030     if (r < 0) {
13031       dout(0) << "WARNING: could not decode policy for object: " << obj << dendl;
13032     }
13033   }
13034
13035   if (astate->has_manifest) {
13036     RGWObjManifest::obj_iterator miter;
13037     RGWObjManifest& manifest = astate->manifest;
13038     for (miter = manifest.obj_begin(); miter != manifest.obj_end(); ++miter) {
13039       const rgw_raw_obj& raw_loc = miter.get_location().get_raw_obj(this);
13040       rgw_obj loc;
13041       rgw_raw_obj_to_obj(manifest.get_obj().bucket, raw_loc, &loc);
13042
13043       if (loc.key.ns == RGW_OBJ_NS_MULTIPART) {
13044         dout(10) << "check_disk_state(): removing manifest part from index: " << loc << dendl;
13045         r = delete_obj_index(loc);
13046         if (r < 0) {
13047           dout(0) << "WARNING: delete_obj_index() returned r=" << r << dendl;
13048         }
13049       }
13050     }
13051   }
13052
13053   object.meta.etag = etag;
13054   object.meta.content_type = content_type;
13055   object.meta.owner = owner.get_id().to_str();
13056   object.meta.owner_display_name = owner.get_display_name();
13057
13058   // encode suggested updates
13059   list_state.ver.pool = io_ctx.get_id();
13060   list_state.ver.epoch = astate->epoch;
13061   list_state.meta.size = object.meta.size;
13062   list_state.meta.accounted_size = object.meta.accounted_size;
13063   list_state.meta.mtime = object.meta.mtime;
13064   list_state.meta.category = main_category;
13065   list_state.meta.etag = etag;
13066   list_state.meta.content_type = content_type;
13067   if (astate->obj_tag.length() > 0)
13068     list_state.tag = astate->obj_tag.c_str();
13069   list_state.meta.owner = owner.get_id().to_str();
13070   list_state.meta.owner_display_name = owner.get_display_name();
13071
13072   list_state.exists = true;
13073   cls_rgw_encode_suggestion(CEPH_RGW_UPDATE | suggest_flag, list_state, suggested_updates);
13074   return 0;
13075 }
13076
13077 int RGWRados::cls_bucket_head(const RGWBucketInfo& bucket_info, int shard_id, map<string, struct rgw_bucket_dir_header>& headers, map<int, string> *bucket_instance_ids)
13078 {
13079   librados::IoCtx index_ctx;
13080   map<int, string> oids;
13081   map<int, struct rgw_cls_list_ret> list_results;
13082   int r = open_bucket_index(bucket_info, index_ctx, oids, list_results, shard_id, bucket_instance_ids);
13083   if (r < 0)
13084     return r;
13085
13086   r = CLSRGWIssueGetDirHeader(index_ctx, oids, list_results, cct->_conf->rgw_bucket_index_max_aio)();
13087   if (r < 0)
13088     return r;
13089
13090   map<int, struct rgw_cls_list_ret>::iterator iter = list_results.begin();
13091   for(; iter != list_results.end(); ++iter) {
13092     headers[oids[iter->first]] = iter->second.dir.header;
13093   }
13094   return 0;
13095 }
13096
13097 int RGWRados::cls_bucket_head_async(const RGWBucketInfo& bucket_info, int shard_id, RGWGetDirHeader_CB *ctx, int *num_aio)
13098 {
13099   librados::IoCtx index_ctx;
13100   map<int, string> bucket_objs;
13101   int r = open_bucket_index(bucket_info, index_ctx, bucket_objs, shard_id);
13102   if (r < 0)
13103     return r;
13104
13105   map<int, string>::iterator iter = bucket_objs.begin();
13106   for (; iter != bucket_objs.end(); ++iter) {
13107     r = cls_rgw_get_dir_header_async(index_ctx, iter->second, static_cast<RGWGetDirHeader_CB*>(ctx->get()));
13108     if (r < 0) {
13109       ctx->put();
13110       break;
13111     } else {
13112       (*num_aio)++;
13113     }
13114   }
13115   return r;
13116 }
13117
13118 int RGWRados::cls_user_get_header(const string& user_id, cls_user_header *header)
13119 {
13120   string buckets_obj_id;
13121   rgw_get_buckets_obj(user_id, buckets_obj_id);
13122   rgw_raw_obj obj(get_zone_params().user_uid_pool, buckets_obj_id);
13123
13124   rgw_rados_ref ref;
13125   int r = get_raw_obj_ref(obj, &ref);
13126   if (r < 0) {
13127     return r;
13128   }
13129
13130   librados::ObjectReadOperation op;
13131   int rc;
13132   ::cls_user_get_header(op, header, &rc);
13133   bufferlist ibl;
13134   r = ref.ioctx.operate(ref.oid, &op, &ibl);
13135   if (r < 0)
13136     return r;
13137   if (rc < 0)
13138     return rc;
13139
13140   return 0;
13141 }
13142
13143 int RGWRados::cls_user_get_header_async(const string& user_id, RGWGetUserHeader_CB *ctx)
13144 {
13145   string buckets_obj_id;
13146   rgw_get_buckets_obj(user_id, buckets_obj_id);
13147   rgw_raw_obj obj(get_zone_params().user_uid_pool, buckets_obj_id);
13148
13149   rgw_rados_ref ref;
13150   int r = get_raw_obj_ref(obj, &ref);
13151   if (r < 0) {
13152     return r;
13153   }
13154
13155   r = ::cls_user_get_header_async(ref.ioctx, ref.oid, ctx);
13156   if (r < 0)
13157     return r;
13158
13159   return 0;
13160 }
13161
13162 int RGWRados::cls_user_sync_bucket_stats(rgw_raw_obj& user_obj, const RGWBucketInfo& bucket_info)
13163 {
13164   map<string, struct rgw_bucket_dir_header> headers;
13165   int r = cls_bucket_head(bucket_info, RGW_NO_SHARD, headers);
13166   if (r < 0) {
13167     ldout(cct, 20) << "cls_bucket_header() returned " << r << dendl;
13168     return r;
13169   }
13170
13171   cls_user_bucket_entry entry;
13172
13173   bucket_info.bucket.convert(&entry.bucket);
13174
13175   for (const auto& hiter : headers) {
13176     for (const auto& iter : hiter.second.stats) {
13177       const struct rgw_bucket_category_stats& header_stats = iter.second;
13178       entry.size += header_stats.total_size;
13179       entry.size_rounded += header_stats.total_size_rounded;
13180       entry.count += header_stats.num_entries;
13181     }
13182   }
13183
13184   list<cls_user_bucket_entry> entries;
13185   entries.push_back(entry);
13186
13187   r = cls_user_update_buckets(user_obj, entries, false);
13188   if (r < 0) {
13189     ldout(cct, 20) << "cls_user_update_buckets() returned " << r << dendl;
13190     return r;
13191   }
13192
13193   return 0;
13194 }
13195
13196 int RGWRados::cls_user_get_bucket_stats(const rgw_bucket& bucket, cls_user_bucket_entry& entry)
13197 {
13198   map<string, struct rgw_bucket_dir_header> headers;
13199   RGWBucketInfo bucket_info;
13200   RGWObjectCtx obj_ctx(this);
13201   int ret = get_bucket_instance_info(obj_ctx, bucket, bucket_info, NULL, NULL);
13202   if (ret < 0) {
13203     return ret;
13204   }
13205
13206   ret = cls_bucket_head(bucket_info, RGW_NO_SHARD, headers);
13207   if (ret < 0) {
13208     ldout(cct, 20) << "cls_bucket_header() returned " << ret << dendl;
13209     return ret;
13210   }
13211
13212   bucket.convert(&entry.bucket);
13213
13214   for (const auto& hiter : headers) {
13215     for (const auto& iter : hiter.second.stats) {
13216       const struct rgw_bucket_category_stats& header_stats = iter.second;
13217       entry.size += header_stats.total_size;
13218       entry.size_rounded += header_stats.total_size_rounded;
13219       entry.count += header_stats.num_entries;
13220     }
13221   }
13222
13223   return 0;
13224 }
13225
13226 int RGWRados::cls_user_list_buckets(rgw_raw_obj& obj,
13227                                     const string& in_marker,
13228                                     const string& end_marker,
13229                                     const int max_entries,
13230                                     list<cls_user_bucket_entry>& entries,
13231                                     string * const out_marker,
13232                                     bool * const truncated)
13233 {
13234   rgw_rados_ref ref;
13235   int r = get_raw_obj_ref(obj, &ref);
13236   if (r < 0) {
13237     return r;
13238   }
13239
13240   librados::ObjectReadOperation op;
13241   int rc;
13242
13243   cls_user_bucket_list(op, in_marker, end_marker, max_entries, entries, out_marker, truncated, &rc);
13244   bufferlist ibl;
13245   r = ref.ioctx.operate(ref.oid, &op, &ibl);
13246   if (r < 0)
13247     return r;
13248   if (rc < 0)
13249     return rc;
13250
13251   return 0;
13252 }
13253
13254 int RGWRados::cls_user_update_buckets(rgw_raw_obj& obj, list<cls_user_bucket_entry>& entries, bool add)
13255 {
13256   rgw_rados_ref ref;
13257   int r = get_raw_obj_ref(obj, &ref);
13258   if (r < 0) {
13259     return r;
13260   }
13261
13262   librados::ObjectWriteOperation op;
13263   cls_user_set_buckets(op, entries, add);
13264   r = ref.ioctx.operate(ref.oid, &op);
13265   if (r < 0)
13266     return r;
13267
13268   return 0;
13269 }
13270
13271 int RGWRados::complete_sync_user_stats(const rgw_user& user_id)
13272 {
13273   string buckets_obj_id;
13274   rgw_get_buckets_obj(user_id, buckets_obj_id);
13275   rgw_raw_obj obj(get_zone_params().user_uid_pool, buckets_obj_id);
13276   return cls_user_complete_stats_sync(obj);
13277 }
13278
13279 int RGWRados::cls_user_complete_stats_sync(rgw_raw_obj& obj)
13280 {
13281   rgw_rados_ref ref;
13282   int r = get_raw_obj_ref(obj, &ref);
13283   if (r < 0) {
13284     return r;
13285   }
13286
13287   librados::ObjectWriteOperation op;
13288   ::cls_user_complete_stats_sync(op);
13289   r = ref.ioctx.operate(ref.oid, &op);
13290   if (r < 0)
13291     return r;
13292
13293   return 0;
13294 }
13295
13296 int RGWRados::cls_user_add_bucket(rgw_raw_obj& obj, const cls_user_bucket_entry& entry)
13297 {
13298   list<cls_user_bucket_entry> l;
13299   l.push_back(entry);
13300
13301   return cls_user_update_buckets(obj, l, true);
13302 }
13303
13304 int RGWRados::cls_user_remove_bucket(rgw_raw_obj& obj, const cls_user_bucket& bucket)
13305 {
13306   rgw_rados_ref ref;
13307   int r = get_system_obj_ref(obj, &ref);
13308   if (r < 0) {
13309     return r;
13310   }
13311
13312   librados::ObjectWriteOperation op;
13313   ::cls_user_remove_bucket(op, bucket);
13314   r = ref.ioctx.operate(ref.oid, &op);
13315   if (r < 0)
13316     return r;
13317
13318   return 0;
13319 }
13320
13321 int RGWRados::check_bucket_shards(const RGWBucketInfo& bucket_info, const rgw_bucket& bucket,
13322                                   RGWQuotaInfo& bucket_quota)
13323 {
13324   if (!cct->_conf->rgw_dynamic_resharding) {
13325       return 0;
13326   }
13327
13328   bool need_resharding = false;
13329   int num_source_shards = (bucket_info.num_shards > 0 ? bucket_info.num_shards : 1);
13330   uint32_t suggested_num_shards;
13331
13332   int ret =  quota_handler->check_bucket_shards((uint64_t)cct->_conf->rgw_max_objs_per_shard,
13333                                                 num_source_shards,  bucket_info.owner, bucket, bucket_quota,
13334                                                 1, need_resharding, &suggested_num_shards);
13335   if (ret < 0) {
13336     return ret;
13337   }
13338
13339   if (need_resharding) {
13340     ldout(cct, 20) << __func__ << " bucket " << bucket.name << " need resharding " <<
13341       " old num shards " << bucket_info.num_shards << " new num shards " << suggested_num_shards <<
13342       dendl;
13343     return add_bucket_to_reshard(bucket_info, suggested_num_shards);
13344   }
13345
13346   return ret;
13347 }
13348
13349 int RGWRados::add_bucket_to_reshard(const RGWBucketInfo& bucket_info, uint32_t new_num_shards)
13350 {
13351   RGWReshard reshard(this);
13352
13353   uint32_t num_source_shards = (bucket_info.num_shards > 0 ? bucket_info.num_shards : 1);
13354
13355   new_num_shards = min(new_num_shards, get_max_bucket_shards());
13356   if (new_num_shards <= num_source_shards) {
13357     ldout(cct, 20) << "not resharding bucket name=" << bucket_info.bucket.name << ", orig_num=" << num_source_shards << ", new_num_shards=" << new_num_shards << dendl;
13358     return 0;
13359   }
13360
13361   cls_rgw_reshard_entry entry;
13362   entry.time = real_clock::now();
13363   entry.tenant = bucket_info.owner.tenant;
13364   entry.bucket_name = bucket_info.bucket.name;
13365   entry.bucket_id = bucket_info.bucket.bucket_id;
13366   entry.old_num_shards = num_source_shards;
13367   entry.new_num_shards = new_num_shards;
13368
13369   return reshard.add(entry);
13370 }
13371
13372 int RGWRados::check_quota(const rgw_user& bucket_owner, rgw_bucket& bucket,
13373                           RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota, uint64_t obj_size)
13374 {
13375   return quota_handler->check_quota(bucket_owner, bucket, user_quota, bucket_quota, 1, obj_size);
13376 }
13377
13378 void RGWRados::get_bucket_index_objects(const string& bucket_oid_base,
13379     uint32_t num_shards, map<int, string>& bucket_objects, int shard_id)
13380 {
13381   if (!num_shards) {
13382     bucket_objects[0] = bucket_oid_base;
13383   } else {
13384     char buf[bucket_oid_base.size() + 32];
13385     if (shard_id < 0) {
13386       for (uint32_t i = 0; i < num_shards; ++i) {
13387         snprintf(buf, sizeof(buf), "%s.%d", bucket_oid_base.c_str(), i);
13388         bucket_objects[i] = buf;
13389       }
13390     } else {
13391       if ((uint32_t)shard_id > num_shards) {
13392         return;
13393       }
13394       snprintf(buf, sizeof(buf), "%s.%d", bucket_oid_base.c_str(), shard_id);
13395       bucket_objects[shard_id] = buf;
13396     }
13397   }
13398 }
13399
13400 void RGWRados::get_bucket_instance_ids(const RGWBucketInfo& bucket_info, int shard_id, map<int, string> *result)
13401 {
13402   const rgw_bucket& bucket = bucket_info.bucket;
13403   string plain_id = bucket.name + ":" + bucket.bucket_id;
13404   if (!bucket_info.num_shards) {
13405     (*result)[0] = plain_id;
13406   } else {
13407     char buf[16];
13408     if (shard_id < 0) {
13409       for (uint32_t i = 0; i < bucket_info.num_shards; ++i) {
13410         snprintf(buf, sizeof(buf), ":%d", i);
13411         (*result)[i] = plain_id + buf;
13412       }
13413     } else {
13414       if ((uint32_t)shard_id > bucket_info.num_shards) {
13415         return;
13416       }
13417       snprintf(buf, sizeof(buf), ":%d", shard_id);
13418       (*result)[shard_id] = plain_id + buf;
13419     }
13420   }
13421 }
13422
13423 int RGWRados::get_target_shard_id(const RGWBucketInfo& bucket_info, const string& obj_key,
13424                                   int *shard_id)
13425 {
13426   int r = 0;
13427   switch (bucket_info.bucket_index_shard_hash_type) {
13428     case RGWBucketInfo::MOD:
13429       if (!bucket_info.num_shards) {
13430         if (shard_id) {
13431           *shard_id = -1;
13432         }
13433       } else {
13434         uint32_t sid = ceph_str_hash_linux(obj_key.c_str(), obj_key.size());
13435         uint32_t sid2 = sid ^ ((sid & 0xFF) << 24);
13436         sid = rgw_shards_mod(sid2, bucket_info.num_shards);
13437         if (shard_id) {
13438           *shard_id = (int)sid;
13439         }
13440       }
13441       break;
13442     default:
13443       r = -ENOTSUP;
13444   }
13445   return r;
13446 }
13447
13448 void RGWRados::get_bucket_index_object(const string& bucket_oid_base, uint32_t num_shards,
13449                                       int shard_id, string *bucket_obj)
13450 {
13451   if (!num_shards) {
13452     // By default with no sharding, we use the bucket oid as itself
13453     (*bucket_obj) = bucket_oid_base;
13454   } else {
13455     char buf[bucket_oid_base.size() + 32];
13456     snprintf(buf, sizeof(buf), "%s.%d", bucket_oid_base.c_str(), shard_id);
13457     (*bucket_obj) = buf;
13458   }
13459 }
13460
13461 int RGWRados::get_bucket_index_object(const string& bucket_oid_base, const string& obj_key,
13462     uint32_t num_shards, RGWBucketInfo::BIShardsHashType hash_type, string *bucket_obj, int *shard_id)
13463 {
13464   int r = 0;
13465   switch (hash_type) {
13466     case RGWBucketInfo::MOD:
13467       if (!num_shards) {
13468         // By default with no sharding, we use the bucket oid as itself
13469         (*bucket_obj) = bucket_oid_base;
13470         if (shard_id) {
13471           *shard_id = -1;
13472         }
13473       } else {
13474         uint32_t sid = ceph_str_hash_linux(obj_key.c_str(), obj_key.size());
13475         uint32_t sid2 = sid ^ ((sid & 0xFF) << 24);
13476         sid = rgw_shards_mod(sid2, num_shards);
13477         char buf[bucket_oid_base.size() + 32];
13478         snprintf(buf, sizeof(buf), "%s.%d", bucket_oid_base.c_str(), sid);
13479         (*bucket_obj) = buf;
13480         if (shard_id) {
13481           *shard_id = (int)sid;
13482         }
13483       }
13484       break;
13485     default:
13486       r = -ENOTSUP;
13487   }
13488   return r;
13489 }
13490
13491 void RGWStateLog::oid_str(int shard, string& oid) {
13492   oid = RGW_STATELOG_OBJ_PREFIX + module_name + ".";
13493   char buf[16];
13494   snprintf(buf, sizeof(buf), "%d", shard);
13495   oid += buf;
13496 }
13497
13498 int RGWStateLog::get_shard_num(const string& object) {
13499   uint32_t val = ceph_str_hash_linux(object.c_str(), object.length());
13500   return val % num_shards;
13501 }
13502
13503 string RGWStateLog::get_oid(const string& object) {
13504   int shard = get_shard_num(object);
13505   string oid;
13506   oid_str(shard, oid);
13507   return oid;
13508 }
13509
13510 int RGWStateLog::open_ioctx(librados::IoCtx& ioctx) {
13511   rgw_pool pool;
13512   store->get_log_pool(pool);
13513   int r = rgw_init_ioctx(store->get_rados_handle(), pool, ioctx);
13514   if (r < 0) {
13515     lderr(store->ctx()) << "ERROR: could not open rados pool" << dendl;
13516     return r;
13517   }
13518   return 0;
13519 }
13520
13521 int RGWStateLog::store_entry(const string& client_id, const string& op_id, const string& object,
13522                   uint32_t state, bufferlist *bl, uint32_t *check_state)
13523 {
13524   if (client_id.empty() ||
13525       op_id.empty() ||
13526       object.empty()) {
13527     ldout(store->ctx(), 0) << "client_id / op_id / object is empty" << dendl;
13528   }
13529
13530   librados::IoCtx ioctx;
13531   int r = open_ioctx(ioctx);
13532   if (r < 0)
13533     return r;
13534
13535   string oid = get_oid(object);
13536
13537   librados::ObjectWriteOperation op;
13538   if (check_state) {
13539     cls_statelog_check_state(op, client_id, op_id, object, *check_state);
13540   }
13541   utime_t ts = ceph_clock_now();
13542   bufferlist nobl;
13543   cls_statelog_add(op, client_id, op_id, object, ts, state, (bl ? *bl : nobl));
13544   r = ioctx.operate(oid, &op);
13545   if (r < 0) {
13546     return r;
13547   }
13548
13549   return 0;
13550 }
13551
13552 int RGWStateLog::remove_entry(const string& client_id, const string& op_id, const string& object)
13553 {
13554   if (client_id.empty() ||
13555       op_id.empty() ||
13556       object.empty()) {
13557     ldout(store->ctx(), 0) << "client_id / op_id / object is empty" << dendl;
13558   }
13559
13560   librados::IoCtx ioctx;
13561   int r = open_ioctx(ioctx);
13562   if (r < 0)
13563     return r;
13564
13565   string oid = get_oid(object);
13566
13567   librados::ObjectWriteOperation op;
13568   cls_statelog_remove_by_object(op, object, op_id);
13569   r = ioctx.operate(oid, &op);
13570   if (r < 0) {
13571     return r;
13572   }
13573
13574   return 0;
13575 }
13576
13577 void RGWStateLog::init_list_entries(const string& client_id, const string& op_id, const string& object,
13578                                     void **handle)
13579 {
13580   list_state *state = new list_state;
13581   state->client_id = client_id;
13582   state->op_id = op_id;
13583   state->object = object;
13584   if (object.empty()) {
13585     state->cur_shard = 0;
13586     state->max_shard = num_shards - 1;
13587   } else {
13588     state->cur_shard = state->max_shard = get_shard_num(object);
13589   }
13590   *handle = (void *)state;
13591 }
13592
13593 int RGWStateLog::list_entries(void *handle, int max_entries,
13594                               list<cls_statelog_entry>& entries,
13595                               bool *done)
13596 {
13597   list_state *state = static_cast<list_state *>(handle);
13598
13599   librados::IoCtx ioctx;
13600   int r = open_ioctx(ioctx);
13601   if (r < 0)
13602     return r;
13603
13604   entries.clear();
13605
13606   for (; state->cur_shard <= state->max_shard && max_entries > 0; ++state->cur_shard) {
13607     string oid;
13608     oid_str(state->cur_shard, oid);
13609
13610     librados::ObjectReadOperation op;
13611     list<cls_statelog_entry> ents;
13612     bool truncated;
13613     cls_statelog_list(op, state->client_id, state->op_id, state->object, state->marker,
13614                       max_entries, ents, &state->marker, &truncated);
13615     bufferlist ibl;
13616     r = ioctx.operate(oid, &op, &ibl);
13617     if (r == -ENOENT) {
13618       truncated = false;
13619       r = 0;
13620     }
13621     if (r < 0) {
13622       ldout(store->ctx(), 0) << "cls_statelog_list returned " << r << dendl;
13623       return r;
13624     }
13625
13626     if (!truncated) {
13627       state->marker.clear();
13628     }
13629
13630     max_entries -= ents.size();
13631
13632     entries.splice(entries.end(), ents);
13633
13634     if (truncated)
13635       break;
13636   }
13637
13638   *done = (state->cur_shard > state->max_shard);
13639
13640   return 0;
13641 }
13642
13643 void RGWStateLog::finish_list_entries(void *handle)
13644 {
13645   list_state *state = static_cast<list_state *>(handle);
13646   delete state;
13647 }
13648
13649 void RGWStateLog::dump_entry(const cls_statelog_entry& entry, Formatter *f)
13650 {
13651   f->open_object_section("statelog_entry");
13652   f->dump_string("client_id", entry.client_id);
13653   f->dump_string("op_id", entry.op_id);
13654   f->dump_string("object", entry.object);
13655   entry.timestamp.gmtime_nsec(f->dump_stream("timestamp"));
13656   if (!dump_entry_internal(entry, f)) {
13657     f->dump_int("state", entry.state);
13658   }
13659   f->close_section();
13660 }
13661
13662 RGWOpState::RGWOpState(RGWRados *_store) : RGWStateLog(_store, _store->ctx()->_conf->rgw_num_zone_opstate_shards, string("obj_opstate"))
13663 {
13664 }
13665
13666 bool RGWOpState::dump_entry_internal(const cls_statelog_entry& entry, Formatter *f)
13667 {
13668   string s;
13669   switch ((OpState)entry.state) {
13670     case OPSTATE_UNKNOWN:
13671       s = "unknown";
13672       break;
13673     case OPSTATE_IN_PROGRESS:
13674       s = "in-progress";
13675       break;
13676     case OPSTATE_COMPLETE:
13677       s = "complete";
13678       break;
13679     case OPSTATE_ERROR:
13680       s = "error";
13681       break;
13682     case OPSTATE_ABORT:
13683       s = "abort";
13684       break;
13685     case OPSTATE_CANCELLED:
13686       s = "cancelled";
13687       break;
13688     default:
13689       s = "invalid";
13690   }
13691   f->dump_string("state", s);
13692   return true;
13693 }
13694
13695 int RGWOpState::state_from_str(const string& s, OpState *state)
13696 {
13697   if (s == "unknown") {
13698     *state = OPSTATE_UNKNOWN;
13699   } else if (s == "in-progress") {
13700     *state = OPSTATE_IN_PROGRESS;
13701   } else if (s == "complete") {
13702     *state = OPSTATE_COMPLETE;
13703   } else if (s == "error") {
13704     *state = OPSTATE_ERROR;
13705   } else if (s == "abort") {
13706     *state = OPSTATE_ABORT;
13707   } else if (s == "cancelled") {
13708     *state = OPSTATE_CANCELLED;
13709   } else {
13710     return -EINVAL;
13711   }
13712
13713   return 0;
13714 }
13715
13716 int RGWOpState::set_state(const string& client_id, const string& op_id, const string& object, OpState state)
13717 {
13718   uint32_t s = (uint32_t)state;
13719   return store_entry(client_id, op_id, object, s, NULL, NULL);
13720 }
13721
13722 int RGWOpState::renew_state(const string& client_id, const string& op_id, const string& object, OpState state)
13723 {
13724   uint32_t s = (uint32_t)state;
13725   return store_entry(client_id, op_id, object, s, NULL, &s);
13726 }
13727
13728 RGWOpStateSingleOp::RGWOpStateSingleOp(RGWRados *store, const string& cid, const string& oid,
13729                                        const string& obj) : os(store), client_id(cid), op_id(oid), object(obj)
13730 {
13731   cct = store->ctx();
13732   cur_state = RGWOpState::OPSTATE_UNKNOWN;
13733 }
13734
13735 int RGWOpStateSingleOp::set_state(RGWOpState::OpState state) {
13736   last_update = real_clock::now();
13737   cur_state = state;
13738   return os.set_state(client_id, op_id, object, state);
13739 }
13740
13741 int RGWOpStateSingleOp::renew_state() {
13742   real_time now = real_clock::now();
13743
13744   int rate_limit_sec = cct->_conf->rgw_opstate_ratelimit_sec;
13745
13746   if (rate_limit_sec && now - last_update < make_timespan(rate_limit_sec)) {
13747     return 0;
13748   }
13749
13750   last_update = now;
13751   return os.renew_state(client_id, op_id, object, cur_state);
13752 }
13753
13754
13755 uint64_t RGWRados::instance_id()
13756 {
13757   return get_rados_handle()->get_instance_id();
13758 }
13759
13760 uint64_t RGWRados::next_bucket_id()
13761 {
13762   Mutex::Locker l(bucket_id_lock);
13763   return ++max_bucket_id;
13764 }
13765
13766 RGWRados *RGWStoreManager::init_storage_provider(CephContext *cct, bool use_gc_thread, bool use_lc_thread, bool quota_threads, bool run_sync_thread, bool run_reshard_thread)
13767 {
13768   int use_cache = cct->_conf->rgw_cache_enabled;
13769   RGWRados *store = NULL;
13770   if (!use_cache) {
13771     store = new RGWRados;
13772   } else {
13773     store = new RGWCache<RGWRados>; 
13774   }
13775
13776   if (store->initialize(cct, use_gc_thread, use_lc_thread, quota_threads, run_sync_thread, run_reshard_thread) < 0) {
13777     delete store;
13778     return NULL;
13779   }
13780
13781   return store;
13782 }
13783
13784 RGWRados *RGWStoreManager::init_raw_storage_provider(CephContext *cct)
13785 {
13786   RGWRados *store = NULL;
13787   store = new RGWRados;
13788
13789   store->set_context(cct);
13790
13791   if (store->init_rados() < 0) {
13792     delete store;
13793     return NULL;
13794   }
13795
13796   return store;
13797 }
13798
13799 void RGWStoreManager::close_storage(RGWRados *store)
13800 {
13801   if (!store)
13802     return;
13803
13804   store->finalize();
13805
13806   delete store;
13807 }
13808
13809 librados::Rados* RGWRados::get_rados_handle()
13810 {
13811   if (rados.size() == 1) {
13812     return &rados[0];
13813   } else {
13814     handle_lock.get_read();
13815     pthread_t id = pthread_self();
13816     std::map<pthread_t, int>:: iterator it = rados_map.find(id);
13817
13818     if (it != rados_map.end()) {
13819       handle_lock.put_read();
13820       return &rados[it->second];
13821     } else {
13822       handle_lock.put_read();
13823       handle_lock.get_write();
13824       const uint32_t handle = next_rados_handle;
13825       rados_map[id] = handle;
13826       if (++next_rados_handle == rados.size()) {
13827         next_rados_handle = 0;
13828       }
13829       handle_lock.put_write();
13830       return &rados[handle];
13831     }
13832   }
13833 }
13834
13835 int RGWRados::delete_raw_obj_aio(const rgw_raw_obj& obj, list<librados::AioCompletion *>& handles)
13836 {
13837   rgw_rados_ref ref;
13838   int ret = get_raw_obj_ref(obj, &ref);
13839   if (ret < 0) {
13840     lderr(cct) << "ERROR: failed to get obj ref with ret=" << ret << dendl;
13841     return ret;
13842   }
13843
13844   ObjectWriteOperation op;
13845   list<string> prefixes;
13846   cls_rgw_remove_obj(op, prefixes);
13847
13848   AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL);
13849   ret = ref.ioctx.aio_operate(ref.oid, c, &op);
13850   if (ret < 0) {
13851     lderr(cct) << "ERROR: AioOperate failed with ret=" << ret << dendl;
13852     c->release();
13853     return ret;
13854   }
13855
13856   handles.push_back(c);
13857
13858   return 0;
13859 }
13860
13861 int RGWRados::delete_obj_aio(const rgw_obj& obj,
13862                              RGWBucketInfo& bucket_info, RGWObjState *astate,
13863                              list<librados::AioCompletion *>& handles, bool keep_index_consistent)
13864 {
13865   rgw_rados_ref ref;
13866   int ret = get_obj_head_ref(bucket_info, obj, &ref);
13867   if (ret < 0) {
13868     lderr(cct) << "ERROR: failed to get obj ref with ret=" << ret << dendl;
13869     return ret;
13870   }
13871
13872   if (keep_index_consistent) {
13873     RGWRados::Bucket bop(this, bucket_info);
13874     RGWRados::Bucket::UpdateIndex index_op(&bop, obj);
13875
13876     ret = index_op.prepare(CLS_RGW_OP_DEL, &astate->write_tag);
13877     if (ret < 0) {
13878       lderr(cct) << "ERROR: failed to prepare index op with ret=" << ret << dendl;
13879       return ret;
13880     }
13881   }
13882
13883   ObjectWriteOperation op;
13884   list<string> prefixes;
13885   cls_rgw_remove_obj(op, prefixes);
13886
13887   AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL);
13888   ret = ref.ioctx.aio_operate(ref.oid, c, &op);
13889   if (ret < 0) {
13890     lderr(cct) << "ERROR: AioOperate failed with ret=" << ret << dendl;
13891     c->release();
13892     return ret;
13893   }
13894
13895   handles.push_back(c);
13896
13897   if (keep_index_consistent) {
13898     ret = delete_obj_index(obj);
13899     if (ret < 0) {
13900       lderr(cct) << "ERROR: failed to delete obj index with ret=" << ret << dendl;
13901       return ret;
13902     }
13903   }
13904   return ret;
13905 }
13906
13907 int rgw_compression_info_from_attrset(map<string, bufferlist>& attrs, bool& need_decompress, RGWCompressionInfo& cs_info) {
13908   map<string, bufferlist>::iterator value = attrs.find(RGW_ATTR_COMPRESSION);
13909   if (value != attrs.end()) {
13910     bufferlist::iterator bliter = value->second.begin();
13911     try {
13912       ::decode(cs_info, bliter);
13913     } catch (buffer::error& err) {
13914       return -EIO;
13915     }
13916     if (cs_info.blocks.size() == 0) {
13917       return -EIO;
13918     }
13919     if (cs_info.compression_type != "none")
13920       need_decompress = true;
13921     else
13922       need_decompress = false;
13923     return 0;
13924   } else {
13925     need_decompress = false;
13926     return 0;
13927   }
13928 }
13929