]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
DBObjectMap, hobject: add helpers for pgid bit matching
authorSamuel Just <sam.just@inktank.com>
Sat, 2 Mar 2013 00:04:04 +0000 (16:04 -0800)
committerSamuel Just <sam.just@inktank.com>
Thu, 14 Mar 2013 02:45:12 +0000 (19:45 -0700)
Create helpers in hobject for generating prefixes for a
pg as well as matching hobjects against a pgid/numpgs
combo.  Use these in HashIndex.cc.

Signed-off-by: Samuel Just <sam.just@inktank.com>
src/os/HashIndex.cc
src/os/hobject.cc
src/os/hobject.h
src/test/test_osd_types.cc

index b3902b056a55d3eaa44be2d1e3268bf174a1f77b..d5f2d74080c57f87d392d6c07f647c6d070cdb98 100644 (file)
@@ -113,7 +113,7 @@ int HashIndex::col_split_level(
     sub_path.push_back(*i);
     path_to_hobject_hash_prefix(sub_path, &bits, &hash);
     if (bits < inbits) {
-      if ((match & ~((~0)<<bits)) == (hash & ~((~0)<<bits))) {
+      if (hobject_t::match_hash(hash, bits, match)) {
        r = col_split_level(
          from,
          to,
@@ -127,7 +127,7 @@ int HashIndex::col_split_level(
          *mkdirred = path.size();
       } // else, skip, doesn't need to be moved or recursed into
     } else {
-      if ((match & ~((~0)<<inbits)) == (hash & ~((~0)<<inbits))) {
+      if (hobject_t::match_hash(hash, inbits, match)) {
        to_move.insert(*i);
       }
     } // else, skip, doesn't need to be moved or recursed into
@@ -138,7 +138,7 @@ int HashIndex::col_split_level(
   for (map<string, hobject_t>::iterator i = objects.begin();
        i != objects.end();
        ++i) {
-    if ((i->second.hash & ~((~0)<<inbits)) == match) {
+    if (i->second.match(inbits, match)) {
       objs_to_move.insert(*i);
     }
   }
index 0134b30ebd1d6a46300ac572eaebab08d013ebd3..1387a0ce280bfc8522432563738b381f910d7b97 100644 (file)
@@ -1,8 +1,107 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
 
 #include "include/types.h"
 #include "hobject.h"
 #include "common/Formatter.h"
 
+static void append_escaped(const string &in, string *out)
+{
+  for (string::const_iterator i = in.begin(); i != in.end(); ++i) {
+    if (*i == '%') {
+      out->push_back('%');
+      out->push_back('p');
+    } else if (*i == '.') {
+      out->push_back('%');
+      out->push_back('e');
+    } else if (*i == '_') {
+      out->push_back('%');
+      out->push_back('u');
+    } else {
+      out->push_back(*i);
+    }
+  }
+}
+
+set<string> hobject_t::get_prefixes(
+  uint32_t bits,
+  uint32_t mask,
+  int64_t pool)
+{
+  uint32_t len = bits;
+  while (len % 4 /* nibbles */) len++;
+
+  set<uint32_t> from;
+  if (bits < 32)
+    from.insert(mask & ~((uint32_t)(~0) << bits));
+  else if (bits == 32)
+    from.insert(mask);
+  else
+    assert(0);
+
+
+  set<uint32_t> to;
+  for (uint32_t i = bits; i < len; ++i) {
+    for (set<uint32_t>::iterator j = from.begin();
+        j != from.end();
+        ++j) {
+      to.insert(*j | (1 << i));
+      to.insert(*j);
+    }
+    to.swap(from);
+    to.clear();
+  }
+
+  char buf[20];
+  char *t = buf;
+  uint64_t poolid(pool);
+  t += snprintf(t, sizeof(buf), "%.*lX", 16, poolid);
+  *(t++) = '.';
+  string poolstr(buf, t - buf);
+  set<string> ret;
+  for (set<uint32_t>::iterator i = from.begin();
+       i != from.end();
+       ++i) {
+    uint32_t revhash(hobject_t::_reverse_nibbles(*i));
+    snprintf(buf, sizeof(buf), "%.*X", (int)(sizeof(revhash))*2, revhash);
+    ret.insert(poolstr + string(buf, len/4));
+  }
+  return ret;
+}
+
+string hobject_t::to_str() const
+{
+  string out;
+
+  char snap_with_hash[1000];
+  char *t = snap_with_hash;
+  char *end = t + sizeof(snap_with_hash);
+
+  uint64_t poolid(pool);
+  t += snprintf(t, end - t, "%.*lX", 16, poolid);
+
+  uint32_t revhash(get_filestore_key_u32());
+  t += snprintf(t, end - t, ".%.*X", 8, revhash);
+
+  if (snap == CEPH_NOSNAP)
+    t += snprintf(t, end - t, ".head");
+  else if (snap == CEPH_SNAPDIR)
+    t += snprintf(t, end - t, ".snapdir");
+  else
+    t += snprintf(t, end - t, ".%llx", (long long unsigned)snap);
+
+  out += string(snap_with_hash);
+
+  out.push_back('.');
+  append_escaped(oid.name, &out);
+  out.push_back('.');
+  append_escaped(get_key(), &out);
+  out.push_back('.');
+  append_escaped(nspace, &out);
+
+  return out;
+}
+
 void hobject_t::encode(bufferlist& bl) const
 {
   ENCODE_START(4, 3, bl);
index d75ae8570c4df38c3c54156cf97bf0e0eb4b1ed2..28e0da0d82a047bc0f126e964962a7c72eae11b5 100644 (file)
@@ -44,6 +44,15 @@ public:
   const string &get_key() const {
     return key;
   }
+
+  string to_str() const;
+
+  static bool match_hash(uint32_t to_check, uint32_t bits, uint32_t match) {
+    return (match & ~((~0)<<bits)) == (to_check & ~((~0)<<bits));
+  }
+  bool match(uint32_t bits, uint32_t match) const {
+    return match_hash(hash, bits, match);
+  }
   
   hobject_t() : snap(0), hash(0), max(false), pool(-1) {}
 
@@ -92,11 +101,27 @@ public:
     return retval;
   }
 
+  /**
+   * Returns set S of strings such that for any object
+   * h where h.match(bits, mask), there is some string
+   * s \in S such that s is a prefix of h.to_str().
+   * Furthermore, for any s \in S, s is a prefix of
+   * h.str() implies that h.match(bits, mask).
+   */
+  static set<string> get_prefixes(
+    uint32_t bits,
+    uint32_t mask,
+    int64_t pool);
+
+  filestore_hobject_key_t get_filestore_key_u32() const {
+    assert(!max);
+    return _reverse_nibbles(hash);
+  }
   filestore_hobject_key_t get_filestore_key() const {
     if (max)
       return 0x100000000ull;
     else
-      return _reverse_nibbles(hash);
+      return get_filestore_key_u32();
   }
   void set_filestore_key(uint32_t v) {
     hash = _reverse_nibbles(v);
index 4ee1a1404cc0f6615f82a89116eae31bf62a2658..b696ace3ac2cd2a820d0d1804d7ad4bc80063541 100644 (file)
 
 #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_t, split)
 {