1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include <boost/intrusive_ptr.hpp>
5 #include "common/ceph_json.h"
6 #include "common/errno.h"
7 #include "rgw_metadata.h"
8 #include "rgw_coroutine.h"
9 #include "cls/version/cls_version_types.h"
11 #include "rgw_rados.h"
12 #include "rgw_tools.h"
14 #include "rgw_cr_rados.h"
16 #include "include/assert.h"
17 #include <boost/asio/yield.hpp>
19 #define dout_subsys ceph_subsys_rgw
21 void LogStatusDump::dump(Formatter
*f
) const {
24 case MDLOG_STATUS_WRITE
:
27 case MDLOG_STATUS_SETATTRS
:
30 case MDLOG_STATUS_REMOVE
:
33 case MDLOG_STATUS_COMPLETE
:
36 case MDLOG_STATUS_ABORT
:
43 encode_json("status", s
, f
);
46 void RGWMetadataLogData::encode(bufferlist
& bl
) const {
47 ENCODE_START(1, 1, bl
);
48 ::encode(read_version
, bl
);
49 ::encode(write_version
, bl
);
50 uint32_t s
= (uint32_t)status
;
55 void RGWMetadataLogData::decode(bufferlist::iterator
& bl
) {
57 ::decode(read_version
, bl
);
58 ::decode(write_version
, bl
);
61 status
= (RGWMDLogStatus
)s
;
65 void RGWMetadataLogData::dump(Formatter
*f
) const {
66 encode_json("read_version", read_version
, f
);
67 encode_json("write_version", write_version
, f
);
68 encode_json("status", LogStatusDump(status
), f
);
71 void decode_json_obj(RGWMDLogStatus
& status
, JSONObj
*obj
) {
73 JSONDecoder::decode_json("status", s
, obj
);
74 if (s
== "complete") {
75 status
= MDLOG_STATUS_COMPLETE
;
76 } else if (s
== "write") {
77 status
= MDLOG_STATUS_WRITE
;
78 } else if (s
== "remove") {
79 status
= MDLOG_STATUS_REMOVE
;
80 } else if (s
== "set_attrs") {
81 status
= MDLOG_STATUS_SETATTRS
;
82 } else if (s
== "abort") {
83 status
= MDLOG_STATUS_ABORT
;
85 status
= MDLOG_STATUS_UNKNOWN
;
89 void RGWMetadataLogData::decode_json(JSONObj
*obj
) {
90 JSONDecoder::decode_json("read_version", read_version
, obj
);
91 JSONDecoder::decode_json("write_version", write_version
, obj
);
92 JSONDecoder::decode_json("status", status
, obj
);
96 int RGWMetadataLog::add_entry(RGWMetadataHandler
*handler
, const string
& section
, const string
& key
, bufferlist
& bl
) {
97 if (!store
->need_to_log_metadata())
103 handler
->get_hash_key(section
, key
, hash_key
);
106 store
->shard_name(prefix
, cct
->_conf
->rgw_md_log_max_shards
, hash_key
, oid
, &shard_id
);
107 mark_modified(shard_id
);
108 real_time now
= real_clock::now();
109 return store
->time_log_add(oid
, now
, section
, key
, bl
);
112 int RGWMetadataLog::store_entries_in_shard(list
<cls_log_entry
>& entries
, int shard_id
, librados::AioCompletion
*completion
)
116 mark_modified(shard_id
);
117 store
->shard_name(prefix
, shard_id
, oid
);
118 return store
->time_log_add(oid
, entries
, completion
, false);
121 void RGWMetadataLog::init_list_entries(int shard_id
, const real_time
& from_time
, const real_time
& end_time
,
122 string
& marker
, void **handle
)
124 LogListCtx
*ctx
= new LogListCtx();
126 ctx
->cur_shard
= shard_id
;
127 ctx
->from_time
= from_time
;
128 ctx
->end_time
= end_time
;
129 ctx
->marker
= marker
;
131 get_shard_oid(ctx
->cur_shard
, ctx
->cur_oid
);
133 *handle
= (void *)ctx
;
136 void RGWMetadataLog::complete_list_entries(void *handle
) {
137 LogListCtx
*ctx
= static_cast<LogListCtx
*>(handle
);
141 int RGWMetadataLog::list_entries(void *handle
,
143 list
<cls_log_entry
>& entries
,
146 LogListCtx
*ctx
= static_cast<LogListCtx
*>(handle
);
153 int ret
= store
->time_log_list(ctx
->cur_oid
, ctx
->from_time
, ctx
->end_time
,
154 max_entries
, entries
, ctx
->marker
,
155 last_marker
, truncated
);
156 if ((ret
< 0) && (ret
!= -ENOENT
))
165 int RGWMetadataLog::get_info(int shard_id
, RGWMetadataLogInfo
*info
)
168 get_shard_oid(shard_id
, oid
);
170 cls_log_header header
;
172 int ret
= store
->time_log_info(oid
, &header
);
173 if ((ret
< 0) && (ret
!= -ENOENT
))
176 info
->marker
= header
.max_marker
;
177 info
->last_update
= header
.max_time
.to_real_time();
182 static void _mdlog_info_completion(librados::completion_t cb
, void *arg
)
184 auto infoc
= static_cast<RGWMetadataLogInfoCompletion
*>(arg
);
186 infoc
->put(); // drop the ref from get_info_async()
189 RGWMetadataLogInfoCompletion::RGWMetadataLogInfoCompletion(info_callback_t cb
)
190 : completion(librados::Rados::aio_create_completion((void *)this, nullptr,
191 _mdlog_info_completion
)),
196 RGWMetadataLogInfoCompletion::~RGWMetadataLogInfoCompletion()
198 completion
->release();
201 int RGWMetadataLog::get_info_async(int shard_id
, RGWMetadataLogInfoCompletion
*completion
)
204 get_shard_oid(shard_id
, oid
);
206 completion
->get(); // hold a ref until the completion fires
208 return store
->time_log_info_async(completion
->get_io_ctx(), oid
,
209 &completion
->get_header(),
210 completion
->get_completion());
213 int RGWMetadataLog::trim(int shard_id
, const real_time
& from_time
, const real_time
& end_time
,
214 const string
& start_marker
, const string
& end_marker
)
217 get_shard_oid(shard_id
, oid
);
221 ret
= store
->time_log_trim(oid
, from_time
, end_time
, start_marker
, end_marker
);
223 if (ret
== -ENOENT
|| ret
== -ENODATA
)
229 int RGWMetadataLog::lock_exclusive(int shard_id
, timespan duration
, string
& zone_id
, string
& owner_id
) {
231 get_shard_oid(shard_id
, oid
);
233 return store
->lock_exclusive(store
->get_zone_params().log_pool
, oid
, duration
, zone_id
, owner_id
);
236 int RGWMetadataLog::unlock(int shard_id
, string
& zone_id
, string
& owner_id
) {
238 get_shard_oid(shard_id
, oid
);
240 return store
->unlock(store
->get_zone_params().log_pool
, oid
, zone_id
, owner_id
);
243 void RGWMetadataLog::mark_modified(int shard_id
)
246 if (modified_shards
.find(shard_id
) != modified_shards
.end()) {
252 RWLock::WLocker
wl(lock
);
253 modified_shards
.insert(shard_id
);
256 void RGWMetadataLog::read_clear_modified(set
<int> &modified
)
258 RWLock::WLocker
wl(lock
);
259 modified
.swap(modified_shards
);
260 modified_shards
.clear();
263 obj_version
& RGWMetadataObject::get_version()
268 class RGWMetadataTopHandler
: public RGWMetadataHandler
{
270 list
<string
> sections
;
271 list
<string
>::iterator iter
;
275 RGWMetadataTopHandler() {}
277 string
get_type() override
{ return string(); }
279 int get(RGWRados
*store
, string
& entry
, RGWMetadataObject
**obj
) override
{ return -ENOTSUP
; }
280 int put(RGWRados
*store
, string
& entry
, RGWObjVersionTracker
& objv_tracker
,
281 real_time mtime
, JSONObj
*obj
, sync_type_t sync_type
) override
{ return -ENOTSUP
; }
283 virtual void get_pool_and_oid(RGWRados
*store
, const string
& key
, rgw_pool
& pool
, string
& oid
) override
{}
285 int remove(RGWRados
*store
, string
& entry
, RGWObjVersionTracker
& objv_tracker
) override
{ return -ENOTSUP
; }
287 int list_keys_init(RGWRados
*store
, void **phandle
) override
{
288 iter_data
*data
= new iter_data
;
289 store
->meta_mgr
->get_sections(data
->sections
);
290 data
->iter
= data
->sections
.begin();
296 int list_keys_next(void *handle
, int max
, list
<string
>& keys
, bool *truncated
) override
{
297 iter_data
*data
= static_cast<iter_data
*>(handle
);
298 for (int i
= 0; i
< max
&& data
->iter
!= data
->sections
.end(); ++i
, ++(data
->iter
)) {
299 keys
.push_back(*data
->iter
);
302 *truncated
= (data
->iter
!= data
->sections
.end());
306 void list_keys_complete(void *handle
) override
{
307 iter_data
*data
= static_cast<iter_data
*>(handle
);
313 static RGWMetadataTopHandler md_top_handler
;
316 RGWMetadataManager::RGWMetadataManager(CephContext
*_cct
, RGWRados
*_store
)
317 : cct(_cct
), store(_store
)
321 RGWMetadataManager::~RGWMetadataManager()
323 map
<string
, RGWMetadataHandler
*>::iterator iter
;
325 for (iter
= handlers
.begin(); iter
!= handlers
.end(); ++iter
) {
332 const std::string
RGWMetadataLogHistory::oid
= "meta.history";
336 int read_history(RGWRados
*store
, RGWMetadataLogHistory
*state
,
337 RGWObjVersionTracker
*objv_tracker
)
339 RGWObjectCtx ctx
{store
};
340 auto& pool
= store
->get_zone_params().log_pool
;
341 const auto& oid
= RGWMetadataLogHistory::oid
;
343 int ret
= rgw_get_system_obj(store
, ctx
, pool
, oid
, bl
, objv_tracker
, nullptr);
350 } catch (buffer::error
& e
) {
351 ldout(store
->ctx(), 1) << "failed to decode the mdlog history: "
352 << e
.what() << dendl
;
358 int write_history(RGWRados
*store
, const RGWMetadataLogHistory
& state
,
359 RGWObjVersionTracker
*objv_tracker
, bool exclusive
= false)
364 auto& pool
= store
->get_zone_params().log_pool
;
365 const auto& oid
= RGWMetadataLogHistory::oid
;
366 return rgw_put_system_obj(store
, pool
, oid
, bl
.c_str(), bl
.length(),
367 exclusive
, objv_tracker
, real_time
{});
370 using Cursor
= RGWPeriodHistory::Cursor
;
372 /// read the mdlog history and use it to initialize the given cursor
373 class ReadHistoryCR
: public RGWCoroutine
{
376 RGWObjVersionTracker
*objv_tracker
;
377 RGWMetadataLogHistory state
;
379 ReadHistoryCR(RGWRados
*store
, Cursor
*cursor
,
380 RGWObjVersionTracker
*objv_tracker
)
381 : RGWCoroutine(store
->ctx()), store(store
), cursor(cursor
),
382 objv_tracker(objv_tracker
)
388 rgw_raw_obj obj
{store
->get_zone_params().log_pool
,
389 RGWMetadataLogHistory::oid
};
390 constexpr bool empty_on_enoent
= false;
392 using ReadCR
= RGWSimpleRadosReadCR
<RGWMetadataLogHistory
>;
393 call(new ReadCR(store
->get_async_rados(), store
, obj
,
394 &state
, empty_on_enoent
, objv_tracker
));
397 ldout(cct
, 1) << "failed to read mdlog history: "
398 << cpp_strerror(retcode
) << dendl
;
399 return set_cr_error(retcode
);
401 *cursor
= store
->period_history
->lookup(state
.oldest_realm_epoch
);
403 return set_cr_error(cursor
->get_error());
406 ldout(cct
, 10) << "read mdlog history with oldest period id="
407 << state
.oldest_period_id
<< " realm_epoch="
408 << state
.oldest_realm_epoch
<< dendl
;
409 return set_cr_done();
415 /// write the given cursor to the mdlog history
416 class WriteHistoryCR
: public RGWCoroutine
{
419 RGWObjVersionTracker
*objv
;
420 RGWMetadataLogHistory state
;
422 WriteHistoryCR(RGWRados
*store
, const Cursor
& cursor
,
423 RGWObjVersionTracker
*objv
)
424 : RGWCoroutine(store
->ctx()), store(store
), cursor(cursor
), objv(objv
)
429 state
.oldest_period_id
= cursor
.get_period().get_id();
430 state
.oldest_realm_epoch
= cursor
.get_epoch();
433 rgw_raw_obj obj
{store
->get_zone_params().log_pool
,
434 RGWMetadataLogHistory::oid
};
436 using WriteCR
= RGWSimpleRadosWriteCR
<RGWMetadataLogHistory
>;
437 call(new WriteCR(store
->get_async_rados(), store
, obj
, state
, objv
));
440 ldout(cct
, 1) << "failed to write mdlog history: "
441 << cpp_strerror(retcode
) << dendl
;
442 return set_cr_error(retcode
);
445 ldout(cct
, 10) << "wrote mdlog history with oldest period id="
446 << state
.oldest_period_id
<< " realm_epoch="
447 << state
.oldest_realm_epoch
<< dendl
;
448 return set_cr_done();
454 /// update the mdlog history to reflect trimmed logs
455 class TrimHistoryCR
: public RGWCoroutine
{
457 const Cursor cursor
; //< cursor to trimmed period
458 RGWObjVersionTracker
*objv
; //< to prevent racing updates
459 Cursor next
; //< target cursor for oldest log period
460 Cursor existing
; //< existing cursor read from disk
463 TrimHistoryCR(RGWRados
*store
, Cursor cursor
, RGWObjVersionTracker
*objv
)
464 : RGWCoroutine(store
->ctx()),
465 store(store
), cursor(cursor
), objv(objv
), next(cursor
)
467 next
.next(); // advance past cursor
472 // read an existing history, and write the new history if it's newer
473 yield
call(new ReadHistoryCR(store
, &existing
, objv
));
475 return set_cr_error(retcode
);
477 // reject older trims with ECANCELED
478 if (cursor
.get_epoch() < existing
.get_epoch()) {
479 ldout(cct
, 4) << "found oldest log epoch=" << existing
.get_epoch()
480 << ", rejecting trim at epoch=" << cursor
.get_epoch() << dendl
;
481 return set_cr_error(-ECANCELED
);
483 // overwrite with updated history
484 yield
call(new WriteHistoryCR(store
, next
, objv
));
486 return set_cr_error(retcode
);
488 return set_cr_done();
494 // traverse all the way back to the beginning of the period history, and
495 // return a cursor to the first period in a fully attached history
496 Cursor
find_oldest_period(RGWRados
*store
)
498 auto cct
= store
->ctx();
499 auto cursor
= store
->period_history
->get_current();
502 // advance to the period's predecessor
503 if (!cursor
.has_prev()) {
504 auto& predecessor
= cursor
.get_period().get_predecessor();
505 if (predecessor
.empty()) {
506 // this is the first period, so our logs must start here
507 ldout(cct
, 10) << "find_oldest_period returning first "
508 "period " << cursor
.get_period().get_id() << dendl
;
511 // pull the predecessor and add it to our history
513 int r
= store
->period_puller
->pull(predecessor
, period
);
517 auto prev
= store
->period_history
->insert(std::move(period
));
521 ldout(cct
, 20) << "find_oldest_period advancing to "
522 "predecessor period " << predecessor
<< dendl
;
523 assert(cursor
.has_prev());
527 ldout(cct
, 10) << "find_oldest_period returning empty cursor" << dendl
;
531 } // anonymous namespace
533 Cursor
RGWMetadataManager::init_oldest_log_period()
535 // read the mdlog history
536 RGWMetadataLogHistory state
;
537 RGWObjVersionTracker objv
;
538 int ret
= read_history(store
, &state
, &objv
);
540 if (ret
== -ENOENT
) {
541 // initialize the mdlog history and write it
542 ldout(cct
, 10) << "initializing mdlog history" << dendl
;
543 auto cursor
= find_oldest_period(store
);
548 // write the initial history
549 state
.oldest_realm_epoch
= cursor
.get_epoch();
550 state
.oldest_period_id
= cursor
.get_period().get_id();
552 constexpr bool exclusive
= true; // don't overwrite
553 int ret
= write_history(store
, state
, &objv
, exclusive
);
554 if (ret
< 0 && ret
!= -EEXIST
) {
555 ldout(cct
, 1) << "failed to write mdlog history: "
556 << cpp_strerror(ret
) << dendl
;
560 } else if (ret
< 0) {
561 ldout(cct
, 1) << "failed to read mdlog history: "
562 << cpp_strerror(ret
) << dendl
;
566 // if it's already in the history, return it
567 auto cursor
= store
->period_history
->lookup(state
.oldest_realm_epoch
);
571 // pull the oldest period by id
573 ret
= store
->period_puller
->pull(state
.oldest_period_id
, period
);
575 ldout(cct
, 1) << "failed to read period id=" << state
.oldest_period_id
576 << " for mdlog history: " << cpp_strerror(ret
) << dendl
;
579 // verify its realm_epoch
580 if (period
.get_realm_epoch() != state
.oldest_realm_epoch
) {
581 ldout(cct
, 1) << "inconsistent mdlog history: read period id="
582 << period
.get_id() << " with realm_epoch=" << period
.get_realm_epoch()
583 << ", expected realm_epoch=" << state
.oldest_realm_epoch
<< dendl
;
584 return Cursor
{-EINVAL
};
586 // attach the period to our history
587 return store
->period_history
->attach(std::move(period
));
590 Cursor
RGWMetadataManager::read_oldest_log_period() const
592 RGWMetadataLogHistory state
;
593 int ret
= read_history(store
, &state
, nullptr);
595 ldout(store
->ctx(), 1) << "failed to read mdlog history: "
596 << cpp_strerror(ret
) << dendl
;
600 ldout(store
->ctx(), 10) << "read mdlog history with oldest period id="
601 << state
.oldest_period_id
<< " realm_epoch="
602 << state
.oldest_realm_epoch
<< dendl
;
604 return store
->period_history
->lookup(state
.oldest_realm_epoch
);
607 RGWCoroutine
* RGWMetadataManager::read_oldest_log_period_cr(Cursor
*period
,
608 RGWObjVersionTracker
*objv
) const
610 return new ReadHistoryCR(store
, period
, objv
);
613 RGWCoroutine
* RGWMetadataManager::trim_log_period_cr(Cursor period
,
614 RGWObjVersionTracker
*objv
) const
616 return new TrimHistoryCR(store
, period
, objv
);
619 int RGWMetadataManager::init(const std::string
& current_period
)
621 // open a log for the current period
622 current_log
= get_log(current_period
);
626 RGWMetadataLog
* RGWMetadataManager::get_log(const std::string
& period
)
628 // construct the period's log in place if it doesn't exist
629 auto insert
= md_logs
.emplace(std::piecewise_construct
,
630 std::forward_as_tuple(period
),
631 std::forward_as_tuple(cct
, store
, period
));
632 return &insert
.first
->second
;
635 int RGWMetadataManager::register_handler(RGWMetadataHandler
*handler
)
637 string type
= handler
->get_type();
639 if (handlers
.find(type
) != handlers
.end())
642 handlers
[type
] = handler
;
647 RGWMetadataHandler
*RGWMetadataManager::get_handler(const string
& type
)
649 map
<string
, RGWMetadataHandler
*>::iterator iter
= handlers
.find(type
);
650 if (iter
== handlers
.end())
656 void RGWMetadataManager::parse_metadata_key(const string
& metadata_key
, string
& type
, string
& entry
)
658 auto pos
= metadata_key
.find(':');
659 if (pos
== string::npos
) {
662 type
= metadata_key
.substr(0, pos
);
663 entry
= metadata_key
.substr(pos
+ 1);
667 int RGWMetadataManager::find_handler(const string
& metadata_key
, RGWMetadataHandler
**handler
, string
& entry
)
671 parse_metadata_key(metadata_key
, type
, entry
);
674 *handler
= &md_top_handler
;
678 map
<string
, RGWMetadataHandler
*>::iterator iter
= handlers
.find(type
);
679 if (iter
== handlers
.end())
682 *handler
= iter
->second
;
688 int RGWMetadataManager::get(string
& metadata_key
, Formatter
*f
)
690 RGWMetadataHandler
*handler
;
692 int ret
= find_handler(metadata_key
, &handler
, entry
);
697 RGWMetadataObject
*obj
;
699 ret
= handler
->get(store
, entry
, &obj
);
704 f
->open_object_section("metadata_info");
705 encode_json("key", metadata_key
, f
);
706 encode_json("ver", obj
->get_version(), f
);
707 real_time mtime
= obj
->get_mtime();
708 if (!real_clock::is_zero(mtime
)) {
710 encode_json("mtime", ut
, f
);
712 encode_json("data", *obj
, f
);
720 int RGWMetadataManager::put(string
& metadata_key
, bufferlist
& bl
,
721 RGWMetadataHandler::sync_type_t sync_type
,
722 obj_version
*existing_version
)
724 RGWMetadataHandler
*handler
;
727 int ret
= find_handler(metadata_key
, &handler
, entry
);
732 if (!parser
.parse(bl
.c_str(), bl
.length())) {
736 RGWObjVersionTracker objv_tracker
;
738 obj_version
*objv
= &objv_tracker
.write_version
;
743 JSONDecoder::decode_json("key", metadata_key
, &parser
);
744 JSONDecoder::decode_json("ver", *objv
, &parser
);
745 JSONDecoder::decode_json("mtime", mtime
, &parser
);
746 } catch (JSONDecoder::err
& e
) {
750 JSONObj
*jo
= parser
.find_obj("data");
755 ret
= handler
->put(store
, entry
, objv_tracker
, mtime
.to_real_time(), jo
, sync_type
);
756 if (existing_version
) {
757 *existing_version
= objv_tracker
.read_version
;
762 int RGWMetadataManager::remove(string
& metadata_key
)
764 RGWMetadataHandler
*handler
;
767 int ret
= find_handler(metadata_key
, &handler
, entry
);
771 RGWMetadataObject
*obj
;
773 ret
= handler
->get(store
, entry
, &obj
);
778 RGWObjVersionTracker objv_tracker
;
780 objv_tracker
.read_version
= obj
->get_version();
784 return handler
->remove(store
, entry
, objv_tracker
);
787 int RGWMetadataManager::lock_exclusive(string
& metadata_key
, timespan duration
, string
& owner_id
) {
788 RGWMetadataHandler
*handler
;
792 int ret
= find_handler(metadata_key
, &handler
, entry
);
799 handler
->get_pool_and_oid(store
, entry
, pool
, oid
);
801 return store
->lock_exclusive(pool
, oid
, duration
, zone_id
, owner_id
);
804 int RGWMetadataManager::unlock(string
& metadata_key
, string
& owner_id
) {
805 librados::IoCtx io_ctx
;
806 RGWMetadataHandler
*handler
;
810 int ret
= find_handler(metadata_key
, &handler
, entry
);
817 handler
->get_pool_and_oid(store
, entry
, pool
, oid
);
819 return store
->unlock(pool
, oid
, zone_id
, owner_id
);
822 struct list_keys_handle
{
824 RGWMetadataHandler
*handler
;
828 int RGWMetadataManager::list_keys_init(string
& section
, void **handle
)
831 RGWMetadataHandler
*handler
;
835 ret
= find_handler(section
, &handler
, entry
);
840 list_keys_handle
*h
= new list_keys_handle
;
841 h
->handler
= handler
;
842 ret
= handler
->list_keys_init(store
, &h
->handle
);
853 int RGWMetadataManager::list_keys_next(void *handle
, int max
, list
<string
>& keys
, bool *truncated
)
855 list_keys_handle
*h
= static_cast<list_keys_handle
*>(handle
);
857 RGWMetadataHandler
*handler
= h
->handler
;
859 return handler
->list_keys_next(h
->handle
, max
, keys
, truncated
);
863 void RGWMetadataManager::list_keys_complete(void *handle
)
865 list_keys_handle
*h
= static_cast<list_keys_handle
*>(handle
);
867 RGWMetadataHandler
*handler
= h
->handler
;
869 handler
->list_keys_complete(h
->handle
);
873 void RGWMetadataManager::dump_log_entry(cls_log_entry
& entry
, Formatter
*f
)
875 f
->open_object_section("entry");
876 f
->dump_string("id", entry
.id
);
877 f
->dump_string("section", entry
.section
);
878 f
->dump_string("name", entry
.name
);
879 entry
.timestamp
.gmtime_nsec(f
->dump_stream("timestamp"));
882 RGWMetadataLogData log_data
;
883 bufferlist::iterator iter
= entry
.data
.begin();
884 ::decode(log_data
, iter
);
886 encode_json("data", log_data
, f
);
887 } catch (buffer::error
& err
) {
888 lderr(cct
) << "failed to decode log entry: " << entry
.section
<< ":" << entry
.name
<< " ts=" << entry
.timestamp
<< dendl
;
893 void RGWMetadataManager::get_sections(list
<string
>& sections
)
895 for (map
<string
, RGWMetadataHandler
*>::iterator iter
= handlers
.begin(); iter
!= handlers
.end(); ++iter
) {
896 sections
.push_back(iter
->first
);
900 int RGWMetadataManager::pre_modify(RGWMetadataHandler
*handler
, string
& section
, const string
& key
,
901 RGWMetadataLogData
& log_data
, RGWObjVersionTracker
*objv_tracker
,
902 RGWMDLogStatus op_type
)
904 section
= handler
->get_type();
906 /* if write version has not been set, and there's a read version, set it so that we can
910 if (objv_tracker
->read_version
.ver
&& !objv_tracker
->write_version
.ver
) {
911 objv_tracker
->write_version
= objv_tracker
->read_version
;
912 objv_tracker
->write_version
.ver
++;
914 log_data
.read_version
= objv_tracker
->read_version
;
915 log_data
.write_version
= objv_tracker
->write_version
;
918 log_data
.status
= op_type
;
921 ::encode(log_data
, logbl
);
923 assert(current_log
); // must have called init()
924 int ret
= current_log
->add_entry(handler
, section
, key
, logbl
);
931 int RGWMetadataManager::post_modify(RGWMetadataHandler
*handler
, const string
& section
, const string
& key
, RGWMetadataLogData
& log_data
,
932 RGWObjVersionTracker
*objv_tracker
, int ret
)
935 log_data
.status
= MDLOG_STATUS_COMPLETE
;
937 log_data
.status
= MDLOG_STATUS_ABORT
;
940 ::encode(log_data
, logbl
);
942 assert(current_log
); // must have called init()
943 int r
= current_log
->add_entry(handler
, section
, key
, logbl
);
953 string
RGWMetadataManager::heap_oid(RGWMetadataHandler
*handler
, const string
& key
, const obj_version
& objv
)
955 char buf
[objv
.tag
.size() + 32];
956 snprintf(buf
, sizeof(buf
), "%s:%lld", objv
.tag
.c_str(), (long long)objv
.ver
);
957 return string(".meta:") + handler
->get_type() + ":" + key
+ ":" + buf
;
960 int RGWMetadataManager::store_in_heap(RGWMetadataHandler
*handler
, const string
& key
, bufferlist
& bl
,
961 RGWObjVersionTracker
*objv_tracker
, real_time mtime
,
962 map
<string
, bufferlist
> *pattrs
)
968 rgw_pool
heap_pool(store
->get_zone_params().metadata_heap
);
970 if (heap_pool
.empty()) {
974 RGWObjVersionTracker otracker
;
975 otracker
.write_version
= objv_tracker
->write_version
;
976 string oid
= heap_oid(handler
, key
, objv_tracker
->write_version
);
977 int ret
= rgw_put_system_obj(store
, heap_pool
, oid
,
978 bl
.c_str(), bl
.length(), false,
979 &otracker
, mtime
, pattrs
);
981 ldout(store
->ctx(), 0) << "ERROR: rgw_put_system_obj() oid=" << oid
<< ") returned ret=" << ret
<< dendl
;
988 int RGWMetadataManager::remove_from_heap(RGWMetadataHandler
*handler
, const string
& key
, RGWObjVersionTracker
*objv_tracker
)
994 rgw_pool
heap_pool(store
->get_zone_params().metadata_heap
);
996 if (heap_pool
.empty()) {
1000 string oid
= heap_oid(handler
, key
, objv_tracker
->write_version
);
1001 rgw_raw_obj
obj(heap_pool
, oid
);
1002 int ret
= store
->delete_system_obj(obj
);
1004 ldout(store
->ctx(), 0) << "ERROR: store->delete_system_obj()=" << oid
<< ") returned ret=" << ret
<< dendl
;
1011 int RGWMetadataManager::put_entry(RGWMetadataHandler
*handler
, const string
& key
, bufferlist
& bl
, bool exclusive
,
1012 RGWObjVersionTracker
*objv_tracker
, real_time mtime
, map
<string
, bufferlist
> *pattrs
)
1015 RGWMetadataLogData log_data
;
1016 int ret
= pre_modify(handler
, section
, key
, log_data
, objv_tracker
, MDLOG_STATUS_WRITE
);
1023 handler
->get_pool_and_oid(store
, key
, pool
, oid
);
1025 ret
= store_in_heap(handler
, key
, bl
, objv_tracker
, mtime
, pattrs
);
1027 ldout(store
->ctx(), 0) << "ERROR: " << __func__
<< ": store_in_heap() key=" << key
<< " returned ret=" << ret
<< dendl
;
1031 ret
= rgw_put_system_obj(store
, pool
, oid
,
1032 bl
.c_str(), bl
.length(), exclusive
,
1033 objv_tracker
, mtime
, pattrs
);
1036 int r
= remove_from_heap(handler
, key
, objv_tracker
);
1038 ldout(store
->ctx(), 0) << "ERROR: " << __func__
<< ": remove_from_heap() key=" << key
<< " returned ret=" << r
<< dendl
;
1042 /* cascading ret into post_modify() */
1044 ret
= post_modify(handler
, section
, key
, log_data
, objv_tracker
, ret
);
1051 int RGWMetadataManager::remove_entry(RGWMetadataHandler
*handler
, string
& key
, RGWObjVersionTracker
*objv_tracker
)
1054 RGWMetadataLogData log_data
;
1055 int ret
= pre_modify(handler
, section
, key
, log_data
, objv_tracker
, MDLOG_STATUS_REMOVE
);
1062 handler
->get_pool_and_oid(store
, key
, pool
, oid
);
1064 rgw_raw_obj
obj(pool
, oid
);
1066 ret
= store
->delete_system_obj(obj
, objv_tracker
);
1067 /* cascading ret into post_modify() */
1069 ret
= post_modify(handler
, section
, key
, log_data
, objv_tracker
, ret
);
1076 int RGWMetadataManager::get_log_shard_id(const string
& section
,
1077 const string
& key
, int *shard_id
)
1079 RGWMetadataHandler
*handler
= get_handler(section
);
1084 handler
->get_hash_key(section
, key
, hash_key
);
1085 *shard_id
= store
->key_to_shard_id(hash_key
, cct
->_conf
->rgw_md_log_max_shards
);