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,
*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
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);
}
}
+// -*- 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);
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) {}
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);
#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)
{