1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
4 #include "rgw_metadata.h"
9 #include "services/svc_meta.h"
10 #include "services/svc_meta_be_sobj.h"
12 #define dout_subsys ceph_subsys_rgw
16 void LogStatusDump::dump(Formatter
*f
) const {
19 case MDLOG_STATUS_WRITE
:
22 case MDLOG_STATUS_SETATTRS
:
25 case MDLOG_STATUS_REMOVE
:
28 case MDLOG_STATUS_COMPLETE
:
31 case MDLOG_STATUS_ABORT
:
38 encode_json("status", s
, f
);
41 void encode_json(const char *name
, const obj_version
& v
, Formatter
*f
)
43 f
->open_object_section(name
);
44 f
->dump_string("tag", v
.tag
);
45 f
->dump_unsigned("ver", v
.ver
);
49 void decode_json_obj(obj_version
& v
, JSONObj
*obj
)
51 JSONDecoder::decode_json("tag", v
.tag
, obj
);
52 JSONDecoder::decode_json("ver", v
.ver
, obj
);
55 void RGWMetadataLogData::encode(bufferlist
& bl
) const {
56 ENCODE_START(1, 1, bl
);
57 encode(read_version
, bl
);
58 encode(write_version
, bl
);
59 uint32_t s
= (uint32_t)status
;
64 void RGWMetadataLogData::decode(bufferlist::const_iterator
& bl
) {
66 decode(read_version
, bl
);
67 decode(write_version
, bl
);
70 status
= (RGWMDLogStatus
)s
;
74 void RGWMetadataLogData::dump(Formatter
*f
) const {
75 encode_json("read_version", read_version
, f
);
76 encode_json("write_version", write_version
, f
);
77 encode_json("status", LogStatusDump(status
), f
);
80 void decode_json_obj(RGWMDLogStatus
& status
, JSONObj
*obj
) {
82 JSONDecoder::decode_json("status", s
, obj
);
83 if (s
== "complete") {
84 status
= MDLOG_STATUS_COMPLETE
;
85 } else if (s
== "write") {
86 status
= MDLOG_STATUS_WRITE
;
87 } else if (s
== "remove") {
88 status
= MDLOG_STATUS_REMOVE
;
89 } else if (s
== "set_attrs") {
90 status
= MDLOG_STATUS_SETATTRS
;
91 } else if (s
== "abort") {
92 status
= MDLOG_STATUS_ABORT
;
94 status
= MDLOG_STATUS_UNKNOWN
;
98 void RGWMetadataLogData::decode_json(JSONObj
*obj
) {
99 JSONDecoder::decode_json("read_version", read_version
, obj
);
100 JSONDecoder::decode_json("write_version", write_version
, obj
);
101 JSONDecoder::decode_json("status", status
, obj
);
104 RGWMetadataHandler_GenericMetaBE::Put::Put(RGWMetadataHandler_GenericMetaBE
*_handler
,
105 RGWSI_MetaBackend_Handler::Op
*_op
,
106 string
& _entry
, RGWMetadataObject
*_obj
,
107 RGWObjVersionTracker
& _objv_tracker
,
109 RGWMDLogSyncType _type
, bool _from_remote_zone
):
110 handler(_handler
), op(_op
),
111 entry(_entry
), obj(_obj
),
112 objv_tracker(_objv_tracker
),
115 from_remote_zone(_from_remote_zone
)
119 int RGWMetadataHandler_GenericMetaBE::do_put_operate(Put
*put_op
, const DoutPrefixProvider
*dpp
)
121 int r
= put_op
->put_pre(dpp
);
122 if (r
!= 0) { /* r can also be STATUS_NO_APPLY */
126 r
= put_op
->put(dpp
);
131 r
= put_op
->put_post(dpp
);
132 if (r
!= 0) { /* e.g., -error or STATUS_APPLIED */
139 int RGWMetadataHandler_GenericMetaBE::get(string
& entry
, RGWMetadataObject
**obj
, optional_yield y
, const DoutPrefixProvider
*dpp
)
141 return be_handler
->call([&](RGWSI_MetaBackend_Handler::Op
*op
) {
142 return do_get(op
, entry
, obj
, y
, dpp
);
146 int RGWMetadataHandler_GenericMetaBE::put(string
& entry
, RGWMetadataObject
*obj
, RGWObjVersionTracker
& objv_tracker
,
147 optional_yield y
, const DoutPrefixProvider
*dpp
, RGWMDLogSyncType type
, bool from_remote_zone
)
149 return be_handler
->call([&](RGWSI_MetaBackend_Handler::Op
*op
) {
150 return do_put(op
, entry
, obj
, objv_tracker
, y
, dpp
, type
, from_remote_zone
);
154 int RGWMetadataHandler_GenericMetaBE::remove(string
& entry
, RGWObjVersionTracker
& objv_tracker
, optional_yield y
, const DoutPrefixProvider
*dpp
)
156 return be_handler
->call([&](RGWSI_MetaBackend_Handler::Op
*op
) {
157 return do_remove(op
, entry
, objv_tracker
, y
, dpp
);
161 int RGWMetadataHandler_GenericMetaBE::mutate(const string
& entry
,
162 const ceph::real_time
& mtime
,
163 RGWObjVersionTracker
*objv_tracker
,
165 const DoutPrefixProvider
*dpp
,
166 RGWMDLogStatus op_type
,
167 std::function
<int()> f
)
169 return be_handler
->call([&](RGWSI_MetaBackend_Handler::Op
*op
) {
170 RGWSI_MetaBackend::MutateParams
params(mtime
, op_type
);
171 return op
->mutate(entry
,
180 int RGWMetadataHandler_GenericMetaBE::get_shard_id(const string
& entry
, int *shard_id
)
182 return be_handler
->call([&](RGWSI_MetaBackend_Handler::Op
*op
) {
183 return op
->get_shard_id(entry
, shard_id
);
187 int RGWMetadataHandler_GenericMetaBE::list_keys_init(const DoutPrefixProvider
*dpp
, const string
& marker
, void **phandle
)
189 auto op
= std::make_unique
<RGWSI_MetaBackend_Handler::Op_ManagedCtx
>(be_handler
);
191 int ret
= op
->list_init(dpp
, marker
);
196 *phandle
= (void *)op
.release();
201 int RGWMetadataHandler_GenericMetaBE::list_keys_next(const DoutPrefixProvider
*dpp
, void *handle
, int max
, list
<string
>& keys
, bool *truncated
)
203 auto op
= static_cast<RGWSI_MetaBackend_Handler::Op_ManagedCtx
*>(handle
);
205 int ret
= op
->list_next(dpp
, max
, &keys
, truncated
);
206 if (ret
< 0 && ret
!= -ENOENT
) {
209 if (ret
== -ENOENT
) {
219 void RGWMetadataHandler_GenericMetaBE::list_keys_complete(void *handle
)
221 auto op
= static_cast<RGWSI_MetaBackend_Handler::Op_ManagedCtx
*>(handle
);
225 string
RGWMetadataHandler_GenericMetaBE::get_marker(void *handle
)
227 auto op
= static_cast<RGWSI_MetaBackend_Handler::Op_ManagedCtx
*>(handle
);
229 int r
= op
->list_get_marker(&marker
);
231 ldout(cct
, 0) << "ERROR: " << __func__
<< "(): list_get_marker() returned: r=" << r
<< dendl
;
232 /* not much else to do */
238 RGWMetadataHandlerPut_SObj::RGWMetadataHandlerPut_SObj(RGWMetadataHandler_GenericMetaBE
*handler
,
239 RGWSI_MetaBackend_Handler::Op
*op
,
240 string
& entry
, RGWMetadataObject
*obj
, RGWObjVersionTracker
& objv_tracker
,
242 RGWMDLogSyncType type
, bool from_remote_zone
) : Put(handler
, op
, entry
, obj
, objv_tracker
, y
, type
, from_remote_zone
) {
245 int RGWMetadataHandlerPut_SObj::put_pre(const DoutPrefixProvider
*dpp
)
247 int ret
= get(&old_obj
, dpp
);
248 if (ret
< 0 && ret
!= -ENOENT
) {
251 exists
= (ret
!= -ENOENT
);
255 auto old_ver
= (!old_obj
? obj_version() : old_obj
->get_version());
256 auto old_mtime
= (!old_obj
? ceph::real_time() : old_obj
->get_mtime());
258 // are we actually going to perform this put, or is it too old?
259 if (!handler
->check_versions(exists
, old_ver
, old_mtime
,
260 objv_tracker
.write_version
, obj
->get_mtime(),
262 return STATUS_NO_APPLY
;
265 objv_tracker
.read_version
= old_ver
; /* maintain the obj version we just read */
270 int RGWMetadataHandlerPut_SObj::put(const DoutPrefixProvider
*dpp
)
272 int ret
= put_check(dpp
);
277 return put_checked(dpp
);
280 int RGWMetadataHandlerPut_SObj::put_checked(const DoutPrefixProvider
*dpp
)
282 RGWSI_MBSObj_PutParams
params(obj
->get_pattrs(), obj
->get_mtime());
284 encode_obj(¶ms
.bl
);
286 int ret
= op
->put(entry
, params
, &objv_tracker
, y
, dpp
);
294 class RGWMetadataTopHandler
: public RGWMetadataHandler
{
296 set
<string
> sections
;
297 set
<string
>::iterator iter
;
301 RGWSI_Meta
*meta
{nullptr};
304 RGWMetadataManager
*mgr
;
307 RGWMetadataTopHandler(RGWSI_Meta
*meta_svc
,
308 RGWMetadataManager
*_mgr
) : mgr(_mgr
) {
309 base_init(meta_svc
->ctx());
313 string
get_type() override
{ return string(); }
315 RGWMetadataObject
*get_meta_obj(JSONObj
*jo
, const obj_version
& objv
, const ceph::real_time
& mtime
) {
316 return new RGWMetadataObject
;
319 int get(string
& entry
, RGWMetadataObject
**obj
, optional_yield y
, const DoutPrefixProvider
*dpp
) override
{
323 int put(string
& entry
, RGWMetadataObject
*obj
, RGWObjVersionTracker
& objv_tracker
,
324 optional_yield y
, const DoutPrefixProvider
*dpp
, RGWMDLogSyncType type
, bool from_remote_zone
) override
{
328 int remove(string
& entry
, RGWObjVersionTracker
& objv_tracker
, optional_yield y
, const DoutPrefixProvider
*dpp
) override
{
332 int mutate(const string
& entry
,
333 const ceph::real_time
& mtime
,
334 RGWObjVersionTracker
*objv_tracker
,
336 const DoutPrefixProvider
*dpp
,
337 RGWMDLogStatus op_type
,
338 std::function
<int()> f
) {
342 int list_keys_init(const DoutPrefixProvider
*dpp
, const string
& marker
, void **phandle
) override
{
343 iter_data
*data
= new iter_data
;
344 list
<string
> sections
;
345 mgr
->get_sections(sections
);
346 for (auto& s
: sections
) {
347 data
->sections
.insert(s
);
349 data
->iter
= data
->sections
.lower_bound(marker
);
355 int list_keys_next(const DoutPrefixProvider
*dpp
, void *handle
, int max
, list
<string
>& keys
, bool *truncated
) override
{
356 iter_data
*data
= static_cast<iter_data
*>(handle
);
357 for (int i
= 0; i
< max
&& data
->iter
!= data
->sections
.end(); ++i
, ++(data
->iter
)) {
358 keys
.push_back(*data
->iter
);
361 *truncated
= (data
->iter
!= data
->sections
.end());
365 void list_keys_complete(void *handle
) override
{
366 iter_data
*data
= static_cast<iter_data
*>(handle
);
371 virtual string
get_marker(void *handle
) override
{
372 iter_data
*data
= static_cast<iter_data
*>(handle
);
374 if (data
->iter
!= data
->sections
.end()) {
375 return *(data
->iter
);
382 RGWMetadataHandlerPut_SObj::~RGWMetadataHandlerPut_SObj() {}
384 int RGWMetadataHandler::attach(RGWMetadataManager
*manager
)
386 return manager
->register_handler(this);
389 RGWMetadataHandler::~RGWMetadataHandler() {}
391 obj_version
& RGWMetadataObject::get_version()
396 RGWMetadataManager::RGWMetadataManager(RGWSI_Meta
*_meta_svc
)
397 : cct(_meta_svc
->ctx()), meta_svc(_meta_svc
)
399 md_top_handler
.reset(new RGWMetadataTopHandler(meta_svc
, this));
402 RGWMetadataManager::~RGWMetadataManager()
406 int RGWMetadataManager::register_handler(RGWMetadataHandler
*handler
)
408 string type
= handler
->get_type();
410 if (handlers
.find(type
) != handlers
.end())
413 handlers
[type
] = handler
;
418 RGWMetadataHandler
*RGWMetadataManager::get_handler(const string
& type
)
420 map
<string
, RGWMetadataHandler
*>::iterator iter
= handlers
.find(type
);
421 if (iter
== handlers
.end())
427 void RGWMetadataManager::parse_metadata_key(const string
& metadata_key
, string
& type
, string
& entry
)
429 auto pos
= metadata_key
.find(':');
430 if (pos
== string::npos
) {
433 type
= metadata_key
.substr(0, pos
);
434 entry
= metadata_key
.substr(pos
+ 1);
438 int RGWMetadataManager::find_handler(const string
& metadata_key
, RGWMetadataHandler
**handler
, string
& entry
)
442 parse_metadata_key(metadata_key
, type
, entry
);
445 *handler
= md_top_handler
.get();
449 map
<string
, RGWMetadataHandler
*>::iterator iter
= handlers
.find(type
);
450 if (iter
== handlers
.end())
453 *handler
= iter
->second
;
459 int RGWMetadataManager::get(string
& metadata_key
, Formatter
*f
, optional_yield y
, const DoutPrefixProvider
*dpp
)
461 RGWMetadataHandler
*handler
;
463 int ret
= find_handler(metadata_key
, &handler
, entry
);
468 RGWMetadataObject
*obj
;
470 ret
= handler
->get(entry
, &obj
, y
, dpp
);
475 f
->open_object_section("metadata_info");
476 encode_json("key", metadata_key
, f
);
477 encode_json("ver", obj
->get_version(), f
);
478 real_time mtime
= obj
->get_mtime();
479 if (!real_clock::is_zero(mtime
)) {
481 encode_json("mtime", ut
, f
);
483 encode_json("data", *obj
, f
);
491 int RGWMetadataManager::put(string
& metadata_key
, bufferlist
& bl
,
493 const DoutPrefixProvider
*dpp
,
494 RGWMDLogSyncType sync_type
,
495 bool from_remote_zone
,
496 obj_version
*existing_version
)
498 RGWMetadataHandler
*handler
;
501 int ret
= find_handler(metadata_key
, &handler
, entry
);
507 if (!parser
.parse(bl
.c_str(), bl
.length())) {
511 RGWObjVersionTracker objv_tracker
;
513 obj_version
*objv
= &objv_tracker
.write_version
;
518 JSONDecoder::decode_json("key", metadata_key
, &parser
);
519 JSONDecoder::decode_json("ver", *objv
, &parser
);
520 JSONDecoder::decode_json("mtime", mtime
, &parser
);
521 } catch (JSONDecoder::err
& e
) {
525 JSONObj
*jo
= parser
.find_obj("data");
529 RGWMetadataObject
*obj
= handler
->get_meta_obj(jo
, *objv
, mtime
.to_real_time());
534 ret
= handler
->put(entry
, obj
, objv_tracker
, y
, dpp
, sync_type
, from_remote_zone
);
535 if (existing_version
) {
536 *existing_version
= objv_tracker
.read_version
;
544 int RGWMetadataManager::remove(string
& metadata_key
, optional_yield y
, const DoutPrefixProvider
*dpp
)
546 RGWMetadataHandler
*handler
;
549 int ret
= find_handler(metadata_key
, &handler
, entry
);
554 RGWMetadataObject
*obj
;
555 ret
= handler
->get(entry
, &obj
, y
, dpp
);
559 RGWObjVersionTracker objv_tracker
;
560 objv_tracker
.read_version
= obj
->get_version();
563 return handler
->remove(entry
, objv_tracker
, y
, dpp
);
566 int RGWMetadataManager::mutate(const string
& metadata_key
,
567 const ceph::real_time
& mtime
,
568 RGWObjVersionTracker
*objv_tracker
,
570 const DoutPrefixProvider
*dpp
,
571 RGWMDLogStatus op_type
,
572 std::function
<int()> f
)
574 RGWMetadataHandler
*handler
;
577 int ret
= find_handler(metadata_key
, &handler
, entry
);
582 return handler
->mutate(entry
, mtime
, objv_tracker
, y
, dpp
, op_type
, f
);
585 int RGWMetadataManager::get_shard_id(const string
& section
, const string
& entry
, int *shard_id
)
587 RGWMetadataHandler
*handler
= get_handler(section
);
592 return handler
->get_shard_id(entry
, shard_id
);
595 struct list_keys_handle
{
597 RGWMetadataHandler
*handler
;
600 int RGWMetadataManager::list_keys_init(const DoutPrefixProvider
*dpp
, const string
& section
, void **handle
)
602 return list_keys_init(dpp
, section
, string(), handle
);
605 int RGWMetadataManager::list_keys_init(const DoutPrefixProvider
*dpp
, const string
& section
,
606 const string
& marker
, void **handle
)
609 RGWMetadataHandler
*handler
;
613 ret
= find_handler(section
, &handler
, entry
);
618 list_keys_handle
*h
= new list_keys_handle
;
619 h
->handler
= handler
;
620 ret
= handler
->list_keys_init(dpp
, marker
, &h
->handle
);
631 int RGWMetadataManager::list_keys_next(const DoutPrefixProvider
*dpp
, void *handle
, int max
, list
<string
>& keys
, bool *truncated
)
633 list_keys_handle
*h
= static_cast<list_keys_handle
*>(handle
);
635 RGWMetadataHandler
*handler
= h
->handler
;
637 return handler
->list_keys_next(dpp
, h
->handle
, max
, keys
, truncated
);
640 void RGWMetadataManager::list_keys_complete(void *handle
)
642 list_keys_handle
*h
= static_cast<list_keys_handle
*>(handle
);
644 RGWMetadataHandler
*handler
= h
->handler
;
646 handler
->list_keys_complete(h
->handle
);
650 string
RGWMetadataManager::get_marker(void *handle
)
652 list_keys_handle
*h
= static_cast<list_keys_handle
*>(handle
);
654 return h
->handler
->get_marker(h
->handle
);
657 void RGWMetadataManager::dump_log_entry(cls_log_entry
& entry
, Formatter
*f
)
659 f
->open_object_section("entry");
660 f
->dump_string("id", entry
.id
);
661 f
->dump_string("section", entry
.section
);
662 f
->dump_string("name", entry
.name
);
663 entry
.timestamp
.gmtime_nsec(f
->dump_stream("timestamp"));
666 RGWMetadataLogData log_data
;
667 auto iter
= entry
.data
.cbegin();
668 decode(log_data
, iter
);
670 encode_json("data", log_data
, f
);
671 } catch (buffer::error
& err
) {
672 lderr(cct
) << "failed to decode log entry: " << entry
.section
<< ":" << entry
.name
<< " ts=" << entry
.timestamp
<< dendl
;
677 void RGWMetadataManager::get_sections(list
<string
>& sections
)
679 for (map
<string
, RGWMetadataHandler
*>::iterator iter
= handlers
.begin(); iter
!= handlers
.end(); ++iter
) {
680 sections
.push_back(iter
->first
);