From: Casey Bodley Date: Thu, 25 Feb 2016 15:40:09 +0000 (-0500) Subject: rgw: implement find_oldest_log_period for RGWMetadataManager X-Git-Tag: v10.1.0~222^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=1353fe514b7fa0296881b6ffa50ef9652280de57;p=ceph.git rgw: implement find_oldest_log_period for RGWMetadataManager Signed-off-by: Casey Bodley --- diff --git a/src/rgw/rgw_metadata.cc b/src/rgw/rgw_metadata.cc index 2f0d1e98174c..027781bb1e98 100644 --- a/src/rgw/rgw_metadata.cc +++ b/src/rgw/rgw_metadata.cc @@ -1,6 +1,7 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab +#include #include "common/ceph_json.h" #include "rgw_metadata.h" #include "rgw_coroutine.h" @@ -9,6 +10,9 @@ #include "rgw_rados.h" #include "rgw_tools.h" +#include "rgw_cr_rados.h" +#include "rgw_boost_asio_yield.h" + #define dout_subsys ceph_subsys_rgw void LogStatusDump::dump(Formatter *f) const { @@ -357,19 +361,126 @@ RGWMetadataManager::~RGWMetadataManager() handlers.clear(); } -static RGWPeriodHistory::Cursor find_oldest_log_period(RGWRados* store) +namespace { + +class FindAnyShardCR : public RGWCoroutine { + RGWRados *const store; + const RGWMetadataLog& mdlog; + const int num_shards; + int ret = 0; + public: + FindAnyShardCR(RGWRados *store, const RGWMetadataLog& mdlog, int num_shards) + : RGWCoroutine(store->ctx()), store(store), mdlog(mdlog), + num_shards(num_shards) {} + + int operate() { + reenter(this) { + // send stat requests for each shard in parallel + yield { + auto async_rados = store->get_async_rados(); + auto& pool = store->get_zone_params().log_pool; + auto oid = std::string{}; + + for (int i = 0; i < num_shards; i++) { + mdlog.get_shard_oid(i, oid); + auto obj = rgw_obj{pool, oid}; + spawn(new RGWStatObjCR(async_rados, store, obj), true); + } + } + drain_all(); + // if any shards were found, return success + while (collect_next(&ret)) { + if (ret == 0) { + // TODO: cancel instead of waiting for the rest + return set_cr_done(); + } + ret = 0; // collect_next() won't modify &ret unless it's a failure + } + // no shards found + set_retcode(-ENOENT); + return set_cr_error(-ENOENT); + } + return 0; + } +}; + +// return true if any log shards exist for the given period +int find_shards_for_period(RGWRados *store, const std::string& period_id) { - // TODO: search backwards through the period history for the first period with - // no log shard objects, and return its successor (some shards may be missing + auto cct = store->ctx(); + RGWMetadataLog mdlog(cct, store, period_id); + auto num_shards = cct->_conf->rgw_md_log_max_shards; + + using FindAnyShardCRRef = boost::intrusive_ptr; + auto cr = FindAnyShardCRRef{new FindAnyShardCR(store, mdlog, num_shards)}; + + RGWCoroutinesManager mgr(cct, nullptr); + int r = mgr.run(cr.get()); + if (r < 0) { + return r; + } + return cr->get_ret_status(); +} + +RGWPeriodHistory::Cursor find_oldest_log_period(RGWRados *store) +{ + // search backwards through the period history for the first period with no + // log shard objects, and return its successor (some shards may be missing // if they contain no metadata yet, so we need to check all shards) - return store->period_history->get_current(); + auto cursor = store->period_history->get_current(); + auto oldest_log = cursor; + + while (cursor) { + // search for an existing log shard object for this period + int r = find_shards_for_period(store, cursor.get_period().get_id()); + if (r == -ENOENT) { + ldout(store->ctx(), 10) << "find_oldest_log_period found no log shards " + "for period " << cursor.get_period().get_id() << "; returning " + "period " << oldest_log.get_period().get_id() << dendl; + return oldest_log; + } + if (r < 0) { + return RGWPeriodHistory::Cursor{r}; + } + oldest_log = cursor; + + // advance to the period's predecessor + if (!cursor.has_prev()) { + auto& predecessor = cursor.get_period().get_predecessor(); + if (predecessor.empty()) { + // this is the first period, so our logs must start here + ldout(store->ctx(), 10) << "find_oldest_log_period returning first " + "period " << cursor.get_period().get_id() << dendl; + return cursor; + } + // pull the predecessor and add it to our history + RGWPeriod period; + int r = store->period_puller->pull(predecessor, period); + if (r < 0) { + return RGWPeriodHistory::Cursor{r}; + } + auto prev = store->period_history->insert(std::move(period)); + if (!prev) { + return prev; + } + ldout(store->ctx(), 10) << "find_oldest_log_period advancing to " + "predecessor period " << predecessor << dendl; + assert(cursor.has_prev()); + } + cursor.prev(); + } + ldout(store->ctx(), 10) << "find_oldest_log_period returning empty cursor" << dendl; + return cursor; } +} // anonymous namespace + int RGWMetadataManager::init(const std::string& current_period) { - // find our oldest log so we can tell other zones where to start their sync - oldest_log_period = find_oldest_log_period(store); - + if (store->is_meta_master()) { + // find our oldest log so we can tell other zones where to start their sync + oldest_log_period = find_oldest_log_period(store); + } // open a log for the current period current_log = get_log(current_period); return 0; diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 58d44a506db4..820cd6770789 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -3680,10 +3680,10 @@ int RGWRados::init_complete() << cpp_strerror(-ret) << dendl; return ret; } - auto md_log = meta_mgr->get_log(current_period.get_id()); - meta_notifier = new RGWMetaNotifier(this, md_log); if (is_meta_master()) { + auto md_log = meta_mgr->get_log(current_period.get_id()); + meta_notifier = new RGWMetaNotifier(this, md_log); meta_notifier->start(); }