]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd_types: template pg_missing_t based on whether it tracks changes
authorSamuel Just <sjust@redhat.com>
Tue, 10 May 2016 19:12:30 +0000 (12:12 -0700)
committerSamuel Just <sjust@redhat.com>
Thu, 14 Jul 2016 14:48:13 +0000 (07:48 -0700)
We'll use the version with TrackChanges = true as the local missing
set so that we can transparently track changes.  Also introduce a
const interface so that PGBackend methods can abstract over the
difference.  Finally, switch around type declarations in users.

Signed-off-by: Samuel Just <sjust@redhat.com>
13 files changed:
src/osd/ECBackend.cc
src/osd/OSD.cc
src/osd/PG.cc
src/osd/PG.h
src/osd/PGBackend.h
src/osd/PGLog.cc
src/osd/PGLog.h
src/osd/ReplicatedPG.cc
src/osd/ReplicatedPG.h
src/osd/osd_types.cc
src/osd/osd_types.h
src/test/encoding/types.h
src/test/osd/types.cc

index cbdd675db099139b20d79c0c5cc07da99ba70da9..55046ffe6ceaa059775fb9958945079af20a646a 100644 (file)
@@ -1475,8 +1475,7 @@ int ECBackend::get_min_avail_to_read_shards(
           i != miter->second.end();
           ++i) {
        dout(10) << __func__ << ": checking missing_loc " << *i << dendl;
-       boost::optional<const pg_missing_t &> m =
-         get_parent()->maybe_get_shard_missing(*i);
+       auto m = get_parent()->maybe_get_shard_missing(*i);
        if (m) {
          assert(!(*m).is_missing(hoid));
        }
index 015e6beedf745179c48635a3eb3954d44cedce71..982f6895a1d437ce4e7d8a257d2451821e6099ef 100644 (file)
@@ -5702,9 +5702,9 @@ void OSD::do_command(Connection *con, ceph_tid_t tid, vector<string>& cmd, buffe
       pg->lock();
 
       fout << *pg << std::endl;
-      std::map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator mend =
+      std::map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator mend =
        pg->pg_log.get_missing().get_items().end();
-      std::map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator mi =
+      std::map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator mi =
        pg->pg_log.get_missing().get_items().begin();
       for (; mi != mend; ++mi) {
        fout << mi->first << " -> " << mi->second << std::endl;
index aa94b74c8f5dfbfc2f9169ac5e94c84085ed80a8..8378cdbbd9dbdbb0cf074c21e6d5c09f40f91f6b 100644 (file)
@@ -337,7 +337,7 @@ void PG::proc_replica_log(
   dout(10) << " peer osd." << from << " now " << oinfo << " " << omissing << dendl;
   might_have_unfound.insert(from);
 
-  for (map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator i =
+  for (map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator i =
         omissing.get_items().begin();
        i != omissing.get_items().end();
        ++i) {
@@ -503,7 +503,7 @@ void PG::MissingLoc::add_batch_sources_info(
 {
   dout(10) << __func__ << ": adding sources in batch " << sources.size() << dendl;
   unsigned loop = 0;
-  for (map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator i = needs_recovery_map.begin();
+  for (map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator i = needs_recovery_map.begin();
       i != needs_recovery_map.end();
       ++i) {
     if (handle && ++loop >= g_conf->osd_loop_before_reset_tphandle) {
@@ -525,7 +525,7 @@ bool PG::MissingLoc::add_source_info(
   bool found_missing = false;
   unsigned loop = 0;
   // found items?
-  for (map<hobject_t,pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator p = needs_recovery_map.begin();
+  for (map<hobject_t,pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator p = needs_recovery_map.begin();
        p != needs_recovery_map.end();
        ++p) {
     const hobject_t &soid(p->first);
@@ -581,7 +581,7 @@ bool PG::MissingLoc::add_source_info(
 
 void PG::discover_all_missing(map<int, map<spg_t,pg_query_t> > &query_map)
 {
-  const pg_missing_t &missing = pg_log.get_missing();
+  auto &missing = pg_log.get_missing();
   assert(have_unfound());
 
   dout(10) << __func__ << " "
@@ -642,7 +642,7 @@ bool PG::needs_recovery() const
 {
   assert(is_primary());
 
-  const pg_missing_t &missing = pg_log.get_missing();
+  auto &missing = pg_log.get_missing();
 
   if (missing.num_missing()) {
     dout(10) << __func__ << " primary has " << missing.num_missing()
@@ -1580,7 +1580,7 @@ void PG::activate(ObjectStore::Transaction& t,
       info.last_epoch_started = activation_epoch;
   }
 
-  const pg_missing_t &missing = pg_log.get_missing();
+  auto &missing = pg_log.get_missing();
 
   if (is_primary()) {
     last_update_ondisk = info.last_update;
index cc196430e38fb6691fbc6b7649647b3e5891a2f3..b1c661644169b062685c1dfa84448072e0845213 100644 (file)
@@ -321,7 +321,7 @@ public:
   ghobject_t    pgmeta_oid;
 
   class MissingLoc {
-    map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator> needs_recovery_map;
+    map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator> needs_recovery_map;
     map<hobject_t, set<pg_shard_t>, hobject_t::BitwiseComparator > missing_loc;
     set<pg_shard_t> missing_loc_sources;
     PG *pg;
@@ -341,7 +341,7 @@ public:
     bool needs_recovery(
       const hobject_t &hoid,
       eversion_t *v = 0) const {
-      map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator i =
+      map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator i =
        needs_recovery_map.find(hoid);
       if (i == needs_recovery_map.end())
        return false;
@@ -359,7 +359,7 @@ public:
       const set<pg_shard_t> &acting) const;
     uint64_t num_unfound() const {
       uint64_t ret = 0;
-      for (map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator i =
+      for (map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator i =
             needs_recovery_map.begin();
           i != needs_recovery_map.end();
           ++i) {
@@ -382,11 +382,11 @@ public:
       missing_loc[hoid].erase(location);
     }
     void add_active_missing(const pg_missing_t &missing) {
-      for (map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator i =
+      for (map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator i =
             missing.get_items().begin();
           i != missing.get_items().end();
           ++i) {
-       map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator j =
+       map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator j =
          needs_recovery_map.find(i->first);
        if (j == needs_recovery_map.end()) {
          needs_recovery_map.insert(*i);
@@ -397,7 +397,7 @@ public:
     }
 
     void add_missing(const hobject_t &hoid, eversion_t need, eversion_t have) {
-      needs_recovery_map[hoid] = pg_missing_t::item(need, have);
+      needs_recovery_map[hoid] = pg_missing_item(need, have);
     }
     void revise_need(const hobject_t &hoid, eversion_t need) {
       assert(needs_recovery(hoid));
@@ -439,7 +439,7 @@ public:
       const map<pg_shard_t, pg_missing_t> &pmissing,
       const map<pg_shard_t, pg_info_t> &pinfo) {
       recovered(hoid);
-      boost::optional<pg_missing_t::item> item;
+      boost::optional<pg_missing_item> item;
       auto miter = missing.get_items().find(hoid);
       if (miter != missing.get_items().end()) {
        item = miter->second;
@@ -483,7 +483,7 @@ public:
     const map<hobject_t, set<pg_shard_t>, hobject_t::BitwiseComparator> &get_missing_locs() const {
       return missing_loc;
     }
-    const map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator> &get_needs_recovery() const {
+    const map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator> &get_needs_recovery() const {
       return needs_recovery_map;
     }
   } missing_loc;
index 228db93a9263e4d83f44ea7b34a08fb42e0b4773..03a464990ae6da80b9211fa59f308973657275fb 100644 (file)
@@ -131,10 +131,10 @@ typedef ceph::shared_ptr<const OSDMap> OSDMapRef;
      virtual const map<hobject_t, set<pg_shard_t>, hobject_t::BitwiseComparator> &get_missing_loc_shards()
        const = 0;
 
-     virtual const pg_missing_t &get_local_missing() const = 0;
+     virtual const pg_missing_tracker_t &get_local_missing() const = 0;
      virtual const map<pg_shard_t, pg_missing_t> &get_shard_missing()
        const = 0;
-     virtual boost::optional<const pg_missing_t &> maybe_get_shard_missing(
+     virtual boost::optional<const pg_missing_const_i &> maybe_get_shard_missing(
        pg_shard_t peer) const {
        if (peer == primary_shard()) {
         return get_local_missing();
@@ -142,14 +142,14 @@ typedef ceph::shared_ptr<const OSDMap> OSDMapRef;
         map<pg_shard_t, pg_missing_t>::const_iterator i =
           get_shard_missing().find(peer);
         if (i == get_shard_missing().end()) {
-          return boost::optional<const pg_missing_t &>();
+          return boost::optional<const pg_missing_const_i &>();
         } else {
           return i->second;
         }
        }
      }
-     virtual const pg_missing_t &get_shard_missing(pg_shard_t peer) const {
-       boost::optional<const pg_missing_t &> m = maybe_get_shard_missing(peer);
+     virtual const pg_missing_const_i &get_shard_missing(pg_shard_t peer) const {
+       auto m = maybe_get_shard_missing(peer);
        assert(m);
        return *m;
      }
index 7338b9835559346938e3f4894ffec32779520de6..a439bb165c3c563f4bdd5ba188b9847a45484628 100644 (file)
@@ -216,7 +216,7 @@ void PGLog::proc_replica_log(
     we will send the peer enough log to arrive at the same state.
   */
 
-  for (map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator i = omissing.get_items().begin();
+  for (map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator i = omissing.get_items().begin();
        i != omissing.get_items().end();
        ++i) {
     dout(20) << " before missing " << i->first << " need " << i->second.need
@@ -394,7 +394,7 @@ void PGLog::merge_log(ObjectStore::Transaction& t,
   // The logs must overlap.
   assert(log.head >= olog.tail && olog.head >= log.tail);
 
-  for (map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator i = missing.get_items().begin();
+  for (map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator i = missing.get_items().begin();
        i != missing.get_items().end();
        ++i) {
     dout(20) << "pg_missing_t sobject: " << i->first << dendl;
index c2fbbd582b70acd5986c0f3435d3f35575201eb9..7f27517af52336e2e5365a722299dfe269857902 100644 (file)
@@ -426,7 +426,8 @@ protected:
   //////////////////// data members ////////////////////
 
   map<eversion_t, hobject_t> divergent_priors;
-  pg_missing_t     missing;
+
+  pg_missing_tracker_t missing;
   IndexedLog  log;
 
   eversion_t dirty_to;         ///< must clear/writeout all keys <= dirty_to
@@ -515,7 +516,7 @@ public:
 
   //////////////////// get or set missing ////////////////////
 
-  const pg_missing_t& get_missing() const { return missing; }
+  const pg_missing_tracker_t& get_missing() const { return missing; }
   void resort_missing(bool sort_bitwise) {
     missing.resort(sort_bitwise);
   }
index 478da38c622075a9986ff996407cdcfdba70dd25..930e534eecb95d4f177dfc136e6cced81365d54b 100644 (file)
@@ -803,9 +803,9 @@ int ReplicatedPG::do_command(
     }
     f->dump_int("num_missing", missing.num_missing());
     f->dump_int("num_unfound", get_num_unfound());
-    const map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator> &needs_recovery_map =
+    const map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator> &needs_recovery_map =
       missing_loc.get_needs_recovery();
-    map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator p =
+    map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator p =
       needs_recovery_map.upper_bound(offset);
     {
       f->open_array_section("objects");
@@ -962,7 +962,7 @@ void ReplicatedPG::do_pg_op(OpRequestRef op)
        // ensure sort order is correct
        pg_log.resort_missing(get_sort_bitwise());
 
-       map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator missing_iter =
+       map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator missing_iter =
          pg_log.get_missing().get_items().lower_bound(current);
        vector<hobject_t>::iterator ls_iter = sentries.begin();
        hobject_t _max = hobject_t::get_max();
@@ -1149,7 +1149,7 @@ void ReplicatedPG::do_pg_op(OpRequestRef op)
        // ensure sort order is correct
        pg_log.resort_missing(get_sort_bitwise());
 
-       map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator missing_iter =
+       map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator missing_iter =
          pg_log.get_missing().get_items().lower_bound(current);
        vector<hobject_t>::iterator ls_iter = sentries.begin();
        hobject_t _max = hobject_t::get_max();
@@ -9815,9 +9815,9 @@ void ReplicatedPG::mark_all_unfound_lost(
   list<pg_log_entry_t> log_entries;
 
   utime_t mtime = ceph_clock_now(cct);
-  map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator m =
+  map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator m =
     missing_loc.get_needs_recovery().begin();
-  map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator mend =
+  map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator mend =
     missing_loc.get_needs_recovery().end();
 
   ObcLockManager manager;
@@ -10551,7 +10551,7 @@ uint64_t ReplicatedPG::recover_primary(uint64_t max, ThreadPool::TPHandle &handl
       latest = 0;
       soid = p->second;
     }
-    const pg_missing_t::item& item = missing.get_items().find(p->second)->second;
+    const pg_missing_item& item = missing.get_items().find(p->second)->second;
     ++p;
 
     hobject_t head = soid;
@@ -10805,7 +10805,7 @@ uint64_t ReplicatedPG::recover_replicas(uint64_t max, ThreadPool::TPHandle &hand
       }
 
       dout(10) << __func__ << ": recover_object_replicas(" << soid << ")" << dendl;
-      map<hobject_t,pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator r = m.get_items().find(soid);
+      map<hobject_t,pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator r = m.get_items().find(soid);
       started += prep_object_replica_pushes(soid, r->second.need,
                                            h);
     }
index faf85ffb2176c113f337cc1eff8cf845d4bdd6ad..3fe75339b54be9a1e001d768e16d55f48dc86ec8 100644 (file)
@@ -352,7 +352,7 @@ public:
     return peer_info;
   }
   using PGBackend::Listener::get_shard_info;  
-  const pg_missing_t &get_local_missing() const {
+  const pg_missing_tracker_t &get_local_missing() const {
     return pg_log.get_missing();
   }
   const PGLog &get_log() const {
index 8cb98af1fff9bedd59ee8dfaa55b60f4e0982b56..79c5db829e9a41246fe49ee8edd7a39b3abaafe7 100644 (file)
@@ -3763,77 +3763,9 @@ ostream& pg_log_t::print(ostream& out) const
   return out;
 }
 
-
 // -- pg_missing_t --
 
-void pg_missing_t::resort(bool sort_bitwise)
-{
-  if (missing.key_comp().bitwise != sort_bitwise) {
-    map<hobject_t, item, hobject_t::ComparatorWithDefault> tmp;
-    tmp.swap(missing);
-    missing = map<hobject_t, item, hobject_t::ComparatorWithDefault>(
-      hobject_t::ComparatorWithDefault(sort_bitwise));
-    missing.insert(tmp.begin(), tmp.end());
-  }
-}
-
-void pg_missing_t::encode(bufferlist &bl) const
-{
-  ENCODE_START(3, 2, bl);
-  ::encode(missing, bl);
-  ENCODE_FINISH(bl);
-}
-
-void pg_missing_t::decode(bufferlist::iterator &bl, int64_t pool)
-{
-  DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, bl);
-  ::decode(missing, bl);
-  DECODE_FINISH(bl);
-
-  if (struct_v < 3) {
-    // Handle hobject_t upgrade
-    map<hobject_t, item, hobject_t::ComparatorWithDefault> tmp;
-    for (map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator i = missing.begin();
-        i != missing.end();
-      ) {
-      if (!i->first.is_max() && i->first.pool == -1) {
-       hobject_t to_insert(i->first);
-       to_insert.pool = pool;
-       tmp[to_insert] = i->second;
-       missing.erase(i++);
-      } else {
-       ++i;
-      }
-    }
-    missing.insert(tmp.begin(), tmp.end());
-  }
-
-  for (map<hobject_t,item, hobject_t::ComparatorWithDefault>::iterator it = missing.begin();
-       it != missing.end();
-       ++it)
-    rmissing[it->second.need.version] = it->first;
-}
-
-void pg_missing_t::dump(Formatter *f) const
-{
-  f->open_array_section("missing");
-  for (map<hobject_t,item, hobject_t::ComparatorWithDefault>::const_iterator p = missing.begin(); p != missing.end(); ++p) {
-    f->open_object_section("item");
-    f->dump_stream("object") << p->first;
-    p->second.dump(f);
-    f->close_section();
-  }
-  f->close_section();
-}
-
-void pg_missing_t::generate_test_instances(list<pg_missing_t*>& o)
-{
-  o.push_back(new pg_missing_t);
-  o.push_back(new pg_missing_t);
-  o.back()->add(hobject_t(object_t("foo"), "foo", 123, 456, 0, ""), eversion_t(5, 6), eversion_t(5, 1));
-}
-
-ostream& operator<<(ostream& out, const pg_missing_t::item& i) 
+ostream& operator<<(ostream& out, const pg_missing_item& i)
 {
   out << i.need;
   if (i.have != eversion_t())
@@ -3841,160 +3773,6 @@ ostream& operator<<(ostream& out, const pg_missing_t::item& i)
   return out;
 }
 
-ostream& operator<<(ostream& out, const pg_missing_t& missing) 
-{
-  out << "missing(" << missing.num_missing();
-  //if (missing.num_lost()) out << ", " << missing.num_lost() << " lost";
-  out << ")";
-  return out;
-}
-
-
-unsigned int pg_missing_t::num_missing() const
-{
-  return missing.size();
-}
-
-bool pg_missing_t::have_missing() const
-{
-  return !missing.empty();
-}
-
-void pg_missing_t::swap(pg_missing_t& o)
-{
-  missing.swap(o.missing);
-  rmissing.swap(o.rmissing);
-}
-
-bool pg_missing_t::is_missing(const hobject_t& oid) const
-{
-  return (missing.find(oid) != missing.end());
-}
-
-bool pg_missing_t::is_missing(const hobject_t& oid, eversion_t v) const
-{
-  map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m = missing.find(oid);
-  if (m == missing.end())
-    return false;
-  const pg_missing_t::item &item(m->second);
-  if (item.need > v)
-    return false;
-  return true;
-}
-
-eversion_t pg_missing_t::have_old(const hobject_t& oid) const
-{
-  map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m = missing.find(oid);
-  if (m == missing.end())
-    return eversion_t();
-  const pg_missing_t::item &item(m->second);
-  return item.have;
-}
-
-/*
- * this needs to be called in log order as we extend the log.  it
- * assumes missing is accurate up through the previous log entry.
- */
-void pg_missing_t::add_next_event(const pg_log_entry_t& e)
-{
-  if (e.is_update()) {
-    map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator missing_it;
-    missing_it = missing.find(e.soid);
-    bool is_missing_divergent_item = missing_it != missing.end();
-    if (e.prior_version == eversion_t() || e.is_clone()) {
-      // new object.
-      if (is_missing_divergent_item) {  // use iterator
-        rmissing.erase((missing_it->second).need.version);
-        missing_it->second = item(e.version, eversion_t());  // .have = nil
-      } else  // create new element in missing map
-        missing[e.soid] = item(e.version, eversion_t());     // .have = nil
-    } else if (is_missing_divergent_item) {
-      // already missing (prior).
-      rmissing.erase((missing_it->second).need.version);
-      (missing_it->second).need = e.version;  // leave .have unchanged.
-    } else if (e.is_backlog()) {
-      // May not have prior version
-      assert(0 == "these don't exist anymore");
-    } else {
-      // not missing, we must have prior_version (if any)
-      assert(!is_missing_divergent_item);
-      missing[e.soid] = item(e.version, e.prior_version);
-    }
-    rmissing[e.version.version] = e.soid;
-  } else if (e.is_delete()) {
-    rm(e.soid, e.version);
-  }
-}
-
-void pg_missing_t::revise_need(hobject_t oid, eversion_t need)
-{
-  if (missing.count(oid)) {
-    rmissing.erase(missing[oid].need.version);
-    missing[oid].need = need;            // no not adjust .have
-  } else {
-    missing[oid] = item(need, eversion_t());
-  }
-  rmissing[need.version] = oid;
-}
-
-void pg_missing_t::revise_have(hobject_t oid, eversion_t have)
-{
-  if (missing.count(oid)) {
-    missing[oid].have = have;
-  }
-}
-
-void pg_missing_t::add(const hobject_t& oid, eversion_t need, eversion_t have)
-{
-  missing[oid] = item(need, have);
-  rmissing[need.version] = oid;
-}
-
-void pg_missing_t::rm(const hobject_t& oid, eversion_t v)
-{
-  std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::iterator p = missing.find(oid);
-  if (p != missing.end() && p->second.need <= v)
-    rm(p);
-}
-
-void pg_missing_t::rm(std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator m)
-{
-  rmissing.erase(m->second.need.version);
-  missing.erase(m);
-}
-
-void pg_missing_t::got(const hobject_t& oid, eversion_t v)
-{
-  std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::iterator p = missing.find(oid);
-  assert(p != missing.end());
-  assert(p->second.need <= v);
-  got(p);
-}
-
-void pg_missing_t::got(std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::iterator m)
-{
-  rmissing.erase(m->second.need.version);
-  missing.erase(m);
-}
-
-void pg_missing_t::split_into(
-  pg_t child_pgid,
-  unsigned split_bits,
-  pg_missing_t *omissing)
-{
-  unsigned mask = ~((~0)<<split_bits);
-  for (map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator i = missing.begin();
-       i != missing.end();
-       ) {
-    if ((i->first.get_hash() & mask) == child_pgid.m_seed) {
-      omissing->add(i->first, i->second.need, i->second.have);
-      rm(i++);
-    } else {
-      ++i;
-    }
-  }
-}
-
 // -- object_copy_cursor_t --
 
 void object_copy_cursor_t::encode(bufferlist& bl) const
index 169ee2390a1473b1106f4acf39afa26196835f0c..ddc133a90c7b4d5f47e23c419925aa30dc9459f2 100644 (file)
@@ -2744,80 +2744,360 @@ inline ostream& operator<<(ostream& out, const pg_log_t& log)
  *  kept in memory, as a supplement to pg_log_t
  *  also used to pass missing info in messages.
  */
-class pg_missing_t {
+struct pg_missing_item {
+  eversion_t need, have;
+  pg_missing_item() {}
+  explicit pg_missing_item(eversion_t n) : need(n) {}  // have no old version
+  pg_missing_item(eversion_t n, eversion_t h) : need(n), have(h) {}
+
+  void encode(bufferlist& bl) const {
+    ::encode(need, bl);
+    ::encode(have, bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    ::decode(need, bl);
+    ::decode(have, bl);
+  }
+  void dump(Formatter *f) const {
+    f->dump_stream("need") << need;
+    f->dump_stream("have") << have;
+  }
+  static void generate_test_instances(list<pg_missing_item*>& o) {
+    o.push_back(new pg_missing_item);
+    o.push_back(new pg_missing_item);
+    o.back()->need = eversion_t(1, 2);
+    o.back()->have = eversion_t(1, 1);
+  }
+  bool operator==(const pg_missing_item &rhs) const {
+    return need == rhs.need && have == rhs.have;
+  }
+  bool operator!=(const pg_missing_item &rhs) const {
+    return !(*this == rhs);
+  }
+};
+WRITE_CLASS_ENCODER(pg_missing_item)
+ostream& operator<<(ostream& out, const pg_missing_item &item);
+
+class pg_missing_const_i {
 public:
-  struct item {
-    eversion_t need, have;
-    item() {}
-    explicit item(eversion_t n) : need(n) {}  // have no old version
-    item(eversion_t n, eversion_t h) : need(n), have(h) {}
-
-    void encode(bufferlist& bl) const {
-      ::encode(need, bl);
-      ::encode(have, bl);
-    }
-    void decode(bufferlist::iterator& bl) {
-      ::decode(need, bl);
-      ::decode(have, bl);
-    }
-    void dump(Formatter *f) const {
-      f->dump_stream("need") << need;
-      f->dump_stream("have") << have;
-    }
-    static void generate_test_instances(list<item*>& o) {
-      o.push_back(new item);
-      o.push_back(new item);
-      o.back()->need = eversion_t(1, 2);
-      o.back()->have = eversion_t(1, 1);
+  virtual const map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault> &
+    get_items() const = 0;
+  virtual const map<version_t, hobject_t> &get_rmissing() const = 0;
+  virtual unsigned int num_missing() const = 0;
+  virtual bool have_missing() const = 0;
+  virtual bool is_missing(const hobject_t& oid) const = 0;
+  virtual bool is_missing(const hobject_t& oid, eversion_t v) const = 0;
+  virtual eversion_t have_old(const hobject_t& oid) const = 0;
+  virtual ~pg_missing_const_i() {}
+};
+
+
+template <bool Track>
+class ChangeTracker {
+public:
+  void changed(const hobject_t &obj) {}
+  template <typename F>
+  void get_changed(F &&f) const {}
+  void flush() {}
+  void clean() {
+    return true;
+  }
+};
+template <>
+class ChangeTracker<true> {
+  set<hobject_t, hobject_t::BitwiseComparator> _changed;
+public:
+  void changed(const hobject_t &obj) {
+    _changed.insert(obj);
+  }
+  template <typename F>
+  void get_changed(F &&f) {
+    for (auto const &i: _changed) {
+      f(i);
     }
-  }; 
-  WRITE_CLASS_ENCODER(item)
+  }
+  void flush() {
+    _changed.clear();
+  }
+  bool clean() const {
+    return _changed.empty();
+  }
+};
 
-private:
+template <bool TrackChanges>
+class pg_missing_set : public pg_missing_const_i {
+  using item = pg_missing_item;
   map<hobject_t, item, hobject_t::ComparatorWithDefault> missing;  // oid -> (need v, have v)
   map<version_t, hobject_t> rmissing;  // v -> oid
+  ChangeTracker<TrackChanges> tracker;
 
 public:
-  const map<hobject_t, item, hobject_t::ComparatorWithDefault> &get_items() const {
+  pg_missing_set() = default;
+
+  template <typename missing_type>
+  pg_missing_set(const missing_type &m) :
+    missing(m.get_items()), rmissing(m.get_rmissing()) {
+    static_assert(
+      !TrackChanges,
+      "Cannot copy construct into tracker pg_missing object");
+  }
+
+  const map<hobject_t, item, hobject_t::ComparatorWithDefault> &get_items() const override {
     return missing;
   }
-  const map<version_t, hobject_t> &get_rmissing() const {
+  const map<version_t, hobject_t> &get_rmissing() const override {
     return rmissing;
   }
-  unsigned int num_missing() const;
-  bool have_missing() const;
-  bool is_missing(const hobject_t& oid) const;
-  bool is_missing(const hobject_t& oid, eversion_t v) const;
-  eversion_t have_old(const hobject_t& oid) const;
-
-  void swap(pg_missing_t& o);
-  void add_next_event(const pg_log_entry_t& e);
-  void revise_need(hobject_t oid, eversion_t need);
-  void revise_have(hobject_t oid, eversion_t have);
-  void add(const hobject_t& oid, eversion_t need, eversion_t have);
-  void rm(const hobject_t& oid, eversion_t v);
-  void rm(std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator m);
-  void got(const hobject_t& oid, eversion_t v);
-  void got(std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator m);
-  void split_into(pg_t child_pgid, unsigned split_bits, pg_missing_t *omissing);
+  unsigned int num_missing() const override {
+    return missing.size();
+  }
+  bool have_missing() const override {
+    return !missing.empty();
+  }
+  bool is_missing(const hobject_t& oid) const override {
+    return (missing.find(oid) != missing.end());
+  }
+  bool is_missing(const hobject_t& oid, eversion_t v) const override {
+    map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m =
+      missing.find(oid);
+    if (m == missing.end())
+      return false;
+    const item &item(m->second);
+    if (item.need > v)
+      return false;
+    return true;
+  }
+  eversion_t have_old(const hobject_t& oid) const override {
+    map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m =
+      missing.find(oid);
+    if (m == missing.end())
+      return eversion_t();
+    const item &item(m->second);
+    return item.have;
+  }
+
+  void swap(pg_missing_set& o) {
+    for (auto &&i: missing)
+      tracker.changed(i.first);
+    missing.swap(o.missing);
+    rmissing.swap(o.rmissing);
+    for (auto &&i: missing)
+      tracker.changed(i.first);
+  }
+
+  /*
+   * this needs to be called in log order as we extend the log.  it
+   * assumes missing is accurate up through the previous log entry.
+   */
+  void add_next_event(const pg_log_entry_t& e) {
+    if (e.is_update()) {
+      map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator missing_it;
+      missing_it = missing.find(e.soid);
+      bool is_missing_divergent_item = missing_it != missing.end();
+      if (e.prior_version == eversion_t() || e.is_clone()) {
+       // new object.
+       if (is_missing_divergent_item) {  // use iterator
+         rmissing.erase((missing_it->second).need.version);
+         missing_it->second = item(e.version, eversion_t());  // .have = nil
+       } else  // create new element in missing map
+         missing[e.soid] = item(e.version, eversion_t());     // .have = nil
+      } else if (is_missing_divergent_item) {
+       // already missing (prior).
+       rmissing.erase((missing_it->second).need.version);
+       (missing_it->second).need = e.version;  // leave .have unchanged.
+      } else if (e.is_backlog()) {
+       // May not have prior version
+       assert(0 == "these don't exist anymore");
+      } else {
+       // not missing, we must have prior_version (if any)
+       assert(!is_missing_divergent_item);
+       missing[e.soid] = item(e.version, e.prior_version);
+      }
+      rmissing[e.version.version] = e.soid;
+    } else if (e.is_delete()) {
+      rm(e.soid, e.version);
+    }
+
+    tracker.changed(e.soid);
+  }
+
+  void revise_need(hobject_t oid, eversion_t need) {
+    if (missing.count(oid)) {
+      rmissing.erase(missing[oid].need.version);
+      missing[oid].need = need;            // no not adjust .have
+    } else {
+      missing[oid] = item(need, eversion_t());
+    }
+    rmissing[need.version] = oid;
+
+    tracker.changed(oid);
+  }
+
+  void revise_have(hobject_t oid, eversion_t have) {
+    if (missing.count(oid)) {
+      tracker.changed(oid);
+      missing[oid].have = have;
+    }
+  }
+
+  void add(const hobject_t& oid, eversion_t need, eversion_t have) {
+    missing[oid] = item(need, have);
+    rmissing[need.version] = oid;
+    tracker.changed(oid);
+  }
+
+  void rm(const hobject_t& oid, eversion_t v) {
+    std::map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator p = missing.find(oid);
+    if (p != missing.end() && p->second.need <= v)
+      rm(p);
+  }
+
+  void rm(std::map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m) {
+    tracker.changed(m->first);
+    rmissing.erase(m->second.need.version);
+    missing.erase(m);
+  }
+
+  void got(const hobject_t& oid, eversion_t v) {
+    std::map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator p = missing.find(oid);
+    assert(p != missing.end());
+    assert(p->second.need <= v);
+    got(p);
+  }
+
+  void got(std::map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m) {
+    tracker.changed(m->first);
+    rmissing.erase(m->second.need.version);
+    missing.erase(m);
+  }
+
+  void split_into(
+    pg_t child_pgid,
+    unsigned split_bits,
+    pg_missing_set *omissing) {
+    unsigned mask = ~((~0)<<split_bits);
+    for (map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator i = missing.begin();
+        i != missing.end();
+      ) {
+      if ((i->first.get_hash() & mask) == child_pgid.m_seed) {
+       omissing->add(i->first, i->second.need, i->second.have);
+       rm(i++);
+      } else {
+       ++i;
+      }
+    }
+  }
 
   void clear() {
+    for (auto const &i: missing)
+      tracker.changed(i.first);
     missing.clear();
     rmissing.clear();
   }
 
-  void resort(bool sort_bitwise);
+  void resort(bool sort_bitwise) {
+    if (missing.key_comp().bitwise != sort_bitwise) {
+      map<hobject_t, item, hobject_t::ComparatorWithDefault> tmp;
+      tmp.swap(missing);
+      missing = map<hobject_t, item, hobject_t::ComparatorWithDefault>(
+       hobject_t::ComparatorWithDefault(sort_bitwise));
+      missing.insert(tmp.begin(), tmp.end());
+    }
+  }
 
-  void encode(bufferlist &bl) const;
-  void decode(bufferlist::iterator &bl, int64_t pool = -1);
-  void dump(Formatter *f) const;
-  static void generate_test_instances(list<pg_missing_t*>& o);
+  void encode(bufferlist &bl) const {
+    ENCODE_START(3, 2, bl);
+    ::encode(missing, bl);
+    ENCODE_FINISH(bl);
+  }
+  void decode(bufferlist::iterator &bl, int64_t pool = -1) {
+    for (auto const &i: missing)
+      tracker.changed(i.first);
+    DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, bl);
+    ::decode(missing, bl);
+    DECODE_FINISH(bl);
+
+    if (struct_v < 3) {
+      // Handle hobject_t upgrade
+      map<hobject_t, item, hobject_t::ComparatorWithDefault> tmp;
+      for (map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator i =
+            missing.begin();
+          i != missing.end();
+       ) {
+       if (!i->first.is_max() && i->first.pool == -1) {
+         hobject_t to_insert(i->first);
+         to_insert.pool = pool;
+         tmp[to_insert] = i->second;
+         missing.erase(i++);
+       } else {
+         ++i;
+       }
+      }
+      missing.insert(tmp.begin(), tmp.end());
+    }
+
+    for (map<hobject_t,item, hobject_t::ComparatorWithDefault>::iterator it =
+          missing.begin();
+        it != missing.end();
+        ++it)
+      rmissing[it->second.need.version] = it->first;
+    for (auto const &i: missing)
+      tracker.changed(i.first);
+  }
+  void dump(Formatter *f) const {
+    f->open_array_section("missing");
+    for (map<hobject_t,item, hobject_t::ComparatorWithDefault>::const_iterator p =
+          missing.begin(); p != missing.end(); ++p) {
+      f->open_object_section("item");
+      f->dump_stream("object") << p->first;
+      p->second.dump(f);
+      f->close_section();
+    }
+    f->close_section();
+  }
+  static void generate_test_instances(list<pg_missing_set*>& o) {
+    o.push_back(new pg_missing_set);
+    o.push_back(new pg_missing_set);
+    o.back()->add(
+      hobject_t(object_t("foo"), "foo", 123, 456, 0, ""),
+      eversion_t(5, 6), eversion_t(5, 1));
+  }
+  template <typename F>
+  std::enable_if<TrackChanges, void> get_changed (F &&f) const {
+    tracker.get_changed(f);
+  }
+  template <typename F>
+  std::enable_if<TrackChanges, void> flush() {
+    tracker.flush();
+  }
+  template <typename F>
+  std::enable_if<TrackChanges, bool> clean() const {
+    return tracker.clean();
+  }
 };
-WRITE_CLASS_ENCODER(pg_missing_t::item)
-WRITE_CLASS_ENCODER(pg_missing_t)
+template <bool TrackChanges>
+void encode(
+  const pg_missing_set<TrackChanges> &c, bufferlist &bl, uint64_t features=0) {
+  ENCODE_DUMP_PRE();
+  c.encode(bl);
+  ENCODE_DUMP_POST(cl);
+}
+template <bool TrackChanges>
+void decode(pg_missing_set<TrackChanges> &c, bufferlist::iterator &p) {
+  c.decode(p);
+}
+template <bool TrackChanges>
+ostream& operator<<(ostream& out, const pg_missing_set<TrackChanges> &missing)
+{
+  out << "missing(" << missing.num_missing();
+  //if (missing.num_lost()) out << ", " << missing.num_lost() << " lost";
+  out << ")";
+  return out;
+}
+
+using pg_missing_t = pg_missing_set<false>;
+using pg_missing_tracker_t = pg_missing_set<true>;
 
-ostream& operator<<(ostream& out, const pg_missing_t::item& i);
-ostream& operator<<(ostream& out, const pg_missing_t& missing);
 
 /**
  * pg list objects response format
index e39641111f09ed3491c6900c63b87429f24e68d9..921ac6b11b2d040b1ffae8c34aef581813c3db08 100644 (file)
@@ -70,7 +70,7 @@ TYPE(pg_interval_t)
 TYPE_FEATUREFUL(pg_query_t)
 TYPE(pg_log_entry_t)
 TYPE(pg_log_t)
-TYPE(pg_missing_t::item)
+TYPE(pg_missing_item)
 TYPE(pg_missing_t)
 TYPE(pg_ls_response_t)
 TYPE(pg_nls_response_t)
index 3d24d9823698390429f6e5c83867a6db7491c644..d4036a6db6965d77b3350b9cc38e739fca97c7bf 100644 (file)
@@ -1049,7 +1049,7 @@ TEST(pg_missing_t, rm)
     missing.rm(oid, eversion_t(epoch * 2,20));
     EXPECT_FALSE(missing.is_missing(oid));
   }
-  // void pg_missing_t::rm(const std::map<hobject_t, pg_missing_t::item>::iterator &m)
+  // void pg_missing_t::rm(const std::map<hobject_t, pg_missing_item>::iterator &m)
   {
     hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
     pg_missing_t missing;
@@ -1081,7 +1081,7 @@ TEST(pg_missing_t, got)
     missing.got(oid, eversion_t(epoch * 2,20));
     EXPECT_FALSE(missing.is_missing(oid));
   }
-  // void pg_missing_t::got(const std::map<hobject_t, pg_missing_t::item>::iterator &m)
+  // void pg_missing_t::got(const std::map<hobject_t, pg_missing_item>::iterator &m)
   {
     hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
     pg_missing_t missing;