]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: master calculates minimum sync status of peers
authorCasey Bodley <cbodley@redhat.com>
Mon, 23 Jan 2017 20:39:19 +0000 (15:39 -0500)
committerCasey Bodley <cbodley@redhat.com>
Tue, 23 Jan 2018 16:24:54 +0000 (11:24 -0500)
Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit 00d7b7b664c49bd476c060152e2738031cc4ba05)

src/rgw/rgw_sync.cc

index 38eb721005d5589f0edb724955c205225332d7b7..24917baee133a4d120ea0c20053a50030895d9f7 100644 (file)
@@ -2312,6 +2312,56 @@ connection_map make_peer_connections(RGWRados *store,
   return connections;
 }
 
+/// return the marker that it's safe to trim up to
+const std::string& get_stable_marker(const rgw_meta_sync_marker& m)
+{
+  return m.state == m.FullSync ? m.next_step_marker : m.marker;
+}
+
+/// comparison operator for take_min_status()
+bool operator<(const rgw_meta_sync_marker& lhs, const rgw_meta_sync_marker& rhs)
+{
+  // sort by stable marker
+  return get_stable_marker(lhs) < get_stable_marker(rhs);
+}
+
+/// populate the status with the minimum stable marker of each shard for any
+/// peer whose realm_epoch matches the minimum realm_epoch in the input
+template <typename Iter>
+int take_min_status(CephContext *cct, Iter first, Iter last,
+                    rgw_meta_sync_status *status)
+{
+  if (first == last) {
+    return -EINVAL;
+  }
+  const size_t num_shards = cct->_conf->rgw_md_log_max_shards;
+
+  status->sync_info.realm_epoch = std::numeric_limits<epoch_t>::max();
+  for (auto p = first; p != last; ++p) {
+    // validate peer's shard count
+    if (p->sync_markers.size() != num_shards) {
+      ldout(cct, 1) << "take_min_status got peer status with "
+          << p->sync_markers.size() << " shards, expected "
+          << num_shards << dendl;
+      return -EINVAL;
+    }
+    if (p->sync_info.realm_epoch < status->sync_info.realm_epoch) {
+      // earlier epoch, take its entire status
+      *status = std::move(*p);
+    } else if (p->sync_info.realm_epoch == status->sync_info.realm_epoch) {
+      // same epoch, take any earlier markers
+      auto m = status->sync_markers.begin();
+      for (auto& shard : p->sync_markers) {
+        if (shard.second < m->second) {
+          m->second = std::move(shard.second);
+        }
+        ++m;
+      }
+    }
+  }
+  return 0;
+}
+
 struct TrimEnv {
   RGWRados *const store;
   RGWHTTPManager *const http;
@@ -2348,6 +2398,7 @@ struct MasterTrimEnv : public TrimEnv {
 
 class MetaMasterTrimCR : public RGWCoroutine {
   MasterTrimEnv& env;
+  rgw_meta_sync_status min_status; //< minimum sync status of all peers
   int ret{0};
 
  public:
@@ -2398,6 +2449,14 @@ int MetaMasterTrimCR::operate()
       drain_all();
       return set_cr_error(ret);
     }
+
+    // determine the minimum epoch and markers
+    ret = take_min_status(env.store->ctx(), env.peer_status.begin(),
+                          env.peer_status.end(), &min_status);
+    if (ret < 0) {
+      ldout(cct, 4) << "failed to calculate min sync status from peers" << dendl;
+      return set_cr_error(ret);
+    }
     return set_cr_done();
   }
   return 0;