From: Casey Bodley Date: Mon, 23 Jan 2017 20:37:18 +0000 (-0500) Subject: rgw: add MetaMasterTrimCR to query sync status from peers X-Git-Tag: v12.0.3~20^2~15 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8bb106720160e42ae6e04f5dffc6af03794009ab;p=ceph.git rgw: add MetaMasterTrimCR to query sync status from peers Signed-off-by: Casey Bodley --- diff --git a/src/rgw/rgw_sync.cc b/src/rgw/rgw_sync.cc index 83c63bd1f82a..3040ebba5373 100644 --- a/src/rgw/rgw_sync.cc +++ b/src/rgw/rgw_sync.cc @@ -2313,3 +2313,118 @@ int RGWCloneMetaLogCoroutine::state_store_mdlog_entries_complete() } +#undef dout_prefix +#define dout_prefix (*_dout << "meta trim: ") + +namespace { + +using Cursor = RGWPeriodHistory::Cursor; + +using connection_map = std::map>; + +/// construct a RGWRESTConn for each zone in the realm +template +connection_map make_peer_connections(RGWRados *store, + const Zonegroups& zonegroups) +{ + connection_map connections; + for (auto& g : zonegroups) { + for (auto& z : g.second.zones) { + std::unique_ptr conn{ + new RGWRESTConn(store->ctx(), store, z.first, z.second.endpoints)}; + connections.emplace(z.first, std::move(conn)); + } + } + return connections; +} + +struct TrimEnv { + RGWRados *const store; + RGWHTTPManager *const http; + int num_shards; + const std::string& zone; + Cursor current; //< cursor to current period + + TrimEnv(RGWRados *store, RGWHTTPManager *http, int num_shards) + : store(store), http(http), num_shards(num_shards), + zone(store->get_zone_params().get_id()), + current(store->period_history->get_current()) + {} +}; + +struct MasterTrimEnv : public TrimEnv { + connection_map connections; //< peer connections + std::vector peer_status; //< sync status for each peer + /// last trim marker for each shard, only applies to current period's mdlog + std::vector last_trim_markers; + + MasterTrimEnv(RGWRados *store, RGWHTTPManager *http, int num_shards) + : TrimEnv(store, http, num_shards), + last_trim_markers(num_shards) + { + auto& period = current.get_period(); + connections = make_peer_connections(store, period.get_map().zonegroups); + connections.erase(zone); + peer_status.resize(connections.size()); + } +}; + +} // anonymous namespace + + +class MetaMasterTrimCR : public RGWCoroutine { + MasterTrimEnv& env; + int ret{0}; + + public: + MetaMasterTrimCR(MasterTrimEnv& env) + : RGWCoroutine(env.store->ctx()), env(env) + {} + + int operate(); +}; + +int MetaMasterTrimCR::operate() +{ + reenter(this) { + // TODO: detect this and fail before we spawn the trim thread? + if (env.connections.empty()) { + ldout(cct, 4) << "no peers, exiting" << dendl; + return set_cr_done(); + } + + ldout(cct, 10) << "fetching sync status for zone " << env.zone << dendl; + yield { + // query mdlog sync status from peers + rgw_http_param_pair params[] = { + { "type", "metadata" }, + { "status", nullptr }, + { nullptr, nullptr } + }; + + auto p = env.peer_status.begin(); + for (auto& c : env.connections) { + ldout(cct, 20) << "query sync status from " << c.first << dendl; + using StatusCR = RGWReadRESTResourceCR; + auto conn = c.second.get(); + spawn(new StatusCR(cct, conn, env.http, "/admin/log/", params, &*p), + false); + ++p; + } + } + + // must get a successful reply from all peers to consider trimming + ret = 0; + while (ret == 0 && num_spawned()) { + yield wait_for_child(); + collect_next(&ret); + } + if (ret < 0) { + ldout(cct, 4) << "failed to fetch sync status from all peers" << dendl; + drain_all(); + return set_cr_error(ret); + } + return set_cr_done(); + } + return 0; +}