]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: rename test/test_osd_types.cc -> test/osd/types.cc
authorSage Weil <sage@inktank.com>
Mon, 20 Jan 2014 18:29:55 +0000 (10:29 -0800)
committerSage Weil <sage@inktank.com>
Sun, 16 Feb 2014 06:09:37 +0000 (22:09 -0800)
Signed-off-by: Sage Weil <sage@inktank.com>
src/test/Makefile.am
src/test/osd/types.cc [new file with mode: 0644]
src/test/test_osd_types.cc [deleted file]

index a5d47597d1c3df48dc3a84a598ca1d360ae56b8b..32a36e3426e654774db3db576c1685cdcfa5be22 100644 (file)
@@ -361,7 +361,7 @@ unittest_ceph_compatset_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 unittest_ceph_compatset_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 check_PROGRAMS += unittest_ceph_compatset
 
-unittest_osd_types_SOURCES = test/test_osd_types.cc
+unittest_osd_types_SOURCES = test/osd/types.cc
 unittest_osd_types_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_osd_types_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL) 
 check_PROGRAMS += unittest_osd_types
diff --git a/src/test/osd/types.cc b/src/test/osd/types.cc
new file mode 100644 (file)
index 0000000..d1e62b8
--- /dev/null
@@ -0,0 +1,1197 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2011 New Dream Network
+ * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#include "include/types.h"
+#include "osd/osd_types.h"
+#include "osd/OSDMap.h"
+#include "gtest/gtest.h"
+#include "common/Thread.h"
+
+#include <sstream>
+
+TEST(hobject, prefixes0)
+{
+  uint32_t mask = 0xE947FA20;
+  uint32_t bits = 12;
+  int64_t pool = 0;
+
+  set<string> prefixes_correct;
+  prefixes_correct.insert(string("0000000000000000.02A"));
+
+  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
+  ASSERT_EQ(prefixes_out, prefixes_correct);
+}
+
+TEST(hobject, prefixes1)
+{
+  uint32_t mask = 0x0000000F;
+  uint32_t bits = 6;
+  int64_t pool = 20;
+
+  set<string> prefixes_correct;
+  prefixes_correct.insert(string("0000000000000014.F0"));
+  prefixes_correct.insert(string("0000000000000014.F4"));
+  prefixes_correct.insert(string("0000000000000014.F8"));
+  prefixes_correct.insert(string("0000000000000014.FC"));
+
+  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
+  ASSERT_EQ(prefixes_out, prefixes_correct);
+}
+
+TEST(hobject, prefixes2)
+{
+  uint32_t mask = 0xDEADBEAF;
+  uint32_t bits = 25;
+  int64_t pool = 0;
+
+  set<string> prefixes_correct;
+  prefixes_correct.insert(string("0000000000000000.FAEBDA0"));
+  prefixes_correct.insert(string("0000000000000000.FAEBDA2"));
+  prefixes_correct.insert(string("0000000000000000.FAEBDA4"));
+  prefixes_correct.insert(string("0000000000000000.FAEBDA6"));
+  prefixes_correct.insert(string("0000000000000000.FAEBDA8"));
+  prefixes_correct.insert(string("0000000000000000.FAEBDAA"));
+  prefixes_correct.insert(string("0000000000000000.FAEBDAC"));
+  prefixes_correct.insert(string("0000000000000000.FAEBDAE"));
+
+  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
+  ASSERT_EQ(prefixes_out, prefixes_correct);
+}
+
+TEST(hobject, prefixes3)
+{
+  uint32_t mask = 0xE947FA20;
+  uint32_t bits = 32;
+  int64_t pool = 0x23;
+
+  set<string> prefixes_correct;
+  prefixes_correct.insert(string("0000000000000023.02AF749E"));
+
+  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
+  ASSERT_EQ(prefixes_out, prefixes_correct);
+}
+
+TEST(hobject, prefixes4)
+{
+  uint32_t mask = 0xE947FA20;
+  uint32_t bits = 0;
+  int64_t pool = 0x23;
+
+  set<string> prefixes_correct;
+  prefixes_correct.insert(string("0000000000000023."));
+
+  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
+  ASSERT_EQ(prefixes_out, prefixes_correct);
+}
+
+TEST(hobject, prefixes5)
+{
+  uint32_t mask = 0xDEADBEAF;
+  uint32_t bits = 1;
+  int64_t pool = 0x34AC5D00;
+
+  set<string> prefixes_correct;
+  prefixes_correct.insert(string("0000000034AC5D00.1"));
+  prefixes_correct.insert(string("0000000034AC5D00.3"));
+  prefixes_correct.insert(string("0000000034AC5D00.5"));
+  prefixes_correct.insert(string("0000000034AC5D00.7"));
+  prefixes_correct.insert(string("0000000034AC5D00.9"));
+  prefixes_correct.insert(string("0000000034AC5D00.B"));
+  prefixes_correct.insert(string("0000000034AC5D00.D"));
+  prefixes_correct.insert(string("0000000034AC5D00.F"));
+
+  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
+  ASSERT_EQ(prefixes_out, prefixes_correct);
+}
+
+TEST(pg_interval_t, check_new_interval)
+{
+  //
+  // Create a situation where osdmaps are the same so that
+  // each test case can diverge from it using minimal code.
+  //
+  int osd_id = 1;
+  epoch_t epoch = 40;
+  ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
+  osdmap->set_max_osd(10);
+  osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
+  osdmap->set_epoch(epoch);
+  ceph::shared_ptr<OSDMap> lastmap(new OSDMap());
+  lastmap->set_max_osd(10);
+  lastmap->set_state(osd_id, CEPH_OSD_EXISTS);
+  lastmap->set_epoch(epoch);
+  epoch_t same_interval_since = epoch;
+  epoch_t last_epoch_clean = same_interval_since;
+  int64_t pool_id = 200;
+  int pg_num = 4;
+  __u8 min_size = 2;
+  {
+    OSDMap::Incremental inc(epoch + 1);
+    inc.new_pools[pool_id].min_size = min_size;
+    inc.new_pools[pool_id].set_pg_num(pg_num);
+    inc.new_up_thru[osd_id] = epoch + 1;
+    osdmap->apply_incremental(inc);
+    lastmap->apply_incremental(inc);
+  }
+  vector<int> new_acting;
+  new_acting.push_back(osd_id);
+  new_acting.push_back(osd_id + 1);
+  vector<int> old_acting = new_acting;
+  vector<int> new_up;
+  new_up.push_back(osd_id);
+  vector<int> old_up = new_up;
+  pg_t pgid;
+  pgid.set_pool(pool_id);
+
+  //
+  // Do nothing if there are no modifications in
+  // acting, up or pool size and that the pool is not
+  // being split
+  //
+  {
+    map<epoch_t, pg_interval_t> past_intervals;
+
+    ASSERT_TRUE(past_intervals.empty());
+    ASSERT_FALSE(pg_interval_t::check_new_interval(old_acting,
+                                                  new_acting,
+                                                  old_up,
+                                                  new_up,
+                                                  same_interval_since,
+                                                  last_epoch_clean,
+                                                  osdmap,
+                                                  lastmap,
+                                                  pool_id,
+                                                  pgid,
+                                                  &past_intervals));
+    ASSERT_TRUE(past_intervals.empty());
+  }
+
+  //
+  // pool did not exist in the old osdmap
+  //
+  {
+    ceph::shared_ptr<OSDMap> lastmap(new OSDMap());
+    lastmap->set_max_osd(10);
+    lastmap->set_state(osd_id, CEPH_OSD_EXISTS);
+    lastmap->set_epoch(epoch);
+
+    map<epoch_t, pg_interval_t> past_intervals;
+
+    ASSERT_TRUE(past_intervals.empty());
+    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
+                                                 new_acting,
+                                                 old_up,
+                                                 new_up,
+                                                 same_interval_since,
+                                                 last_epoch_clean,
+                                                 osdmap,
+                                                 lastmap,
+                                                 pool_id,
+                                                 pgid,
+                                                 &past_intervals));
+    ASSERT_EQ((unsigned int)1, past_intervals.size());
+    ASSERT_EQ(same_interval_since, past_intervals[same_interval_since].first);
+    ASSERT_EQ(osdmap->get_epoch() - 1, past_intervals[same_interval_since].last);
+    ASSERT_EQ(osd_id, past_intervals[same_interval_since].acting[0]);
+    ASSERT_EQ(osd_id, past_intervals[same_interval_since].up[0]);
+  }
+
+  //
+  // The acting set has changed
+  //
+  {
+    vector<int> new_acting;
+    int new_primary = osd_id + 1;
+    new_acting.push_back(new_primary);
+
+    map<epoch_t, pg_interval_t> past_intervals;
+
+    ASSERT_TRUE(past_intervals.empty());
+    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
+                                                 new_acting,
+                                                 old_up,
+                                                 new_up,
+                                                 same_interval_since,
+                                                 last_epoch_clean,
+                                                 osdmap,
+                                                 lastmap,
+                                                 pool_id,
+                                                 pgid,
+                                                 &past_intervals));
+    ASSERT_EQ((unsigned int)1, past_intervals.size());
+    ASSERT_EQ(same_interval_since, past_intervals[same_interval_since].first);
+    ASSERT_EQ(osdmap->get_epoch() - 1, past_intervals[same_interval_since].last);
+    ASSERT_EQ(osd_id, past_intervals[same_interval_since].acting[0]);
+    ASSERT_EQ(osd_id, past_intervals[same_interval_since].up[0]);
+  }
+
+  //
+  // The up set has changed
+  //
+  {
+    vector<int> new_up;
+    int new_primary = osd_id + 1;
+    new_up.push_back(new_primary);
+
+    map<epoch_t, pg_interval_t> past_intervals;
+
+    ASSERT_TRUE(past_intervals.empty());
+    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
+                                                 new_acting,
+                                                 old_up,
+                                                 new_up,
+                                                 same_interval_since,
+                                                 last_epoch_clean,
+                                                 osdmap,
+                                                 lastmap,
+                                                 pool_id,
+                                                 pgid,
+                                                 &past_intervals));
+    ASSERT_EQ((unsigned int)1, past_intervals.size());
+    ASSERT_EQ(same_interval_since, past_intervals[same_interval_since].first);
+    ASSERT_EQ(osdmap->get_epoch() - 1, past_intervals[same_interval_since].last);
+    ASSERT_EQ(osd_id, past_intervals[same_interval_since].acting[0]);
+    ASSERT_EQ(osd_id, past_intervals[same_interval_since].up[0]);
+  }
+
+  //
+  // PG is splitting
+  //
+  {
+    ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
+    osdmap->set_max_osd(10);
+    osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
+    osdmap->set_epoch(epoch);
+    int new_pg_num = pg_num ^ 2;
+    OSDMap::Incremental inc(epoch + 1);
+    inc.new_pools[pool_id].min_size = min_size;
+    inc.new_pools[pool_id].set_pg_num(new_pg_num);
+    osdmap->apply_incremental(inc);
+
+    map<epoch_t, pg_interval_t> past_intervals;
+
+    ASSERT_TRUE(past_intervals.empty());
+    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
+                                                 new_acting,
+                                                 old_up,
+                                                 new_up,
+                                                 same_interval_since,
+                                                 last_epoch_clean,
+                                                 osdmap,
+                                                 lastmap,
+                                                 pool_id,
+                                                 pgid,
+                                                 &past_intervals));
+    ASSERT_EQ((unsigned int)1, past_intervals.size());
+    ASSERT_EQ(same_interval_since, past_intervals[same_interval_since].first);
+    ASSERT_EQ(osdmap->get_epoch() - 1, past_intervals[same_interval_since].last);
+    ASSERT_EQ(osd_id, past_intervals[same_interval_since].acting[0]);
+    ASSERT_EQ(osd_id, past_intervals[same_interval_since].up[0]);
+  }
+
+  //
+  // PG size has changed
+  //
+  {
+    ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
+    osdmap->set_max_osd(10);
+    osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
+    osdmap->set_epoch(epoch);
+    OSDMap::Incremental inc(epoch + 1);
+    __u8 new_min_size = min_size + 1;
+    inc.new_pools[pool_id].min_size = new_min_size;
+    inc.new_pools[pool_id].set_pg_num(pg_num);
+    osdmap->apply_incremental(inc);
+
+    map<epoch_t, pg_interval_t> past_intervals;
+
+    ASSERT_TRUE(past_intervals.empty());
+    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
+                                                 new_acting,
+                                                 old_up,
+                                                 new_up,
+                                                 same_interval_since,
+                                                 last_epoch_clean,
+                                                 osdmap,
+                                                 lastmap,
+                                                 pool_id,
+                                                 pgid,
+                                                 &past_intervals));
+    ASSERT_EQ((unsigned int)1, past_intervals.size());
+    ASSERT_EQ(same_interval_since, past_intervals[same_interval_since].first);
+    ASSERT_EQ(osdmap->get_epoch() - 1, past_intervals[same_interval_since].last);
+    ASSERT_EQ(osd_id, past_intervals[same_interval_since].acting[0]);
+    ASSERT_EQ(osd_id, past_intervals[same_interval_since].up[0]);
+  }
+
+  //
+  // The old acting set was empty : the previous interval could not
+  // have been rw
+  //
+  {
+    vector<int> old_acting;
+
+    map<epoch_t, pg_interval_t> past_intervals;
+
+    ostringstream out;
+
+    ASSERT_TRUE(past_intervals.empty());
+    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
+                                                 new_acting,
+                                                 old_up,
+                                                 new_up,
+                                                 same_interval_since,
+                                                 last_epoch_clean,
+                                                 osdmap,
+                                                 lastmap,
+                                                 pool_id,
+                                                 pgid,
+                                                 &past_intervals,
+                                                 &out));
+    ASSERT_EQ((unsigned int)1, past_intervals.size());
+    ASSERT_FALSE(past_intervals[same_interval_since].maybe_went_rw);
+    ASSERT_NE(string::npos, out.str().find("acting set is too small"));
+  }
+
+  //
+  // The old acting set did not have enough osd : it could
+  // not have been rw
+  //
+  {
+    vector<int> old_acting;
+    old_acting.push_back(osd_id);
+
+    //
+    // see http://tracker.ceph.com/issues/5780
+    // the size of the old acting set should be compared
+    // with the min_size of the old osdmap
+    //
+    // The new osdmap is created so that it triggers the
+    // bug.
+    //
+    ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
+    osdmap->set_max_osd(10);
+    osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
+    osdmap->set_epoch(epoch);
+    OSDMap::Incremental inc(epoch + 1);
+    __u8 new_min_size = old_acting.size();
+    inc.new_pools[pool_id].min_size = new_min_size;
+    inc.new_pools[pool_id].set_pg_num(pg_num);
+    osdmap->apply_incremental(inc);
+
+    ostringstream out;
+
+    map<epoch_t, pg_interval_t> past_intervals;
+
+    ASSERT_TRUE(past_intervals.empty());
+    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
+                                                 new_acting,
+                                                 old_up,
+                                                 new_up,
+                                                 same_interval_since,
+                                                 last_epoch_clean,
+                                                 osdmap,
+                                                 lastmap,
+                                                 pool_id,
+                                                 pgid,
+                                                 &past_intervals,
+                                                 &out));
+    ASSERT_EQ((unsigned int)1, past_intervals.size());
+    ASSERT_FALSE(past_intervals[same_interval_since].maybe_went_rw);
+    ASSERT_NE(string::npos, out.str().find("acting set is too small"));
+  }
+
+  //
+  // The acting set changes. The old acting set primary was up during the
+  // previous interval and may have been rw.
+  //
+  {
+    vector<int> new_acting;
+    new_acting.push_back(osd_id + 4);
+    new_acting.push_back(osd_id + 5);
+
+    ostringstream out;
+
+    map<epoch_t, pg_interval_t> past_intervals;
+
+    ASSERT_TRUE(past_intervals.empty());
+    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
+                                                 new_acting,
+                                                 old_up,
+                                                 new_up,
+                                                 same_interval_since,
+                                                 last_epoch_clean,
+                                                 osdmap,
+                                                 lastmap,
+                                                 pool_id,
+                                                 pgid,
+                                                 &past_intervals,
+                                                 &out));
+    ASSERT_EQ((unsigned int)1, past_intervals.size());
+    ASSERT_TRUE(past_intervals[same_interval_since].maybe_went_rw);
+    ASSERT_NE(string::npos, out.str().find("includes interval"));
+  }
+  //
+  // The acting set changes. The old acting set primary was not up
+  // during the old interval but last_epoch_clean is in the
+  // old interval and it may have been rw.
+  //
+  {
+    vector<int> new_acting;
+    new_acting.push_back(osd_id + 4);
+    new_acting.push_back(osd_id + 5);
+
+    ceph::shared_ptr<OSDMap> lastmap(new OSDMap());
+    lastmap->set_max_osd(10);
+    lastmap->set_state(osd_id, CEPH_OSD_EXISTS);
+    lastmap->set_epoch(epoch);
+    OSDMap::Incremental inc(epoch + 1);
+    inc.new_pools[pool_id].min_size = min_size;
+    inc.new_pools[pool_id].set_pg_num(pg_num);
+    inc.new_up_thru[osd_id] = epoch - 10;
+    lastmap->apply_incremental(inc);
+
+    ostringstream out;
+
+    map<epoch_t, pg_interval_t> past_intervals;
+
+    ASSERT_TRUE(past_intervals.empty());
+    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
+                                                 new_acting,
+                                                 old_up,
+                                                 new_up,
+                                                 same_interval_since,
+                                                 last_epoch_clean,
+                                                 osdmap,
+                                                 lastmap,
+                                                 pool_id,
+                                                 pgid,
+                                                 &past_intervals,
+                                                 &out));
+    ASSERT_EQ((unsigned int)1, past_intervals.size());
+    ASSERT_TRUE(past_intervals[same_interval_since].maybe_went_rw);
+    ASSERT_NE(string::npos, out.str().find("presumed to have been rw"));
+  }
+
+  //
+  // The acting set changes. The old acting set primary was not up
+  // during the old interval and last_epoch_clean is before the
+  // old interval : the previous interval could not possibly have
+  // been rw.
+  //
+  {
+    vector<int> new_acting;
+    new_acting.push_back(osd_id + 4);
+    new_acting.push_back(osd_id + 5);
+
+    epoch_t last_epoch_clean = epoch - 10;
+
+    ceph::shared_ptr<OSDMap> lastmap(new OSDMap());
+    lastmap->set_max_osd(10);
+    lastmap->set_state(osd_id, CEPH_OSD_EXISTS);
+    lastmap->set_epoch(epoch);
+    OSDMap::Incremental inc(epoch + 1);
+    inc.new_pools[pool_id].min_size = min_size;
+    inc.new_pools[pool_id].set_pg_num(pg_num);
+    inc.new_up_thru[osd_id] = last_epoch_clean;
+    lastmap->apply_incremental(inc);
+
+    ostringstream out;
+
+    map<epoch_t, pg_interval_t> past_intervals;
+
+    ASSERT_TRUE(past_intervals.empty());
+    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
+                                                 new_acting,
+                                                 old_up,
+                                                 new_up,
+                                                 same_interval_since,
+                                                 last_epoch_clean,
+                                                 osdmap,
+                                                 lastmap,
+                                                 pool_id,
+                                                 pgid,
+                                                 &past_intervals,
+                                                 &out));
+    ASSERT_EQ((unsigned int)1, past_intervals.size());
+    ASSERT_FALSE(past_intervals[same_interval_since].maybe_went_rw);
+    ASSERT_NE(string::npos, out.str().find("does not include interval"));
+  }
+}
+
+TEST(pg_t, split)
+{
+  pg_t pgid(0, 0, -1);
+  set<pg_t> s;
+  bool b;
+
+  s.clear();
+  b = pgid.is_split(1, 1, &s);
+  ASSERT_TRUE(!b);
+
+  s.clear();
+  b = pgid.is_split(2, 4, NULL);
+  ASSERT_TRUE(b);
+  b = pgid.is_split(2, 4, &s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(2, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(2, 8, &s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(3u, s.size());
+  ASSERT_TRUE(s.count(pg_t(2, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(4, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(6, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(3, 8, &s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(4, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(6, 8, NULL);
+  ASSERT_TRUE(!b);
+  b = pgid.is_split(6, 8, &s);
+  ASSERT_TRUE(!b);
+  ASSERT_EQ(0u, s.size());
+
+  pgid = pg_t(1, 0, -1);
+
+  s.clear();
+  b = pgid.is_split(2, 4, &s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(2, 6, &s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(2u, s.size());
+  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(2, 8, &s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(3u, s.size());
+  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(4, 8, &s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(3, 8, &s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(3u, s.size());
+  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(6, 8, &s);
+  ASSERT_TRUE(!b);
+  ASSERT_EQ(0u, s.size());
+
+  pgid = pg_t(3, 0, -1);
+
+  s.clear();
+  b = pgid.is_split(7, 8, &s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(7, 12, &s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(2u, s.size());
+  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(11, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(7, 11, &s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
+
+}
+
+TEST(pg_missing_t, constructor)
+{
+  pg_missing_t missing;
+  EXPECT_EQ((unsigned int)0, missing.num_missing());
+  EXPECT_FALSE(missing.have_missing());
+}
+
+TEST(pg_missing_t, have_missing)
+{
+  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+  pg_missing_t missing;
+  EXPECT_FALSE(missing.have_missing());
+  missing.add(oid, eversion_t(), eversion_t());
+  EXPECT_TRUE(missing.have_missing());
+}
+
+TEST(pg_missing_t, swap)
+{
+  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+  pg_missing_t missing;
+  EXPECT_FALSE(missing.have_missing());
+  missing.add(oid, eversion_t(), eversion_t());
+  EXPECT_TRUE(missing.have_missing());
+
+  pg_missing_t other;
+  EXPECT_FALSE(other.have_missing());
+
+  other.swap(missing);
+  EXPECT_FALSE(missing.have_missing());
+  EXPECT_TRUE(other.have_missing());
+}
+
+TEST(pg_missing_t, is_missing)
+{
+  // pg_missing_t::is_missing(const hobject_t& oid) const
+  {
+    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+    pg_missing_t missing;
+    EXPECT_FALSE(missing.is_missing(oid));
+    missing.add(oid, eversion_t(), eversion_t());
+    EXPECT_TRUE(missing.is_missing(oid));
+  }
+
+  // bool pg_missing_t::is_missing(const hobject_t& oid, eversion_t v) const
+  {
+    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+    pg_missing_t missing;
+    eversion_t need(10,5);
+    EXPECT_FALSE(missing.is_missing(oid, eversion_t()));
+    missing.add(oid, need, eversion_t());
+    EXPECT_TRUE(missing.is_missing(oid));
+    EXPECT_FALSE(missing.is_missing(oid, eversion_t()));
+    EXPECT_TRUE(missing.is_missing(oid, need));
+  }
+}
+
+TEST(pg_missing_t, have_old)
+{
+  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+  pg_missing_t missing;
+  EXPECT_EQ(eversion_t(), missing.have_old(oid));
+  missing.add(oid, eversion_t(), eversion_t());
+  EXPECT_EQ(eversion_t(), missing.have_old(oid));
+  eversion_t have(1,1);
+  missing.revise_have(oid, have);
+  EXPECT_EQ(have, missing.have_old(oid));
+}
+
+TEST(pg_missing_t, add_next_event)
+{
+  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+  hobject_t oid_other(object_t("other"), "key", 9123, 9456, 0, "");
+  eversion_t version(10,5);
+  eversion_t prior_version(3,4);
+  pg_log_entry_t sample_e(pg_log_entry_t::DELETE, oid, version, prior_version,
+                         0, osd_reqid_t(entity_name_t::CLIENT(777), 8, 999),
+                         utime_t(8,9));
+
+  // new object (MODIFY)
+  {
+    pg_missing_t missing;
+    pg_log_entry_t e = sample_e;
+
+    e.op = pg_log_entry_t::MODIFY;
+    e.prior_version = eversion_t();
+    EXPECT_TRUE(e.is_update());
+    EXPECT_FALSE(missing.is_missing(oid));
+    missing.add_next_event(e);
+    EXPECT_TRUE(missing.is_missing(oid));
+    EXPECT_EQ(eversion_t(), missing.missing[oid].have);
+    EXPECT_EQ(oid, missing.rmissing[e.version.version]);
+    EXPECT_EQ(1U, missing.num_missing());
+    EXPECT_EQ(1U, missing.rmissing.size());
+
+    // adding the same object replaces the previous one
+    missing.add_next_event(e);
+    EXPECT_TRUE(missing.is_missing(oid));
+    EXPECT_EQ(1U, missing.num_missing());
+    EXPECT_EQ(1U, missing.rmissing.size());
+  }
+
+  // new object (CLONE)
+  {
+    pg_missing_t missing;
+    pg_log_entry_t e = sample_e;
+
+    e.op = pg_log_entry_t::CLONE;
+    e.prior_version = eversion_t();
+    EXPECT_TRUE(e.is_clone());
+    EXPECT_FALSE(missing.is_missing(oid));
+    missing.add_next_event(e);
+    EXPECT_TRUE(missing.is_missing(oid));
+    EXPECT_EQ(eversion_t(), missing.missing[oid].have);
+    EXPECT_EQ(oid, missing.rmissing[e.version.version]);
+    EXPECT_EQ(1U, missing.num_missing());
+    EXPECT_EQ(1U, missing.rmissing.size());
+
+    // adding the same object replaces the previous one
+    missing.add_next_event(e);
+    EXPECT_TRUE(missing.is_missing(oid));
+    EXPECT_EQ(1U, missing.num_missing());
+    EXPECT_EQ(1U, missing.rmissing.size());
+  }
+
+  // existing object (MODIFY)
+  {
+    pg_missing_t missing;
+    pg_log_entry_t e = sample_e;
+
+    e.op = pg_log_entry_t::MODIFY;
+    e.prior_version = eversion_t();
+    EXPECT_TRUE(e.is_update());
+    EXPECT_FALSE(missing.is_missing(oid));
+    missing.add_next_event(e);
+    EXPECT_TRUE(missing.is_missing(oid));
+    EXPECT_EQ(eversion_t(), missing.missing[oid].have);
+    EXPECT_EQ(oid, missing.rmissing[e.version.version]);
+    EXPECT_EQ(1U, missing.num_missing());
+    EXPECT_EQ(1U, missing.rmissing.size());
+
+    // adding the same object with a different version
+    e.prior_version = prior_version;
+    missing.add_next_event(e);
+    EXPECT_EQ(eversion_t(), missing.missing[oid].have);
+    EXPECT_TRUE(missing.is_missing(oid));
+    EXPECT_EQ(1U, missing.num_missing());
+    EXPECT_EQ(1U, missing.rmissing.size());
+  }
+
+  // object with prior version (MODIFY)
+  {
+    pg_missing_t missing;
+    pg_log_entry_t e = sample_e;
+
+    e.op = pg_log_entry_t::MODIFY;
+    EXPECT_TRUE(e.is_update());
+    EXPECT_FALSE(missing.is_missing(oid));
+    missing.add_next_event(e);
+    EXPECT_TRUE(missing.is_missing(oid));
+    EXPECT_EQ(prior_version, missing.missing[oid].have);
+    EXPECT_EQ(version, missing.missing[oid].need);
+    EXPECT_EQ(oid, missing.rmissing[e.version.version]);
+    EXPECT_EQ(1U, missing.num_missing());
+    EXPECT_EQ(1U, missing.rmissing.size());
+  }
+
+  // obsolete (BACKLOG)
+  {
+    pg_missing_t missing;
+    pg_log_entry_t e = sample_e;
+
+    e.op = pg_log_entry_t::BACKLOG;
+    EXPECT_TRUE(e.is_backlog());
+    EXPECT_FALSE(missing.is_missing(oid));
+    EXPECT_THROW(missing.add_next_event(e), FailedAssertion);
+  }
+
+  // adding a DELETE matching an existing event
+  {
+    pg_missing_t missing;
+    pg_log_entry_t e = sample_e;
+
+    e.op = pg_log_entry_t::MODIFY;
+    EXPECT_TRUE(e.is_update());
+    EXPECT_FALSE(missing.is_missing(oid));
+    missing.add_next_event(e);
+    EXPECT_TRUE(missing.is_missing(oid));
+
+    e.op = pg_log_entry_t::DELETE;
+    EXPECT_TRUE(e.is_delete());
+    missing.add_next_event(e);
+    EXPECT_FALSE(missing.have_missing());
+  }
+}
+
+TEST(pg_missing_t, revise_need)
+{
+  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+  pg_missing_t missing;
+  // create a new entry
+  EXPECT_FALSE(missing.is_missing(oid));
+  eversion_t need(10,10);
+  missing.revise_need(oid, need);
+  EXPECT_TRUE(missing.is_missing(oid));
+  EXPECT_EQ(eversion_t(), missing.missing[oid].have);
+  EXPECT_EQ(need, missing.missing[oid].need);
+  // update an existing entry and preserve have
+  eversion_t have(1,1);
+  missing.revise_have(oid, have);
+  eversion_t new_need(10,12);
+  EXPECT_EQ(have, missing.missing[oid].have);
+  missing.revise_need(oid, new_need);
+  EXPECT_EQ(have, missing.missing[oid].have);
+  EXPECT_EQ(new_need, missing.missing[oid].need);
+}
+
+TEST(pg_missing_t, revise_have)
+{
+  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+  pg_missing_t missing;
+  // a non existing entry means noop
+  EXPECT_FALSE(missing.is_missing(oid));
+  eversion_t have(1,1);
+  missing.revise_have(oid, have);
+  EXPECT_FALSE(missing.is_missing(oid));
+  // update an existing entry
+  eversion_t need(10,12);
+  missing.add(oid, need, have);
+  EXPECT_TRUE(missing.is_missing(oid));
+  eversion_t new_have(2,2);
+  EXPECT_EQ(have, missing.missing[oid].have);
+  missing.revise_have(oid, new_have);
+  EXPECT_EQ(new_have, missing.missing[oid].have);
+  EXPECT_EQ(need, missing.missing[oid].need);
+}
+
+TEST(pg_missing_t, add)
+{
+  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+  pg_missing_t missing;
+  EXPECT_FALSE(missing.is_missing(oid));
+  eversion_t have(1,1);
+  eversion_t need(10,10);
+  missing.add(oid, need, have);
+  EXPECT_TRUE(missing.is_missing(oid));
+  EXPECT_EQ(have, missing.missing[oid].have);
+  EXPECT_EQ(need, missing.missing[oid].need);
+}
+
+TEST(pg_missing_t, rm)
+{
+  // void pg_missing_t::rm(const hobject_t& oid, eversion_t v)
+  {
+    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+    pg_missing_t missing;
+    EXPECT_FALSE(missing.is_missing(oid));
+    epoch_t epoch = 10;
+    eversion_t need(epoch,10);
+    missing.add(oid, need, eversion_t());
+    EXPECT_TRUE(missing.is_missing(oid));
+    // rm of an older version is a noop
+    missing.rm(oid, eversion_t(epoch / 2,20));
+    EXPECT_TRUE(missing.is_missing(oid));
+    // rm of a later version removes the object
+    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)
+  {
+    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+    pg_missing_t missing;
+    EXPECT_FALSE(missing.is_missing(oid));
+    missing.add(oid, eversion_t(), eversion_t());
+    EXPECT_TRUE(missing.is_missing(oid));
+    const std::map<hobject_t, pg_missing_t::item>::iterator m = missing.missing.find(oid);
+    missing.rm(m);
+    EXPECT_FALSE(missing.is_missing(oid));
+  }
+}
+
+TEST(pg_missing_t, got)
+{
+  // void pg_missing_t::got(const hobject_t& oid, eversion_t v)
+  {
+    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+    pg_missing_t missing;
+    // assert if the oid does not exist
+    EXPECT_THROW(missing.got(oid, eversion_t()), FailedAssertion);
+    EXPECT_FALSE(missing.is_missing(oid));
+    epoch_t epoch = 10;
+    eversion_t need(epoch,10);
+    missing.add(oid, need, eversion_t());
+    EXPECT_TRUE(missing.is_missing(oid));
+    // assert if that the version to be removed is lower than the version of the object
+    EXPECT_THROW(missing.got(oid, eversion_t(epoch / 2,20)), FailedAssertion);
+    // remove of a later version removes the object
+    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)
+  {
+    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
+    pg_missing_t missing;
+    EXPECT_FALSE(missing.is_missing(oid));
+    missing.add(oid, eversion_t(), eversion_t());
+    EXPECT_TRUE(missing.is_missing(oid));
+    const std::map<hobject_t, pg_missing_t::item>::iterator m = missing.missing.find(oid);
+    missing.got(m);
+    EXPECT_FALSE(missing.is_missing(oid));
+  }
+}
+
+TEST(pg_missing_t, split_into)
+{
+  uint32_t hash1 = 1;
+  hobject_t oid1(object_t("objname"), "key1", 123, hash1, 0, "");
+  uint32_t hash2 = 2;
+  hobject_t oid2(object_t("objname"), "key2", 123, hash2, 0, "");
+  pg_missing_t missing;
+  missing.add(oid1, eversion_t(), eversion_t());
+  missing.add(oid2, eversion_t(), eversion_t());
+  pg_t child_pgid;
+  child_pgid.m_seed = 1;
+  pg_missing_t child;
+  unsigned split_bits = 1;
+  missing.split_into(child_pgid, split_bits, &child);
+  EXPECT_TRUE(child.is_missing(oid1));
+  EXPECT_FALSE(child.is_missing(oid2));
+  EXPECT_FALSE(missing.is_missing(oid1));
+  EXPECT_TRUE(missing.is_missing(oid2));
+}
+
+class ObjectContextTest : public ::testing::Test {
+protected:
+
+  static const useconds_t DELAY_MAX = 20 * 1000 * 1000;
+
+  class Thread_read_lock : public Thread {
+  public:
+    ObjectContext &obc;
+
+    Thread_read_lock(ObjectContext& _obc) :
+      obc(_obc)
+    {
+    }
+
+    virtual void *entry() {
+      obc.ondisk_read_lock();
+      return NULL;
+    }
+  };
+
+  class Thread_write_lock : public Thread {
+  public:
+    ObjectContext &obc;
+
+    Thread_write_lock(ObjectContext& _obc) :
+      obc(_obc)
+    {
+    }
+
+    virtual void *entry() {
+      obc.ondisk_write_lock();
+      return NULL;
+    }
+  };
+
+};
+
+TEST_F(ObjectContextTest, read_write_lock)
+{
+  {
+    ObjectContext obc;
+
+    //
+    // write_lock
+    // write_lock
+    // write_unlock
+    // write_unlock
+    //
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(0, obc.unstable_writes);
+
+    obc.ondisk_write_lock();
+
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(1, obc.unstable_writes);
+
+    obc.ondisk_write_lock();
+
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(2, obc.unstable_writes);
+
+    obc.ondisk_write_unlock();
+
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(1, obc.unstable_writes);
+
+    obc.ondisk_write_unlock();
+
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(0, obc.unstable_writes);
+  }
+
+  useconds_t delay = 0;
+
+  {
+    ObjectContext obc;
+
+    //
+    // write_lock
+    // read_lock => wait
+    // write_unlock => signal
+    // read_unlock
+    //
+    EXPECT_EQ(0, obc.readers_waiting);
+    EXPECT_EQ(0, obc.readers);
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(0, obc.unstable_writes);
+
+    obc.ondisk_write_lock();
+
+    EXPECT_EQ(0, obc.readers_waiting);
+    EXPECT_EQ(0, obc.readers);
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(1, obc.unstable_writes);
+
+    Thread_read_lock t(obc);
+    t.create();
+
+    do {
+      cout << "Trying (1) with delay " << delay << "us\n";
+      usleep(delay);
+    } while (obc.readers_waiting == 0 &&
+            ( delay = delay * 2 + 1) < DELAY_MAX);
+
+    EXPECT_EQ(1, obc.readers_waiting);
+    EXPECT_EQ(0, obc.readers);
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(1, obc.unstable_writes);
+
+    obc.ondisk_write_unlock();
+
+    do {
+      cout << "Trying (2) with delay " << delay << "us\n";
+      usleep(delay);
+    } while ((obc.readers == 0 || obc.readers_waiting == 1) &&
+            ( delay = delay * 2 + 1) < DELAY_MAX);
+    EXPECT_EQ(0, obc.readers_waiting);
+    EXPECT_EQ(1, obc.readers);
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(0, obc.unstable_writes);
+
+    obc.ondisk_read_unlock();
+
+    EXPECT_EQ(0, obc.readers_waiting);
+    EXPECT_EQ(0, obc.readers);
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(0, obc.unstable_writes);
+
+    t.join();
+  }
+
+  {
+    ObjectContext obc;
+
+    //
+    // read_lock
+    // write_lock => wait
+    // read_unlock => signal
+    // write_unlock
+    //
+    EXPECT_EQ(0, obc.readers_waiting);
+    EXPECT_EQ(0, obc.readers);
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(0, obc.unstable_writes);
+
+    obc.ondisk_read_lock();
+
+    EXPECT_EQ(0, obc.readers_waiting);
+    EXPECT_EQ(1, obc.readers);
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(0, obc.unstable_writes);
+
+    Thread_write_lock t(obc);
+    t.create();
+
+    do {
+      cout << "Trying (3) with delay " << delay << "us\n";
+      usleep(delay);
+    } while ((obc.writers_waiting == 0) &&
+            ( delay = delay * 2 + 1) < DELAY_MAX);
+
+    EXPECT_EQ(0, obc.readers_waiting);
+    EXPECT_EQ(1, obc.readers);
+    EXPECT_EQ(1, obc.writers_waiting);
+    EXPECT_EQ(0, obc.unstable_writes);
+
+    obc.ondisk_read_unlock();
+
+    do {
+      cout << "Trying (4) with delay " << delay << "us\n";
+      usleep(delay);
+    } while ((obc.unstable_writes == 0 || obc.writers_waiting == 1) &&
+            ( delay = delay * 2 + 1) < DELAY_MAX);
+
+    EXPECT_EQ(0, obc.readers_waiting);
+    EXPECT_EQ(0, obc.readers);
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(1, obc.unstable_writes);
+
+    obc.ondisk_write_unlock();
+
+    EXPECT_EQ(0, obc.readers_waiting);
+    EXPECT_EQ(0, obc.readers);
+    EXPECT_EQ(0, obc.writers_waiting);
+    EXPECT_EQ(0, obc.unstable_writes);
+
+    t.join();
+  }
+
+}
+
+TEST(pg_pool_t_test, get_pg_num_divisor) {
+  pg_pool_t p;
+  p.set_pg_num(16);
+  p.set_pgp_num(16);
+
+  for (int i = 0; i < 16; ++i)
+    ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(i, 1)));
+
+  p.set_pg_num(12);
+  p.set_pgp_num(12);
+  //cout << "num " << p.get_pg_num()
+  //     << " mask " << p.get_pg_num_mask() << std::endl;
+  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(0, 1)));
+  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(1, 1)));
+  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(2, 1)));
+  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(3, 1)));
+  ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(4, 1)));
+  ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(5, 1)));
+  ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(6, 1)));
+  ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(7, 1)));
+  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(8, 1)));
+  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(9, 1)));
+  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(10, 1)));
+  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(11, 1)));
+}
+
+
+/*
+ * Local Variables:
+ * compile-command: "cd .. ;
+ *   make unittest_osd_types ;
+ *   ./unittest_osd_types # --gtest_filter=pg_missing_t.constructor
+ * "
+ * End:
+ */
diff --git a/src/test/test_osd_types.cc b/src/test/test_osd_types.cc
deleted file mode 100644 (file)
index ed87869..0000000
+++ /dev/null
@@ -1,1198 +0,0 @@
-// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2011 New Dream Network
- * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
- *
- * Author: Loic Dachary <loic@dachary.org>
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License version 2, as published by the Free Software
- * Foundation.  See file COPYING.
- *
- */
-
-#include "include/types.h"
-#include "osd/osd_types.h"
-#include "osd/OSDMap.h"
-#include "gtest/gtest.h"
-#include "common/Thread.h"
-
-#include <sstream>
-
-TEST(hobject, prefixes0)
-{
-  uint32_t mask = 0xE947FA20;
-  uint32_t bits = 12;
-  int64_t pool = 0;
-
-  set<string> prefixes_correct;
-  prefixes_correct.insert(string("0000000000000000.02A"));
-
-  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
-  ASSERT_EQ(prefixes_out, prefixes_correct);
-}
-
-TEST(hobject, prefixes1)
-{
-  uint32_t mask = 0x0000000F;
-  uint32_t bits = 6;
-  int64_t pool = 20;
-
-  set<string> prefixes_correct;
-  prefixes_correct.insert(string("0000000000000014.F0"));
-  prefixes_correct.insert(string("0000000000000014.F4"));
-  prefixes_correct.insert(string("0000000000000014.F8"));
-  prefixes_correct.insert(string("0000000000000014.FC"));
-
-  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
-  ASSERT_EQ(prefixes_out, prefixes_correct);
-}
-
-TEST(hobject, prefixes2)
-{
-  uint32_t mask = 0xDEADBEAF;
-  uint32_t bits = 25;
-  int64_t pool = 0;
-
-  set<string> prefixes_correct;
-  prefixes_correct.insert(string("0000000000000000.FAEBDA0"));
-  prefixes_correct.insert(string("0000000000000000.FAEBDA2"));
-  prefixes_correct.insert(string("0000000000000000.FAEBDA4"));
-  prefixes_correct.insert(string("0000000000000000.FAEBDA6"));
-  prefixes_correct.insert(string("0000000000000000.FAEBDA8"));
-  prefixes_correct.insert(string("0000000000000000.FAEBDAA"));
-  prefixes_correct.insert(string("0000000000000000.FAEBDAC"));
-  prefixes_correct.insert(string("0000000000000000.FAEBDAE"));
-
-  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
-  ASSERT_EQ(prefixes_out, prefixes_correct);
-}
-
-TEST(hobject, prefixes3)
-{
-  uint32_t mask = 0xE947FA20;
-  uint32_t bits = 32;
-  int64_t pool = 0x23;
-
-  set<string> prefixes_correct;
-  prefixes_correct.insert(string("0000000000000023.02AF749E"));
-
-  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
-  ASSERT_EQ(prefixes_out, prefixes_correct);
-}
-
-TEST(hobject, prefixes4)
-{
-  uint32_t mask = 0xE947FA20;
-  uint32_t bits = 0;
-  int64_t pool = 0x23;
-
-  set<string> prefixes_correct;
-  prefixes_correct.insert(string("0000000000000023."));
-
-  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
-  ASSERT_EQ(prefixes_out, prefixes_correct);
-}
-
-TEST(hobject, prefixes5)
-{
-  uint32_t mask = 0xDEADBEAF;
-  uint32_t bits = 1;
-  int64_t pool = 0x34AC5D00;
-
-  set<string> prefixes_correct;
-  prefixes_correct.insert(string("0000000034AC5D00.1"));
-  prefixes_correct.insert(string("0000000034AC5D00.3"));
-  prefixes_correct.insert(string("0000000034AC5D00.5"));
-  prefixes_correct.insert(string("0000000034AC5D00.7"));
-  prefixes_correct.insert(string("0000000034AC5D00.9"));
-  prefixes_correct.insert(string("0000000034AC5D00.B"));
-  prefixes_correct.insert(string("0000000034AC5D00.D"));
-  prefixes_correct.insert(string("0000000034AC5D00.F"));
-
-  set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
-  ASSERT_EQ(prefixes_out, prefixes_correct);
-}
-
-TEST(pg_interval_t, check_new_interval)
-{
-  //
-  // Create a situation where osdmaps are the same so that
-  // each test case can diverge from it using minimal code.
-  //
-  int osd_id = 1;
-  epoch_t epoch = 40;
-  ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
-  osdmap->set_max_osd(10);
-  osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
-  osdmap->set_epoch(epoch);
-  ceph::shared_ptr<OSDMap> lastmap(new OSDMap());
-  lastmap->set_max_osd(10);
-  lastmap->set_state(osd_id, CEPH_OSD_EXISTS);
-  lastmap->set_epoch(epoch);
-  epoch_t same_interval_since = epoch;
-  epoch_t last_epoch_clean = same_interval_since;
-  int64_t pool_id = 200;
-  int pg_num = 4;
-  __u8 min_size = 2;
-  {
-    OSDMap::Incremental inc(epoch + 1);
-    inc.new_pools[pool_id].min_size = min_size;
-    inc.new_pools[pool_id].set_pg_num(pg_num);
-    inc.new_up_thru[osd_id] = epoch + 1;
-    osdmap->apply_incremental(inc);
-    lastmap->apply_incremental(inc);
-  }
-  vector<int> new_acting;
-  new_acting.push_back(osd_id);
-  new_acting.push_back(osd_id + 1);
-  vector<int> old_acting = new_acting;
-  vector<int> new_up;
-  new_up.push_back(osd_id);
-  vector<int> old_up = new_up;
-  pg_t pgid;
-  pgid.set_pool(pool_id);
-
-  //
-  // Do nothing if there are no modifications in
-  // acting, up or pool size and that the pool is not
-  // being split
-  //
-  {
-    map<epoch_t, pg_interval_t> past_intervals;
-
-    ASSERT_TRUE(past_intervals.empty());
-    ASSERT_FALSE(pg_interval_t::check_new_interval(old_acting,
-                                                  new_acting,
-                                                  old_up,
-                                                  new_up,
-                                                  same_interval_since,
-                                                  last_epoch_clean,
-                                                  osdmap,
-                                                  lastmap,
-                                                  pool_id,
-                                                  pgid,
-                                                  &past_intervals));
-    ASSERT_TRUE(past_intervals.empty());
-  }
-
-  //
-  // pool did not exist in the old osdmap
-  //
-  {
-    ceph::shared_ptr<OSDMap> lastmap(new OSDMap());
-    lastmap->set_max_osd(10);
-    lastmap->set_state(osd_id, CEPH_OSD_EXISTS);
-    lastmap->set_epoch(epoch);
-
-    map<epoch_t, pg_interval_t> past_intervals;
-
-    ASSERT_TRUE(past_intervals.empty());
-    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
-                                                 new_acting,
-                                                 old_up,
-                                                 new_up,
-                                                 same_interval_since,
-                                                 last_epoch_clean,
-                                                 osdmap,
-                                                 lastmap,
-                                                 pool_id,
-                                                 pgid,
-                                                 &past_intervals));
-    ASSERT_EQ((unsigned int)1, past_intervals.size());
-    ASSERT_EQ(same_interval_since, past_intervals[same_interval_since].first);
-    ASSERT_EQ(osdmap->get_epoch() - 1, past_intervals[same_interval_since].last);
-    ASSERT_EQ(osd_id, past_intervals[same_interval_since].acting[0]);
-    ASSERT_EQ(osd_id, past_intervals[same_interval_since].up[0]);
-  }
-
-  //
-  // The acting set has changed
-  //
-  {
-    vector<int> new_acting;
-    int new_primary = osd_id + 1;
-    new_acting.push_back(new_primary);
-
-    map<epoch_t, pg_interval_t> past_intervals;
-
-    ASSERT_TRUE(past_intervals.empty());
-    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
-                                                 new_acting,
-                                                 old_up,
-                                                 new_up,
-                                                 same_interval_since,
-                                                 last_epoch_clean,
-                                                 osdmap,
-                                                 lastmap,
-                                                 pool_id,
-                                                 pgid,
-                                                 &past_intervals));
-    ASSERT_EQ((unsigned int)1, past_intervals.size());
-    ASSERT_EQ(same_interval_since, past_intervals[same_interval_since].first);
-    ASSERT_EQ(osdmap->get_epoch() - 1, past_intervals[same_interval_since].last);
-    ASSERT_EQ(osd_id, past_intervals[same_interval_since].acting[0]);
-    ASSERT_EQ(osd_id, past_intervals[same_interval_since].up[0]);
-  }
-
-  //
-  // The up set has changed
-  //
-  {
-    vector<int> new_up;
-    int new_primary = osd_id + 1;
-    new_up.push_back(new_primary);
-
-    map<epoch_t, pg_interval_t> past_intervals;
-
-    ASSERT_TRUE(past_intervals.empty());
-    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
-                                                 new_acting,
-                                                 old_up,
-                                                 new_up,
-                                                 same_interval_since,
-                                                 last_epoch_clean,
-                                                 osdmap,
-                                                 lastmap,
-                                                 pool_id,
-                                                 pgid,
-                                                 &past_intervals));
-    ASSERT_EQ((unsigned int)1, past_intervals.size());
-    ASSERT_EQ(same_interval_since, past_intervals[same_interval_since].first);
-    ASSERT_EQ(osdmap->get_epoch() - 1, past_intervals[same_interval_since].last);
-    ASSERT_EQ(osd_id, past_intervals[same_interval_since].acting[0]);
-    ASSERT_EQ(osd_id, past_intervals[same_interval_since].up[0]);
-  }
-
-  //
-  // PG is splitting
-  //
-  {
-    ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
-    osdmap->set_max_osd(10);
-    osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
-    osdmap->set_epoch(epoch);
-    int new_pg_num = pg_num ^ 2;
-    OSDMap::Incremental inc(epoch + 1);
-    inc.new_pools[pool_id].min_size = min_size;
-    inc.new_pools[pool_id].set_pg_num(new_pg_num);
-    osdmap->apply_incremental(inc);
-
-    map<epoch_t, pg_interval_t> past_intervals;
-
-    ASSERT_TRUE(past_intervals.empty());
-    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
-                                                 new_acting,
-                                                 old_up,
-                                                 new_up,
-                                                 same_interval_since,
-                                                 last_epoch_clean,
-                                                 osdmap,
-                                                 lastmap,
-                                                 pool_id,
-                                                 pgid,
-                                                 &past_intervals));
-    ASSERT_EQ((unsigned int)1, past_intervals.size());
-    ASSERT_EQ(same_interval_since, past_intervals[same_interval_since].first);
-    ASSERT_EQ(osdmap->get_epoch() - 1, past_intervals[same_interval_since].last);
-    ASSERT_EQ(osd_id, past_intervals[same_interval_since].acting[0]);
-    ASSERT_EQ(osd_id, past_intervals[same_interval_since].up[0]);
-  }
-
-  //
-  // PG size has changed
-  //
-  {
-    ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
-    osdmap->set_max_osd(10);
-    osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
-    osdmap->set_epoch(epoch);
-    OSDMap::Incremental inc(epoch + 1);
-    __u8 new_min_size = min_size + 1;
-    inc.new_pools[pool_id].min_size = new_min_size;
-    inc.new_pools[pool_id].set_pg_num(pg_num);
-    osdmap->apply_incremental(inc);
-
-    map<epoch_t, pg_interval_t> past_intervals;
-
-    ASSERT_TRUE(past_intervals.empty());
-    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
-                                                 new_acting,
-                                                 old_up,
-                                                 new_up,
-                                                 same_interval_since,
-                                                 last_epoch_clean,
-                                                 osdmap,
-                                                 lastmap,
-                                                 pool_id,
-                                                 pgid,
-                                                 &past_intervals));
-    ASSERT_EQ((unsigned int)1, past_intervals.size());
-    ASSERT_EQ(same_interval_since, past_intervals[same_interval_since].first);
-    ASSERT_EQ(osdmap->get_epoch() - 1, past_intervals[same_interval_since].last);
-    ASSERT_EQ(osd_id, past_intervals[same_interval_since].acting[0]);
-    ASSERT_EQ(osd_id, past_intervals[same_interval_since].up[0]);
-  }
-  
-  //
-  // The old acting set was empty : the previous interval could not
-  // have been rw
-  //
-  {
-    vector<int> old_acting;
-
-    map<epoch_t, pg_interval_t> past_intervals;
-
-    ostringstream out;
-
-    ASSERT_TRUE(past_intervals.empty());
-    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
-                                                 new_acting,
-                                                 old_up,
-                                                 new_up,
-                                                 same_interval_since,
-                                                 last_epoch_clean,
-                                                 osdmap,
-                                                 lastmap,
-                                                 pool_id,
-                                                 pgid,
-                                                 &past_intervals,
-                                                 &out));
-    ASSERT_EQ((unsigned int)1, past_intervals.size());
-    ASSERT_FALSE(past_intervals[same_interval_since].maybe_went_rw);
-    ASSERT_NE(string::npos, out.str().find("acting set is too small"));
-  }
-
-  //
-  // The old acting set did not have enough osd : it could 
-  // not have been rw
-  //
-  {
-    vector<int> old_acting;
-    old_acting.push_back(osd_id); 
-
-    //
-    // see http://tracker.ceph.com/issues/5780
-    // the size of the old acting set should be compared 
-    // with the min_size of the old osdmap
-    //
-    // The new osdmap is created so that it triggers the
-    // bug.
-    //
-    ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
-    osdmap->set_max_osd(10);
-    osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
-    osdmap->set_epoch(epoch);
-    OSDMap::Incremental inc(epoch + 1);
-    __u8 new_min_size = old_acting.size();
-    inc.new_pools[pool_id].min_size = new_min_size;
-    inc.new_pools[pool_id].set_pg_num(pg_num);
-    osdmap->apply_incremental(inc);
-
-    ostringstream out;
-
-    map<epoch_t, pg_interval_t> past_intervals;
-
-    ASSERT_TRUE(past_intervals.empty());
-    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
-                                                 new_acting,
-                                                 old_up,
-                                                 new_up,
-                                                 same_interval_since,
-                                                 last_epoch_clean,
-                                                 osdmap,
-                                                 lastmap,
-                                                 pool_id,
-                                                 pgid,
-                                                 &past_intervals,
-                                                 &out));
-    ASSERT_EQ((unsigned int)1, past_intervals.size());
-    ASSERT_FALSE(past_intervals[same_interval_since].maybe_went_rw);
-    ASSERT_NE(string::npos, out.str().find("acting set is too small"));
-  }
-
-  //
-  // The acting set changes. The old acting set primary was up during the
-  // previous interval and may have been rw.
-  //
-  {
-    vector<int> new_acting;
-    new_acting.push_back(osd_id + 4); 
-    new_acting.push_back(osd_id + 5); 
-    
-    ostringstream out;
-
-    map<epoch_t, pg_interval_t> past_intervals;
-
-    ASSERT_TRUE(past_intervals.empty());
-    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
-                                                 new_acting,
-                                                 old_up,
-                                                 new_up,
-                                                 same_interval_since,
-                                                 last_epoch_clean,
-                                                 osdmap,
-                                                 lastmap,
-                                                 pool_id,
-                                                 pgid,
-                                                 &past_intervals,
-                                                 &out));
-    ASSERT_EQ((unsigned int)1, past_intervals.size());
-    ASSERT_TRUE(past_intervals[same_interval_since].maybe_went_rw);
-    ASSERT_NE(string::npos, out.str().find("includes interval"));
-  }
-  //
-  // The acting set changes. The old acting set primary was not up 
-  // during the old interval but last_epoch_clean is in the
-  // old interval and it may have been rw.
-  //
-  {
-    vector<int> new_acting;
-    new_acting.push_back(osd_id + 4); 
-    new_acting.push_back(osd_id + 5); 
-
-    ceph::shared_ptr<OSDMap> lastmap(new OSDMap());
-    lastmap->set_max_osd(10);
-    lastmap->set_state(osd_id, CEPH_OSD_EXISTS);
-    lastmap->set_epoch(epoch);
-    OSDMap::Incremental inc(epoch + 1);
-    inc.new_pools[pool_id].min_size = min_size;
-    inc.new_pools[pool_id].set_pg_num(pg_num);
-    inc.new_up_thru[osd_id] = epoch - 10;
-    lastmap->apply_incremental(inc);
-
-    ostringstream out;
-
-    map<epoch_t, pg_interval_t> past_intervals;
-
-    ASSERT_TRUE(past_intervals.empty());
-    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
-                                                 new_acting,
-                                                 old_up,
-                                                 new_up,
-                                                 same_interval_since,
-                                                 last_epoch_clean,
-                                                 osdmap,
-                                                 lastmap,
-                                                 pool_id,
-                                                 pgid,
-                                                 &past_intervals,
-                                                 &out));
-    ASSERT_EQ((unsigned int)1, past_intervals.size());
-    ASSERT_TRUE(past_intervals[same_interval_since].maybe_went_rw);
-    ASSERT_NE(string::npos, out.str().find("presumed to have been rw"));
-  }
-
-  //
-  // The acting set changes. The old acting set primary was not up 
-  // during the old interval and last_epoch_clean is before the
-  // old interval : the previous interval could not possibly have
-  // been rw.
-  //
-  {
-    vector<int> new_acting;
-    new_acting.push_back(osd_id + 4); 
-    new_acting.push_back(osd_id + 5); 
-
-    epoch_t last_epoch_clean = epoch - 10;
-
-    ceph::shared_ptr<OSDMap> lastmap(new OSDMap());
-    lastmap->set_max_osd(10);
-    lastmap->set_state(osd_id, CEPH_OSD_EXISTS);
-    lastmap->set_epoch(epoch);
-    OSDMap::Incremental inc(epoch + 1);
-    inc.new_pools[pool_id].min_size = min_size;
-    inc.new_pools[pool_id].set_pg_num(pg_num);
-    inc.new_up_thru[osd_id] = last_epoch_clean;
-    lastmap->apply_incremental(inc);
-
-    ostringstream out;
-
-    map<epoch_t, pg_interval_t> past_intervals;
-
-    ASSERT_TRUE(past_intervals.empty());
-    ASSERT_TRUE(pg_interval_t::check_new_interval(old_acting,
-                                                 new_acting,
-                                                 old_up,
-                                                 new_up,
-                                                 same_interval_since,
-                                                 last_epoch_clean,
-                                                 osdmap,
-                                                 lastmap,
-                                                 pool_id,
-                                                 pgid,
-                                                 &past_intervals,
-                                                 &out));
-    ASSERT_EQ((unsigned int)1, past_intervals.size());
-    ASSERT_FALSE(past_intervals[same_interval_since].maybe_went_rw);
-    ASSERT_NE(string::npos, out.str().find("does not include interval"));
-  }
-}
-
-TEST(pg_t, split)
-{
-  pg_t pgid(0, 0, -1);
-  set<pg_t> s;
-  bool b;
-
-  s.clear();
-  b = pgid.is_split(1, 1, &s);
-  ASSERT_TRUE(!b);
-
-  s.clear();
-  b = pgid.is_split(2, 4, NULL);
-  ASSERT_TRUE(b);
-  b = pgid.is_split(2, 4, &s);
-  ASSERT_TRUE(b);
-  ASSERT_EQ(1u, s.size());
-  ASSERT_TRUE(s.count(pg_t(2, 0, -1)));
-
-  s.clear();
-  b = pgid.is_split(2, 8, &s);
-  ASSERT_TRUE(b);
-  ASSERT_EQ(3u, s.size());
-  ASSERT_TRUE(s.count(pg_t(2, 0, -1)));
-  ASSERT_TRUE(s.count(pg_t(4, 0, -1)));
-  ASSERT_TRUE(s.count(pg_t(6, 0, -1)));
-
-  s.clear();
-  b = pgid.is_split(3, 8, &s);
-  ASSERT_TRUE(b);
-  ASSERT_EQ(1u, s.size());
-  ASSERT_TRUE(s.count(pg_t(4, 0, -1)));
-
-  s.clear();
-  b = pgid.is_split(6, 8, NULL);
-  ASSERT_TRUE(!b);
-  b = pgid.is_split(6, 8, &s);
-  ASSERT_TRUE(!b);
-  ASSERT_EQ(0u, s.size());
-
-  pgid = pg_t(1, 0, -1);
-  
-  s.clear();
-  b = pgid.is_split(2, 4, &s);
-  ASSERT_TRUE(b);
-  ASSERT_EQ(1u, s.size());
-  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
-
-  s.clear();
-  b = pgid.is_split(2, 6, &s);
-  ASSERT_TRUE(b);
-  ASSERT_EQ(2u, s.size());
-  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
-  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
-
-  s.clear();
-  b = pgid.is_split(2, 8, &s);
-  ASSERT_TRUE(b);
-  ASSERT_EQ(3u, s.size());
-  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
-  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
-  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
-
-  s.clear();
-  b = pgid.is_split(4, 8, &s);
-  ASSERT_TRUE(b);
-  ASSERT_EQ(1u, s.size());
-  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
-
-  s.clear();
-  b = pgid.is_split(3, 8, &s);
-  ASSERT_TRUE(b);
-  ASSERT_EQ(3u, s.size());
-  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
-  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
-  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
-
-  s.clear();
-  b = pgid.is_split(6, 8, &s);
-  ASSERT_TRUE(!b);
-  ASSERT_EQ(0u, s.size());
-
-  pgid = pg_t(3, 0, -1);
-
-  s.clear();
-  b = pgid.is_split(7, 8, &s);
-  ASSERT_TRUE(b);
-  ASSERT_EQ(1u, s.size());
-  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
-
-  s.clear();
-  b = pgid.is_split(7, 12, &s);
-  ASSERT_TRUE(b);
-  ASSERT_EQ(2u, s.size());
-  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
-  ASSERT_TRUE(s.count(pg_t(11, 0, -1)));
-
-  s.clear();
-  b = pgid.is_split(7, 11, &s);
-  ASSERT_TRUE(b);
-  ASSERT_EQ(1u, s.size());
-  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
-
-}
-
-TEST(pg_missing_t, constructor)
-{
-  pg_missing_t missing;
-  EXPECT_EQ((unsigned int)0, missing.num_missing());
-  EXPECT_FALSE(missing.have_missing());
-}
-
-TEST(pg_missing_t, have_missing)
-{
-  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-  pg_missing_t missing;
-  EXPECT_FALSE(missing.have_missing());
-  missing.add(oid, eversion_t(), eversion_t());
-  EXPECT_TRUE(missing.have_missing());
-}
-
-TEST(pg_missing_t, swap)
-{
-  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-  pg_missing_t missing;
-  EXPECT_FALSE(missing.have_missing());
-  missing.add(oid, eversion_t(), eversion_t());
-  EXPECT_TRUE(missing.have_missing());
-
-  pg_missing_t other;
-  EXPECT_FALSE(other.have_missing());
-
-  other.swap(missing);
-  EXPECT_FALSE(missing.have_missing());  
-  EXPECT_TRUE(other.have_missing());  
-}
-
-TEST(pg_missing_t, is_missing)
-{
-  // pg_missing_t::is_missing(const hobject_t& oid) const
-  {
-    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-    pg_missing_t missing;
-    EXPECT_FALSE(missing.is_missing(oid));
-    missing.add(oid, eversion_t(), eversion_t());
-    EXPECT_TRUE(missing.is_missing(oid));
-  }
-
-  // bool pg_missing_t::is_missing(const hobject_t& oid, eversion_t v) const
-  {
-    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-    pg_missing_t missing;
-    eversion_t need(10,5);
-    EXPECT_FALSE(missing.is_missing(oid, eversion_t()));
-    missing.add(oid, need, eversion_t());
-    EXPECT_TRUE(missing.is_missing(oid));
-    EXPECT_FALSE(missing.is_missing(oid, eversion_t()));
-    EXPECT_TRUE(missing.is_missing(oid, need));
-  }
-}
-
-TEST(pg_missing_t, have_old)
-{
-  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-  pg_missing_t missing;
-  EXPECT_EQ(eversion_t(), missing.have_old(oid));
-  missing.add(oid, eversion_t(), eversion_t());
-  EXPECT_EQ(eversion_t(), missing.have_old(oid));
-  eversion_t have(1,1);
-  missing.revise_have(oid, have);
-  EXPECT_EQ(have, missing.have_old(oid));
-}
-
-TEST(pg_missing_t, add_next_event)
-{
-  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-  hobject_t oid_other(object_t("other"), "key", 9123, 9456, 0, "");
-  eversion_t version(10,5);
-  eversion_t prior_version(3,4);
-  pg_log_entry_t sample_e(pg_log_entry_t::DELETE, oid, version, prior_version,
-                         0, osd_reqid_t(entity_name_t::CLIENT(777), 8, 999),
-                         utime_t(8,9));
-
-  // new object (MODIFY)
-  {
-    pg_missing_t missing;
-    pg_log_entry_t e = sample_e;
-
-    e.op = pg_log_entry_t::MODIFY;
-    e.prior_version = eversion_t();
-    EXPECT_TRUE(e.is_update());
-    EXPECT_FALSE(missing.is_missing(oid));
-    missing.add_next_event(e);
-    EXPECT_TRUE(missing.is_missing(oid));
-    EXPECT_EQ(eversion_t(), missing.missing[oid].have);
-    EXPECT_EQ(oid, missing.rmissing[e.version.version]);
-    EXPECT_EQ(1U, missing.num_missing());
-    EXPECT_EQ(1U, missing.rmissing.size());
-
-    // adding the same object replaces the previous one
-    missing.add_next_event(e);
-    EXPECT_TRUE(missing.is_missing(oid));
-    EXPECT_EQ(1U, missing.num_missing());
-    EXPECT_EQ(1U, missing.rmissing.size());
-  }
-  
-  // new object (CLONE)
-  {
-    pg_missing_t missing;
-    pg_log_entry_t e = sample_e;
-
-    e.op = pg_log_entry_t::CLONE;
-    e.prior_version = eversion_t();
-    EXPECT_TRUE(e.is_clone());
-    EXPECT_FALSE(missing.is_missing(oid));
-    missing.add_next_event(e);
-    EXPECT_TRUE(missing.is_missing(oid));
-    EXPECT_EQ(eversion_t(), missing.missing[oid].have);
-    EXPECT_EQ(oid, missing.rmissing[e.version.version]);
-    EXPECT_EQ(1U, missing.num_missing());
-    EXPECT_EQ(1U, missing.rmissing.size());
-
-    // adding the same object replaces the previous one
-    missing.add_next_event(e);
-    EXPECT_TRUE(missing.is_missing(oid));
-    EXPECT_EQ(1U, missing.num_missing());
-    EXPECT_EQ(1U, missing.rmissing.size());
-  }
-
-  // existing object (MODIFY)
-  {
-    pg_missing_t missing;
-    pg_log_entry_t e = sample_e;
-
-    e.op = pg_log_entry_t::MODIFY;
-    e.prior_version = eversion_t();
-    EXPECT_TRUE(e.is_update());
-    EXPECT_FALSE(missing.is_missing(oid));
-    missing.add_next_event(e);
-    EXPECT_TRUE(missing.is_missing(oid));
-    EXPECT_EQ(eversion_t(), missing.missing[oid].have);
-    EXPECT_EQ(oid, missing.rmissing[e.version.version]);
-    EXPECT_EQ(1U, missing.num_missing());
-    EXPECT_EQ(1U, missing.rmissing.size());
-
-    // adding the same object with a different version
-    e.prior_version = prior_version;
-    missing.add_next_event(e);
-    EXPECT_EQ(eversion_t(), missing.missing[oid].have);
-    EXPECT_TRUE(missing.is_missing(oid));
-    EXPECT_EQ(1U, missing.num_missing());
-    EXPECT_EQ(1U, missing.rmissing.size());
-  }
-  
-  // object with prior version (MODIFY)
-  {
-    pg_missing_t missing;
-    pg_log_entry_t e = sample_e;
-
-    e.op = pg_log_entry_t::MODIFY;
-    EXPECT_TRUE(e.is_update());
-    EXPECT_FALSE(missing.is_missing(oid));
-    missing.add_next_event(e);
-    EXPECT_TRUE(missing.is_missing(oid));
-    EXPECT_EQ(prior_version, missing.missing[oid].have);
-    EXPECT_EQ(version, missing.missing[oid].need);
-    EXPECT_EQ(oid, missing.rmissing[e.version.version]);
-    EXPECT_EQ(1U, missing.num_missing());
-    EXPECT_EQ(1U, missing.rmissing.size());
-  }
-
-  // obsolete (BACKLOG)
-  {
-    pg_missing_t missing;
-    pg_log_entry_t e = sample_e;
-
-    e.op = pg_log_entry_t::BACKLOG;
-    EXPECT_TRUE(e.is_backlog());
-    EXPECT_FALSE(missing.is_missing(oid));
-    EXPECT_THROW(missing.add_next_event(e), FailedAssertion);
-  }
-  
-  // adding a DELETE matching an existing event
-  {
-    pg_missing_t missing;
-    pg_log_entry_t e = sample_e;
-
-    e.op = pg_log_entry_t::MODIFY;
-    EXPECT_TRUE(e.is_update());
-    EXPECT_FALSE(missing.is_missing(oid));
-    missing.add_next_event(e);
-    EXPECT_TRUE(missing.is_missing(oid));
-
-    e.op = pg_log_entry_t::DELETE;
-    EXPECT_TRUE(e.is_delete());
-    missing.add_next_event(e);
-    EXPECT_FALSE(missing.have_missing());
-  }
-}
-
-TEST(pg_missing_t, revise_need)
-{
-  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-  pg_missing_t missing;
-  // create a new entry
-  EXPECT_FALSE(missing.is_missing(oid));
-  eversion_t need(10,10);
-  missing.revise_need(oid, need);
-  EXPECT_TRUE(missing.is_missing(oid));
-  EXPECT_EQ(eversion_t(), missing.missing[oid].have);
-  EXPECT_EQ(need, missing.missing[oid].need);
-  // update an existing entry and preserve have
-  eversion_t have(1,1);
-  missing.revise_have(oid, have);
-  eversion_t new_need(10,12);
-  EXPECT_EQ(have, missing.missing[oid].have);
-  missing.revise_need(oid, new_need);
-  EXPECT_EQ(have, missing.missing[oid].have);
-  EXPECT_EQ(new_need, missing.missing[oid].need);
-}
-
-TEST(pg_missing_t, revise_have)
-{
-  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-  pg_missing_t missing;
-  // a non existing entry means noop
-  EXPECT_FALSE(missing.is_missing(oid));
-  eversion_t have(1,1);
-  missing.revise_have(oid, have);
-  EXPECT_FALSE(missing.is_missing(oid));
-  // update an existing entry
-  eversion_t need(10,12);
-  missing.add(oid, need, have);
-  EXPECT_TRUE(missing.is_missing(oid));
-  eversion_t new_have(2,2);
-  EXPECT_EQ(have, missing.missing[oid].have);
-  missing.revise_have(oid, new_have);
-  EXPECT_EQ(new_have, missing.missing[oid].have);
-  EXPECT_EQ(need, missing.missing[oid].need);
-}
-
-TEST(pg_missing_t, add)
-{
-  hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-  pg_missing_t missing;
-  EXPECT_FALSE(missing.is_missing(oid));
-  eversion_t have(1,1);
-  eversion_t need(10,10);
-  missing.add(oid, need, have);
-  EXPECT_TRUE(missing.is_missing(oid));
-  EXPECT_EQ(have, missing.missing[oid].have);
-  EXPECT_EQ(need, missing.missing[oid].need);
-}
-
-TEST(pg_missing_t, rm)
-{
-  // void pg_missing_t::rm(const hobject_t& oid, eversion_t v)
-  {
-    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-    pg_missing_t missing;
-    EXPECT_FALSE(missing.is_missing(oid));
-    epoch_t epoch = 10;
-    eversion_t need(epoch,10);
-    missing.add(oid, need, eversion_t());
-    EXPECT_TRUE(missing.is_missing(oid));
-    // rm of an older version is a noop
-    missing.rm(oid, eversion_t(epoch / 2,20));
-    EXPECT_TRUE(missing.is_missing(oid));
-    // rm of a later version removes the object
-    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)
-  {
-    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-    pg_missing_t missing;
-    EXPECT_FALSE(missing.is_missing(oid));
-    missing.add(oid, eversion_t(), eversion_t());
-    EXPECT_TRUE(missing.is_missing(oid));
-    const std::map<hobject_t, pg_missing_t::item>::iterator m = missing.missing.find(oid);
-    missing.rm(m);
-    EXPECT_FALSE(missing.is_missing(oid));
-  }
-}
-
-TEST(pg_missing_t, got)
-{
-  // void pg_missing_t::got(const hobject_t& oid, eversion_t v)
-  {
-    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-    pg_missing_t missing;
-    // assert if the oid does not exist
-    EXPECT_THROW(missing.got(oid, eversion_t()), FailedAssertion);
-    EXPECT_FALSE(missing.is_missing(oid));
-    epoch_t epoch = 10;
-    eversion_t need(epoch,10);
-    missing.add(oid, need, eversion_t());
-    EXPECT_TRUE(missing.is_missing(oid));
-    // assert if that the version to be removed is lower than the version of the object
-    EXPECT_THROW(missing.got(oid, eversion_t(epoch / 2,20)), FailedAssertion);
-    // remove of a later version removes the object
-    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)
-  {
-    hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
-    pg_missing_t missing;
-    EXPECT_FALSE(missing.is_missing(oid));
-    missing.add(oid, eversion_t(), eversion_t());
-    EXPECT_TRUE(missing.is_missing(oid));
-    const std::map<hobject_t, pg_missing_t::item>::iterator m = missing.missing.find(oid);
-    missing.got(m);
-    EXPECT_FALSE(missing.is_missing(oid));
-  }
-}
-
-TEST(pg_missing_t, split_into)
-{
-  uint32_t hash1 = 1;
-  hobject_t oid1(object_t("objname"), "key1", 123, hash1, 0, "");
-  uint32_t hash2 = 2;
-  hobject_t oid2(object_t("objname"), "key2", 123, hash2, 0, "");
-  pg_missing_t missing;
-  missing.add(oid1, eversion_t(), eversion_t());
-  missing.add(oid2, eversion_t(), eversion_t());  
-  pg_t child_pgid;
-  child_pgid.m_seed = 1;
-  pg_missing_t child;  
-  unsigned split_bits = 1;
-  missing.split_into(child_pgid, split_bits, &child);
-  EXPECT_TRUE(child.is_missing(oid1));
-  EXPECT_FALSE(child.is_missing(oid2));
-  EXPECT_FALSE(missing.is_missing(oid1));
-  EXPECT_TRUE(missing.is_missing(oid2));
-}
-
-class ObjectContextTest : public ::testing::Test {
-protected:
-
-  static const useconds_t DELAY_MAX = 20 * 1000 * 1000;
-
-  class Thread_read_lock : public Thread {
-  public:
-    ObjectContext &obc;
-
-    Thread_read_lock(ObjectContext& _obc) : 
-      obc(_obc)
-    {
-    }
-    
-    virtual void *entry() {
-      obc.ondisk_read_lock();
-      return NULL;
-    }
-  };
-
-  class Thread_write_lock : public Thread {
-  public:
-    ObjectContext &obc;
-
-    Thread_write_lock(ObjectContext& _obc) : 
-      obc(_obc)
-    {
-    }
-    
-    virtual void *entry() {
-      obc.ondisk_write_lock();
-      return NULL;
-    }
-  };
-
-};
-
-TEST_F(ObjectContextTest, read_write_lock)
-{
-  {
-    ObjectContext obc;
-
-    //
-    // write_lock
-    // write_lock
-    // write_unlock
-    // write_unlock
-    //
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(0, obc.unstable_writes);
-
-    obc.ondisk_write_lock();
-
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(1, obc.unstable_writes);
-
-    obc.ondisk_write_lock();
-
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(2, obc.unstable_writes);
-
-    obc.ondisk_write_unlock();
-
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(1, obc.unstable_writes);
-
-    obc.ondisk_write_unlock();
-
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(0, obc.unstable_writes);
-  }
-
-  useconds_t delay = 0;
-
-  {
-    ObjectContext obc;
-
-    //
-    // write_lock
-    // read_lock => wait
-    // write_unlock => signal
-    // read_unlock
-    //
-    EXPECT_EQ(0, obc.readers_waiting);
-    EXPECT_EQ(0, obc.readers);
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(0, obc.unstable_writes);
-
-    obc.ondisk_write_lock();
-
-    EXPECT_EQ(0, obc.readers_waiting);
-    EXPECT_EQ(0, obc.readers);
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(1, obc.unstable_writes);
-
-    Thread_read_lock t(obc);
-    t.create();
-
-    do {
-      cout << "Trying (1) with delay " << delay << "us\n";
-      usleep(delay);
-    } while (obc.readers_waiting == 0 &&
-            ( delay = delay * 2 + 1) < DELAY_MAX);
-
-    EXPECT_EQ(1, obc.readers_waiting);
-    EXPECT_EQ(0, obc.readers);
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(1, obc.unstable_writes);
-
-    obc.ondisk_write_unlock();
-
-    do {
-      cout << "Trying (2) with delay " << delay << "us\n";
-      usleep(delay);
-    } while ((obc.readers == 0 || obc.readers_waiting == 1) && 
-            ( delay = delay * 2 + 1) < DELAY_MAX);
-    EXPECT_EQ(0, obc.readers_waiting);
-    EXPECT_EQ(1, obc.readers);
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(0, obc.unstable_writes);
-
-    obc.ondisk_read_unlock();
-
-    EXPECT_EQ(0, obc.readers_waiting);
-    EXPECT_EQ(0, obc.readers);
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(0, obc.unstable_writes);
-
-    t.join();
-  }
-
-  {
-    ObjectContext obc;
-
-    //
-    // read_lock
-    // write_lock => wait
-    // read_unlock => signal
-    // write_unlock
-    //
-    EXPECT_EQ(0, obc.readers_waiting);
-    EXPECT_EQ(0, obc.readers);
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(0, obc.unstable_writes);
-
-    obc.ondisk_read_lock();
-
-    EXPECT_EQ(0, obc.readers_waiting);
-    EXPECT_EQ(1, obc.readers);
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(0, obc.unstable_writes);
-
-    Thread_write_lock t(obc);
-    t.create();
-
-    do {
-      cout << "Trying (3) with delay " << delay << "us\n";
-      usleep(delay);
-    } while ((obc.writers_waiting == 0) &&
-            ( delay = delay * 2 + 1) < DELAY_MAX);
-
-    EXPECT_EQ(0, obc.readers_waiting);
-    EXPECT_EQ(1, obc.readers);
-    EXPECT_EQ(1, obc.writers_waiting);
-    EXPECT_EQ(0, obc.unstable_writes);
-
-    obc.ondisk_read_unlock();
-
-    do {
-      cout << "Trying (4) with delay " << delay << "us\n";
-      usleep(delay);
-    } while ((obc.unstable_writes == 0 || obc.writers_waiting == 1) &&
-            ( delay = delay * 2 + 1) < DELAY_MAX);
-
-    EXPECT_EQ(0, obc.readers_waiting);
-    EXPECT_EQ(0, obc.readers);
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(1, obc.unstable_writes);
-
-    obc.ondisk_write_unlock();
-
-    EXPECT_EQ(0, obc.readers_waiting);
-    EXPECT_EQ(0, obc.readers);
-    EXPECT_EQ(0, obc.writers_waiting);
-    EXPECT_EQ(0, obc.unstable_writes);
-
-    t.join();
-  }
-  
-}
-
-TEST(pg_pool_t_test, get_pg_num_divisor) {
-  pg_pool_t p;
-  p.set_pg_num(16);
-  p.set_pgp_num(16);
-
-  for (int i = 0; i < 16; ++i)
-    ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(i, 1)));
-
-  p.set_pg_num(12);
-  p.set_pgp_num(12);
-  //cout << "num " << p.get_pg_num()
-  //     << " mask " << p.get_pg_num_mask() << std::endl;
-  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(0, 1)));
-  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(1, 1)));
-  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(2, 1)));
-  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(3, 1)));
-  ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(4, 1)));
-  ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(5, 1)));
-  ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(6, 1)));
-  ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(7, 1)));
-  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(8, 1)));
-  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(9, 1)));
-  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(10, 1)));
-  ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(11, 1)));
-}
-
-
-/*
- * Local Variables:
- * compile-command: "cd .. ; 
- *   make unittest_osd_types ; 
- *   ./unittest_osd_types # --gtest_filter=pg_missing_t.constructor 
- * "
- * End:
- */
-