]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab ft=cpp | |
3 | ||
4 | ||
5 | #include "svc_bucket_sobj.h" | |
6 | #include "svc_zone.h" | |
7 | #include "svc_sys_obj.h" | |
8 | #include "svc_sys_obj_cache.h" | |
9 | #include "svc_bi.h" | |
10 | #include "svc_meta.h" | |
11 | #include "svc_meta_be_sobj.h" | |
12 | #include "svc_sync_modules.h" | |
13 | ||
1e59de90 TL |
14 | #include "rgw_bucket.h" |
15 | #include "rgw_tools.h" | |
16 | #include "rgw_zone.h" | |
9f95a23c TL |
17 | |
18 | #define dout_subsys ceph_subsys_rgw | |
19 | ||
20 | #define RGW_BUCKET_INSTANCE_MD_PREFIX ".bucket.meta." | |
21 | ||
20effc67 TL |
22 | using namespace std; |
23 | ||
9f95a23c TL |
24 | class RGWSI_Bucket_SObj_Module : public RGWSI_MBSObj_Handler_Module { |
25 | RGWSI_Bucket_SObj::Svc& svc; | |
26 | ||
27 | const string prefix; | |
28 | public: | |
29 | RGWSI_Bucket_SObj_Module(RGWSI_Bucket_SObj::Svc& _svc) : RGWSI_MBSObj_Handler_Module("bucket"), | |
30 | svc(_svc) {} | |
31 | ||
32 | void get_pool_and_oid(const string& key, rgw_pool *pool, string *oid) override { | |
33 | if (pool) { | |
34 | *pool = svc.zone->get_zone_params().domain_root; | |
35 | } | |
36 | if (oid) { | |
37 | *oid = key; | |
38 | } | |
39 | } | |
40 | ||
41 | const string& get_oid_prefix() override { | |
42 | return prefix; | |
43 | } | |
44 | ||
45 | bool is_valid_oid(const string& oid) override { | |
46 | return (!oid.empty() && oid[0] != '.'); | |
47 | } | |
48 | ||
49 | string key_to_oid(const string& key) override { | |
50 | return key; | |
51 | } | |
52 | ||
53 | string oid_to_key(const string& oid) override { | |
54 | /* should have been called after is_valid_oid(), | |
55 | * so no need to check for validity */ | |
56 | return oid; | |
57 | } | |
58 | }; | |
59 | ||
60 | class RGWSI_BucketInstance_SObj_Module : public RGWSI_MBSObj_Handler_Module { | |
61 | RGWSI_Bucket_SObj::Svc& svc; | |
62 | ||
63 | const string prefix; | |
64 | public: | |
65 | RGWSI_BucketInstance_SObj_Module(RGWSI_Bucket_SObj::Svc& _svc) : RGWSI_MBSObj_Handler_Module("bucket.instance"), | |
66 | svc(_svc), prefix(RGW_BUCKET_INSTANCE_MD_PREFIX) {} | |
67 | ||
68 | void get_pool_and_oid(const string& key, rgw_pool *pool, string *oid) override { | |
69 | if (pool) { | |
70 | *pool = svc.zone->get_zone_params().domain_root; | |
71 | } | |
72 | if (oid) { | |
73 | *oid = key_to_oid(key); | |
74 | } | |
75 | } | |
76 | ||
77 | const string& get_oid_prefix() override { | |
78 | return prefix; | |
79 | } | |
80 | ||
81 | bool is_valid_oid(const string& oid) override { | |
82 | return (oid.compare(0, prefix.size(), RGW_BUCKET_INSTANCE_MD_PREFIX) == 0); | |
83 | } | |
84 | ||
85 | // 'tenant/' is used in bucket instance keys for sync to avoid parsing ambiguity | |
86 | // with the existing instance[:shard] format. once we parse the shard, the / is | |
87 | // replaced with a : to match the [tenant:]instance format | |
88 | string key_to_oid(const string& key) override { | |
89 | string oid = prefix + key; | |
90 | ||
91 | // replace tenant/ with tenant: | |
92 | auto c = oid.find('/', prefix.size()); | |
93 | if (c != string::npos) { | |
94 | oid[c] = ':'; | |
95 | } | |
96 | ||
97 | return oid; | |
98 | } | |
99 | ||
100 | // convert bucket instance oids back to the tenant/ format for metadata keys. | |
101 | // it's safe to parse 'tenant:' only for oids, because they won't contain the | |
102 | // optional :shard at the end | |
103 | string oid_to_key(const string& oid) override { | |
104 | /* this should have been called after oid was checked for validity */ | |
105 | ||
106 | if (oid.size() < prefix.size()) { /* just sanity check */ | |
107 | return string(); | |
108 | } | |
109 | ||
110 | string key = oid.substr(prefix.size()); | |
111 | ||
112 | // find first : (could be tenant:bucket or bucket:instance) | |
113 | auto c = key.find(':'); | |
114 | if (c != string::npos) { | |
115 | // if we find another :, the first one was for tenant | |
116 | if (key.find(':', c + 1) != string::npos) { | |
117 | key[c] = '/'; | |
118 | } | |
119 | } | |
120 | ||
121 | return key; | |
122 | } | |
123 | ||
124 | /* | |
125 | * hash entry for mdlog placement. Use the same hash key we'd have for the bucket entry | |
126 | * point, so that the log entries end up at the same log shard, so that we process them | |
127 | * in order | |
128 | */ | |
129 | string get_hash_key(const string& key) override { | |
130 | string k = "bucket:"; | |
131 | int pos = key.find(':'); | |
132 | if (pos < 0) | |
133 | k.append(key); | |
134 | else | |
135 | k.append(key.substr(0, pos)); | |
136 | ||
137 | return k; | |
138 | } | |
139 | }; | |
140 | ||
141 | RGWSI_Bucket_SObj::RGWSI_Bucket_SObj(CephContext *cct): RGWSI_Bucket(cct) { | |
142 | } | |
143 | ||
144 | RGWSI_Bucket_SObj::~RGWSI_Bucket_SObj() { | |
145 | } | |
146 | ||
147 | void RGWSI_Bucket_SObj::init(RGWSI_Zone *_zone_svc, RGWSI_SysObj *_sysobj_svc, | |
148 | RGWSI_SysObj_Cache *_cache_svc, RGWSI_BucketIndex *_bi, | |
149 | RGWSI_Meta *_meta_svc, RGWSI_MetaBackend *_meta_be_svc, | |
150 | RGWSI_SyncModules *_sync_modules_svc, | |
151 | RGWSI_Bucket_Sync *_bucket_sync_svc) | |
152 | { | |
153 | svc.bucket = this; | |
154 | svc.zone = _zone_svc; | |
155 | svc.sysobj = _sysobj_svc; | |
156 | svc.cache = _cache_svc; | |
157 | svc.bi = _bi; | |
158 | svc.meta = _meta_svc; | |
159 | svc.meta_be = _meta_be_svc; | |
160 | svc.sync_modules = _sync_modules_svc; | |
161 | svc.bucket_sync = _bucket_sync_svc; | |
162 | } | |
163 | ||
b3b6e05e | 164 | int RGWSI_Bucket_SObj::do_start(optional_yield, const DoutPrefixProvider *dpp) |
9f95a23c TL |
165 | { |
166 | binfo_cache.reset(new RGWChainedCacheImpl<bucket_info_cache_entry>); | |
167 | binfo_cache->init(svc.cache); | |
168 | ||
169 | /* create first backend handler for bucket entrypoints */ | |
170 | ||
171 | RGWSI_MetaBackend_Handler *ep_handler; | |
172 | ||
173 | int r = svc.meta->create_be_handler(RGWSI_MetaBackend::Type::MDBE_SOBJ, &ep_handler); | |
174 | if (r < 0) { | |
b3b6e05e | 175 | ldpp_dout(dpp, 0) << "ERROR: failed to create be handler: r=" << r << dendl; |
9f95a23c TL |
176 | return r; |
177 | } | |
178 | ||
179 | ep_be_handler = ep_handler; | |
180 | ||
181 | RGWSI_MetaBackend_Handler_SObj *ep_bh = static_cast<RGWSI_MetaBackend_Handler_SObj *>(ep_handler); | |
182 | ||
183 | auto ep_module = new RGWSI_Bucket_SObj_Module(svc); | |
184 | ep_be_module.reset(ep_module); | |
185 | ep_bh->set_module(ep_module); | |
186 | ||
187 | /* create a second backend handler for bucket instance */ | |
188 | ||
189 | RGWSI_MetaBackend_Handler *bi_handler; | |
190 | ||
191 | r = svc.meta->create_be_handler(RGWSI_MetaBackend::Type::MDBE_SOBJ, &bi_handler); | |
192 | if (r < 0) { | |
b3b6e05e | 193 | ldpp_dout(dpp, 0) << "ERROR: failed to create be handler: r=" << r << dendl; |
9f95a23c TL |
194 | return r; |
195 | } | |
196 | ||
197 | bi_be_handler = bi_handler; | |
198 | ||
199 | RGWSI_MetaBackend_Handler_SObj *bi_bh = static_cast<RGWSI_MetaBackend_Handler_SObj *>(bi_handler); | |
200 | ||
201 | auto bi_module = new RGWSI_BucketInstance_SObj_Module(svc); | |
202 | bi_be_module.reset(bi_module); | |
203 | bi_bh->set_module(bi_module); | |
204 | ||
205 | return 0; | |
206 | } | |
207 | ||
208 | int RGWSI_Bucket_SObj::read_bucket_entrypoint_info(RGWSI_Bucket_EP_Ctx& ctx, | |
209 | const string& key, | |
210 | RGWBucketEntryPoint *entry_point, | |
211 | RGWObjVersionTracker *objv_tracker, | |
212 | real_time *pmtime, | |
213 | map<string, bufferlist> *pattrs, | |
214 | optional_yield y, | |
b3b6e05e | 215 | const DoutPrefixProvider *dpp, |
9f95a23c TL |
216 | rgw_cache_entry_info *cache_info, |
217 | boost::optional<obj_version> refresh_version) | |
218 | { | |
219 | bufferlist bl; | |
220 | ||
221 | auto params = RGWSI_MBSObj_GetParams(&bl, pattrs, pmtime).set_cache_info(cache_info) | |
222 | .set_refresh_version(refresh_version); | |
223 | ||
b3b6e05e | 224 | int ret = svc.meta_be->get_entry(ctx.get(), key, params, objv_tracker, y, dpp); |
9f95a23c TL |
225 | if (ret < 0) { |
226 | return ret; | |
227 | } | |
228 | ||
229 | auto iter = bl.cbegin(); | |
230 | try { | |
231 | decode(*entry_point, iter); | |
232 | } catch (buffer::error& err) { | |
b3b6e05e | 233 | ldpp_dout(dpp, 0) << "ERROR: could not decode buffer info, caught buffer::error" << dendl; |
9f95a23c TL |
234 | return -EIO; |
235 | } | |
236 | return 0; | |
237 | } | |
238 | ||
239 | int RGWSI_Bucket_SObj::store_bucket_entrypoint_info(RGWSI_Bucket_EP_Ctx& ctx, | |
240 | const string& key, | |
241 | RGWBucketEntryPoint& info, | |
242 | bool exclusive, | |
243 | real_time mtime, | |
f51cf556 | 244 | const map<string, bufferlist> *pattrs, |
9f95a23c | 245 | RGWObjVersionTracker *objv_tracker, |
b3b6e05e TL |
246 | optional_yield y, |
247 | const DoutPrefixProvider *dpp) | |
9f95a23c TL |
248 | { |
249 | bufferlist bl; | |
250 | encode(info, bl); | |
251 | ||
252 | RGWSI_MBSObj_PutParams params(bl, pattrs, mtime, exclusive); | |
253 | ||
b3b6e05e | 254 | int ret = svc.meta_be->put(ctx.get(), key, params, objv_tracker, y, dpp); |
9f95a23c TL |
255 | if (ret < 0) { |
256 | return ret; | |
257 | } | |
258 | ||
259 | return ret; | |
260 | } | |
261 | ||
262 | int RGWSI_Bucket_SObj::remove_bucket_entrypoint_info(RGWSI_Bucket_EP_Ctx& ctx, | |
263 | const string& key, | |
264 | RGWObjVersionTracker *objv_tracker, | |
b3b6e05e TL |
265 | optional_yield y, |
266 | const DoutPrefixProvider *dpp) | |
9f95a23c TL |
267 | { |
268 | RGWSI_MBSObj_RemoveParams params; | |
b3b6e05e | 269 | return svc.meta_be->remove(ctx.get(), key, params, objv_tracker, y, dpp); |
9f95a23c TL |
270 | } |
271 | ||
272 | int RGWSI_Bucket_SObj::read_bucket_instance_info(RGWSI_Bucket_BI_Ctx& ctx, | |
273 | const string& key, | |
274 | RGWBucketInfo *info, | |
275 | real_time *pmtime, map<string, bufferlist> *pattrs, | |
276 | optional_yield y, | |
b3b6e05e | 277 | const DoutPrefixProvider *dpp, |
9f95a23c TL |
278 | rgw_cache_entry_info *cache_info, |
279 | boost::optional<obj_version> refresh_version) | |
280 | { | |
281 | string cache_key("bi/"); | |
282 | cache_key.append(key); | |
283 | ||
284 | if (auto e = binfo_cache->find(cache_key)) { | |
285 | if (refresh_version && | |
286 | e->info.objv_tracker.read_version.compare(&(*refresh_version))) { | |
b3b6e05e | 287 | ldpp_dout(dpp, -1) << "WARNING: The bucket info cache is inconsistent. This is " |
9f95a23c TL |
288 | << "a failure that should be debugged. I am a nice machine, " |
289 | << "so I will try to recover." << dendl; | |
290 | binfo_cache->invalidate(key); | |
291 | } else { | |
292 | *info = e->info; | |
293 | if (pattrs) | |
294 | *pattrs = e->attrs; | |
295 | if (pmtime) | |
296 | *pmtime = e->mtime; | |
297 | return 0; | |
298 | } | |
299 | } | |
300 | ||
301 | bucket_info_cache_entry e; | |
302 | rgw_cache_entry_info ci; | |
303 | ||
304 | int ret = do_read_bucket_instance_info(ctx, key, | |
305 | &e.info, &e.mtime, &e.attrs, | |
b3b6e05e | 306 | &ci, refresh_version, y, dpp); |
9f95a23c TL |
307 | *info = e.info; |
308 | ||
309 | if (ret < 0) { | |
310 | if (ret != -ENOENT) { | |
b3b6e05e | 311 | ldpp_dout(dpp, -1) << "ERROR: do_read_bucket_instance_info failed: " << ret << dendl; |
9f95a23c | 312 | } else { |
b3b6e05e | 313 | ldpp_dout(dpp, 20) << "do_read_bucket_instance_info, bucket instance not found (key=" << key << ")" << dendl; |
9f95a23c TL |
314 | } |
315 | return ret; | |
316 | } | |
317 | ||
318 | if (pmtime) { | |
319 | *pmtime = e.mtime; | |
320 | } | |
321 | if (pattrs) { | |
322 | *pattrs = e.attrs; | |
323 | } | |
324 | if (cache_info) { | |
325 | *cache_info = ci; | |
326 | } | |
327 | ||
328 | /* chain to only bucket instance and *not* bucket entrypoint */ | |
b3b6e05e TL |
329 | if (!binfo_cache->put(dpp, svc.cache, cache_key, &e, {&ci})) { |
330 | ldpp_dout(dpp, 20) << "couldn't put binfo cache entry, might have raced with data changes" << dendl; | |
9f95a23c TL |
331 | } |
332 | ||
333 | if (refresh_version && | |
334 | refresh_version->compare(&info->objv_tracker.read_version)) { | |
b3b6e05e | 335 | ldpp_dout(dpp, -1) << "WARNING: The OSD has the same version I have. Something may " |
9f95a23c TL |
336 | << "have gone squirrelly. An administrator may have forced a " |
337 | << "change; otherwise there is a problem somewhere." << dendl; | |
338 | } | |
339 | ||
340 | return 0; | |
341 | } | |
342 | ||
343 | int RGWSI_Bucket_SObj::do_read_bucket_instance_info(RGWSI_Bucket_BI_Ctx& ctx, | |
344 | const string& key, | |
345 | RGWBucketInfo *info, | |
346 | real_time *pmtime, map<string, bufferlist> *pattrs, | |
347 | rgw_cache_entry_info *cache_info, | |
348 | boost::optional<obj_version> refresh_version, | |
b3b6e05e TL |
349 | optional_yield y, |
350 | const DoutPrefixProvider *dpp) | |
9f95a23c TL |
351 | { |
352 | bufferlist bl; | |
353 | RGWObjVersionTracker ot; | |
354 | ||
355 | auto params = RGWSI_MBSObj_GetParams(&bl, pattrs, pmtime).set_cache_info(cache_info) | |
356 | .set_refresh_version(refresh_version); | |
357 | ||
b3b6e05e | 358 | int ret = svc.meta_be->get_entry(ctx.get(), key, params, &ot, y, dpp); |
9f95a23c TL |
359 | if (ret < 0) { |
360 | return ret; | |
361 | } | |
362 | ||
363 | auto iter = bl.cbegin(); | |
364 | try { | |
365 | decode(*info, iter); | |
366 | } catch (buffer::error& err) { | |
b3b6e05e | 367 | ldpp_dout(dpp, 0) << "ERROR: could not decode buffer info, caught buffer::error" << dendl; |
9f95a23c TL |
368 | return -EIO; |
369 | } | |
370 | info->objv_tracker = ot; | |
371 | return 0; | |
372 | } | |
373 | ||
374 | int RGWSI_Bucket_SObj::read_bucket_info(RGWSI_Bucket_X_Ctx& ctx, | |
375 | const rgw_bucket& bucket, | |
376 | RGWBucketInfo *info, | |
377 | real_time *pmtime, | |
378 | map<string, bufferlist> *pattrs, | |
379 | boost::optional<obj_version> refresh_version, | |
b3b6e05e TL |
380 | optional_yield y, |
381 | const DoutPrefixProvider *dpp) | |
9f95a23c TL |
382 | { |
383 | rgw_cache_entry_info cache_info; | |
384 | ||
385 | if (!bucket.bucket_id.empty()) { | |
386 | return read_bucket_instance_info(ctx.bi, get_bi_meta_key(bucket), | |
387 | info, | |
388 | pmtime, pattrs, | |
389 | y, | |
b3b6e05e | 390 | dpp, |
9f95a23c TL |
391 | &cache_info, refresh_version); |
392 | } | |
393 | ||
394 | string bucket_entry = get_entrypoint_meta_key(bucket); | |
395 | string cache_key("b/"); | |
396 | cache_key.append(bucket_entry); | |
397 | ||
398 | if (auto e = binfo_cache->find(cache_key)) { | |
399 | bool found_version = (bucket.bucket_id.empty() || | |
400 | bucket.bucket_id == e->info.bucket.bucket_id); | |
401 | ||
402 | if (!found_version || | |
403 | (refresh_version && | |
404 | e->info.objv_tracker.read_version.compare(&(*refresh_version)))) { | |
20effc67 | 405 | ldpp_dout(dpp, -1) << "WARNING: The bucket info cache is inconsistent. This is " |
9f95a23c TL |
406 | << "a failure that should be debugged. I am a nice machine, " |
407 | << "so I will try to recover." << dendl; | |
408 | binfo_cache->invalidate(cache_key); | |
409 | } else { | |
410 | *info = e->info; | |
411 | if (pattrs) | |
412 | *pattrs = e->attrs; | |
413 | if (pmtime) | |
414 | *pmtime = e->mtime; | |
415 | return 0; | |
416 | } | |
417 | } | |
418 | ||
419 | RGWBucketEntryPoint entry_point; | |
420 | real_time ep_mtime; | |
421 | RGWObjVersionTracker ot; | |
422 | rgw_cache_entry_info entry_cache_info; | |
423 | int ret = read_bucket_entrypoint_info(ctx.ep, bucket_entry, | |
424 | &entry_point, &ot, &ep_mtime, pattrs, | |
425 | y, | |
b3b6e05e | 426 | dpp, |
9f95a23c TL |
427 | &entry_cache_info, refresh_version); |
428 | if (ret < 0) { | |
429 | /* only init these fields */ | |
430 | info->bucket = bucket; | |
431 | return ret; | |
432 | } | |
433 | ||
434 | if (entry_point.has_bucket_info) { | |
435 | *info = entry_point.old_bucket_info; | |
436 | info->bucket.tenant = bucket.tenant; | |
b3b6e05e | 437 | ldpp_dout(dpp, 20) << "rgw_get_bucket_info: old bucket info, bucket=" << info->bucket << " owner " << info->owner << dendl; |
9f95a23c TL |
438 | return 0; |
439 | } | |
440 | ||
441 | /* data is in the bucket instance object, we need to get attributes from there, clear everything | |
442 | * that we got | |
443 | */ | |
444 | if (pattrs) { | |
445 | pattrs->clear(); | |
446 | } | |
447 | ||
b3b6e05e | 448 | ldpp_dout(dpp, 20) << "rgw_get_bucket_info: bucket instance: " << entry_point.bucket << dendl; |
9f95a23c TL |
449 | |
450 | ||
451 | /* read bucket instance info */ | |
452 | ||
453 | bucket_info_cache_entry e; | |
454 | ||
455 | ret = read_bucket_instance_info(ctx.bi, get_bi_meta_key(entry_point.bucket), | |
456 | &e.info, &e.mtime, &e.attrs, | |
457 | y, | |
b3b6e05e | 458 | dpp, |
9f95a23c TL |
459 | &cache_info, refresh_version); |
460 | *info = e.info; | |
461 | if (ret < 0) { | |
b3b6e05e | 462 | ldpp_dout(dpp, -1) << "ERROR: read_bucket_instance_from_oid failed: " << ret << dendl; |
9f95a23c TL |
463 | info->bucket = bucket; |
464 | // XXX and why return anything in case of an error anyway? | |
465 | return ret; | |
466 | } | |
467 | ||
468 | if (pmtime) | |
469 | *pmtime = e.mtime; | |
470 | if (pattrs) | |
471 | *pattrs = e.attrs; | |
472 | ||
473 | /* chain to both bucket entry point and bucket instance */ | |
b3b6e05e TL |
474 | if (!binfo_cache->put(dpp, svc.cache, cache_key, &e, {&entry_cache_info, &cache_info})) { |
475 | ldpp_dout(dpp, 20) << "couldn't put binfo cache entry, might have raced with data changes" << dendl; | |
9f95a23c TL |
476 | } |
477 | ||
478 | if (refresh_version && | |
479 | refresh_version->compare(&info->objv_tracker.read_version)) { | |
b3b6e05e | 480 | ldpp_dout(dpp, -1) << "WARNING: The OSD has the same version I have. Something may " |
9f95a23c TL |
481 | << "have gone squirrelly. An administrator may have forced a " |
482 | << "change; otherwise there is a problem somewhere." << dendl; | |
483 | } | |
484 | ||
485 | return 0; | |
486 | } | |
487 | ||
488 | ||
489 | int RGWSI_Bucket_SObj::store_bucket_instance_info(RGWSI_Bucket_BI_Ctx& ctx, | |
490 | const string& key, | |
491 | RGWBucketInfo& info, | |
492 | std::optional<RGWBucketInfo *> orig_info, | |
493 | bool exclusive, | |
494 | real_time mtime, | |
f51cf556 | 495 | const map<string, bufferlist> *pattrs, |
b3b6e05e TL |
496 | optional_yield y, |
497 | const DoutPrefixProvider *dpp) | |
9f95a23c TL |
498 | { |
499 | bufferlist bl; | |
500 | encode(info, bl); | |
501 | ||
502 | /* | |
503 | * we might need some special handling if overwriting | |
504 | */ | |
505 | RGWBucketInfo shared_bucket_info; | |
506 | if (!orig_info && !exclusive) { /* if exclusive, we're going to fail when try | |
507 | to overwrite, so the whole check here is moot */ | |
508 | /* | |
509 | * we're here because orig_info wasn't passed in | |
510 | * we don't have info about what was there before, so need to fetch first | |
511 | */ | |
512 | int r = read_bucket_instance_info(ctx, | |
513 | key, | |
514 | &shared_bucket_info, | |
515 | nullptr, nullptr, | |
516 | y, | |
b3b6e05e | 517 | dpp, |
9f95a23c TL |
518 | nullptr, boost::none); |
519 | if (r < 0) { | |
520 | if (r != -ENOENT) { | |
b3b6e05e | 521 | ldpp_dout(dpp, 0) << "ERROR: " << __func__ << "(): read_bucket_instance_info() of key=" << key << " returned r=" << r << dendl; |
9f95a23c TL |
522 | return r; |
523 | } | |
524 | } else { | |
525 | orig_info = &shared_bucket_info; | |
526 | } | |
527 | } | |
528 | ||
529 | if (orig_info && *orig_info && !exclusive) { | |
1e59de90 | 530 | int r = svc.bi->handle_overwrite(dpp, info, *(orig_info.value()), y); |
9f95a23c | 531 | if (r < 0) { |
b3b6e05e | 532 | ldpp_dout(dpp, 0) << "ERROR: " << __func__ << "(): svc.bi->handle_overwrite() of key=" << key << " returned r=" << r << dendl; |
9f95a23c TL |
533 | return r; |
534 | } | |
535 | } | |
536 | ||
537 | RGWSI_MBSObj_PutParams params(bl, pattrs, mtime, exclusive); | |
538 | ||
b3b6e05e | 539 | int ret = svc.meta_be->put(ctx.get(), key, params, &info.objv_tracker, y, dpp); |
9f95a23c TL |
540 | |
541 | if (ret >= 0) { | |
b3b6e05e | 542 | int r = svc.bucket_sync->handle_bi_update(dpp, info, |
9f95a23c TL |
543 | orig_info.value_or(nullptr), |
544 | y); | |
545 | if (r < 0) { | |
546 | return r; | |
547 | } | |
548 | } else if (ret == -EEXIST) { | |
549 | /* well, if it's exclusive we shouldn't overwrite it, because we might race with another | |
550 | * bucket operation on this specific bucket (e.g., being synced from the master), but | |
20effc67 | 551 | * since bucket instance meta object is unique for this specific bucket instance, we don't |
9f95a23c TL |
552 | * need to return an error. |
553 | * A scenario where we'd get -EEXIST here, is in a multi-zone config, we're not on the | |
554 | * master, creating a bucket, sending bucket creation to the master, we create the bucket | |
555 | * locally, while in the sync thread we sync the new bucket. | |
556 | */ | |
557 | ret = 0; | |
558 | } | |
559 | ||
560 | if (ret < 0) { | |
561 | return ret; | |
562 | } | |
563 | ||
564 | return ret; | |
565 | } | |
566 | ||
567 | int RGWSI_Bucket_SObj::remove_bucket_instance_info(RGWSI_Bucket_BI_Ctx& ctx, | |
568 | const string& key, | |
569 | const RGWBucketInfo& info, | |
570 | RGWObjVersionTracker *objv_tracker, | |
b3b6e05e TL |
571 | optional_yield y, |
572 | const DoutPrefixProvider *dpp) | |
9f95a23c TL |
573 | { |
574 | RGWSI_MBSObj_RemoveParams params; | |
b3b6e05e | 575 | int ret = svc.meta_be->remove_entry(dpp, ctx.get(), key, params, objv_tracker, y); |
9f95a23c TL |
576 | |
577 | if (ret < 0 && | |
578 | ret != -ENOENT) { | |
579 | return ret; | |
580 | } | |
581 | ||
b3b6e05e | 582 | int r = svc.bucket_sync->handle_bi_removal(dpp, info, y); |
9f95a23c | 583 | if (r < 0) { |
b3b6e05e | 584 | ldpp_dout(dpp, 0) << "ERROR: failed to update bucket instance sync index: r=" << r << dendl; |
9f95a23c TL |
585 | /* returning success as index is just keeping hints, so will keep extra hints, |
586 | * but bucket removal succeeded | |
587 | */ | |
588 | } | |
589 | ||
590 | return 0; | |
591 | } | |
592 | ||
593 | int RGWSI_Bucket_SObj::read_bucket_stats(const RGWBucketInfo& bucket_info, | |
594 | RGWBucketEnt *ent, | |
b3b6e05e TL |
595 | optional_yield y, |
596 | const DoutPrefixProvider *dpp) | |
9f95a23c TL |
597 | { |
598 | ent->count = 0; | |
599 | ent->size = 0; | |
600 | ent->size_rounded = 0; | |
601 | ||
602 | vector<rgw_bucket_dir_header> headers; | |
603 | ||
b3b6e05e | 604 | int r = svc.bi->read_stats(dpp, bucket_info, ent, y); |
9f95a23c | 605 | if (r < 0) { |
b3b6e05e | 606 | ldpp_dout(dpp, 0) << "ERROR: " << __func__ << "(): read_stats returned r=" << r << dendl; |
9f95a23c TL |
607 | return r; |
608 | } | |
609 | ||
610 | return 0; | |
611 | } | |
612 | ||
613 | int RGWSI_Bucket_SObj::read_bucket_stats(RGWSI_Bucket_X_Ctx& ctx, | |
614 | const rgw_bucket& bucket, | |
615 | RGWBucketEnt *ent, | |
b3b6e05e TL |
616 | optional_yield y, |
617 | const DoutPrefixProvider *dpp) | |
9f95a23c TL |
618 | { |
619 | RGWBucketInfo bucket_info; | |
b3b6e05e | 620 | int ret = read_bucket_info(ctx, bucket, &bucket_info, nullptr, nullptr, boost::none, y, dpp); |
9f95a23c TL |
621 | if (ret < 0) { |
622 | return ret; | |
623 | } | |
624 | ||
b3b6e05e | 625 | return read_bucket_stats(bucket_info, ent, y, dpp); |
9f95a23c TL |
626 | } |
627 | ||
628 | int RGWSI_Bucket_SObj::read_buckets_stats(RGWSI_Bucket_X_Ctx& ctx, | |
f51cf556 | 629 | std::vector<RGWBucketEnt>& buckets, |
b3b6e05e TL |
630 | optional_yield y, |
631 | const DoutPrefixProvider *dpp) | |
9f95a23c | 632 | { |
f51cf556 | 633 | for (auto& ent : buckets) { |
b3b6e05e | 634 | int r = read_bucket_stats(ctx, ent.bucket, &ent, y, dpp); |
9f95a23c | 635 | if (r < 0) { |
b3b6e05e | 636 | ldpp_dout(dpp, 0) << "ERROR: " << __func__ << "(): read_bucket_stats returned r=" << r << dendl; |
9f95a23c TL |
637 | return r; |
638 | } | |
639 | } | |
640 | ||
f51cf556 | 641 | return buckets.size(); |
1e59de90 | 642 | } |