]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: make coll_t structured instead of a string
authorSage Weil <sage@redhat.com>
Tue, 6 Jan 2015 22:01:11 +0000 (14:01 -0800)
committerSage Weil <sage@redhat.com>
Fri, 19 Jun 2015 00:02:48 +0000 (17:02 -0700)
coll_t now has a restricted set of representable values:

- meta
- pg
- pg temp
- forremoval

The forremoval is for legacy compatibility only; we will be able to remove
it soonish.

Signed-off-by: Sage Weil <sage@redhat.com>
src/osd/osd_types.cc
src/osd/osd_types.h
src/tools/ceph_objectstore_tool.cc

index f6037691a195c770e67a2f62bd76798cfdda18d8..acf14c9a97320315914d3aa1e604bb258e7c7206 100644 (file)
@@ -548,78 +548,77 @@ ostream& operator<<(ostream& out, const pg_t &pg)
 
 // -- coll_t --
 
-bool coll_t::is_temp() const
-{
-  if (str.length() > 5 &&
-      strncmp(str.c_str() + str.length() - 5, "_TEMP", 5) == 0)
+std::string coll_t::to_str() const
+{
+  switch (type) {
+  case TYPE_META:
+    return "meta";
+  case TYPE_PG:
+    return stringify(pgid) + "_head";
+  case TYPE_PG_TEMP:
+    return stringify(pgid) + "_TEMP";
+  case TYPE_PG_REMOVAL:
+    return string("FORREMOVAL_") +
+      stringify(removal_seq) + "_" +
+      stringify(pgid);
+  default:
+    assert(0 == "unknown collection type");
+  }
+}
+
+bool coll_t::parse(const std::string& s)
+{
+  if (s == "meta") {
+    type = TYPE_META;
+    pgid = spg_t();
+    removal_seq = 0;
     return true;
-  return false;
-}
-
-bool coll_t::is_temp(spg_t *pgid) const
-{
-  const char *cstr(str.c_str());
-  if (!pgid->parse(cstr))
-    return false;
-  const char *tmp_start = strchr(cstr, '_');
-  if (!tmp_start)
-    return false;
-  if (strncmp(tmp_start, "_TEMP", 5) == 0)
+  }
+  if (s.find("_head") == s.length() - 5 &&
+      pgid.parse(s.substr(0, s.length() - 5))) {
+    type = TYPE_PG;
+    removal_seq = 0;
     return true;
-  return false;
-}
-
-bool coll_t::is_pg(spg_t *pgid) const
-{
-  const char *cstr(str.c_str());
-
-  if (!pgid->parse(cstr))
-    return false;
-  const char *snap_start = strchr(cstr, '_');
-  if (!snap_start)
-    return false;
-  if (strncmp(snap_start, "_head", 5) != 0)
-    return false;
-  return true;
-}
-
-bool coll_t::is_pg_prefix(spg_t *pgid) const
-{
-  const char *cstr(str.c_str());
-
-  if (!pgid->parse(cstr))
-    return false;
-  const char *snap_start = strchr(cstr, '_');
-  if (!snap_start)
-    return false;
-  return true;
-}
-
-bool coll_t::is_removal(spg_t *pgid) const
-{
-  if (str.substr(0, 11) != string("FORREMOVAL_"))
-    return false;
-
-  stringstream ss(str.substr(11));
-  uint64_t seq;  // unused...
-  ss >> seq;
-  char sep;
-  ss >> sep;
-  assert(sep == '_');
-  string pgid_str;
-  ss >> pgid_str;
-  if (!pgid->parse(pgid_str.c_str())) {
-    assert(0);
-    return false;
   }
-  return true;
+  if (s.find("_TEMP") == s.length() - 5 &&
+      pgid.parse(s.substr(0, s.length() - 5))) {
+    type = TYPE_PG_TEMP;
+    removal_seq = 0;
+    return true;
+  }
+  if (s.find("FORREMOVAL_") == 0) {
+    type = TYPE_PG_REMOVAL;
+    stringstream ss(s.substr(11));
+    ss >> removal_seq;
+    char sep;
+    ss >> sep;
+    assert(sep == '_');
+    string pgid_str;
+    ss >> pgid_str;
+    if (!pgid.parse(pgid_str.c_str())) {
+      assert(0);
+      return false;
+    }
+    return true;
+  }
+  return false;
 }
 
 void coll_t::encode(bufferlist& bl) const
 {
-  __u8 struct_v = 3;
-  ::encode(struct_v, bl);
-  ::encode(str, bl);
+  if (is_removal() || is_temp()) {
+    // can't express this as v2...
+    __u8 struct_v = 3;
+    ::encode(struct_v, bl);
+    ::encode(to_str(), bl);
+  } else {
+    __u8 struct_v = 2;
+    ::encode(struct_v, bl);
+    ::encode((__u8)type, bl);
+    ::encode(pgid, bl);
+    snapid_t snap = CEPH_NOSNAP;
+    ::encode(snap, bl);
+  }
 }
 
 void coll_t::decode(bufferlist::iterator& bl)
@@ -627,72 +626,72 @@ void coll_t::decode(bufferlist::iterator& bl)
   __u8 struct_v;
   ::decode(struct_v, bl);
   switch (struct_v) {
-  case 1: {
-    spg_t pgid;
-    snapid_t snap;
-
-    ::decode(pgid, bl);
-    ::decode(snap, bl);
-    // infer the type
-    if (pgid == spg_t() && snap == 0)
-      str = "meta";
-    else
-      str = pg_and_snap_to_str(pgid, snap);
-    break;
-  }
+  case 1:
+    {
+      snapid_t snap;
+      ::decode(pgid, bl);
+      ::decode(snap, bl);
 
-  case 2: {
-    __u8 type;
-    spg_t pgid;
-    snapid_t snap;
-    
-    ::decode(type, bl);
-    ::decode(pgid, bl);
-    ::decode(snap, bl);
-    switch (type) {
-    case 0:
-      str = "meta";
-      break;
-    case 1:
-      str = "temp";
-      break;
-    case 2:
-      str = pg_and_snap_to_str(pgid, snap);
-      break;
-    default: {
-      ostringstream oss;
-      oss << "coll_t::decode(): can't understand type " << type;
-      throw std::domain_error(oss.str());
+      // infer the type
+      if (pgid == spg_t() && snap == 0) {
+       type = TYPE_META;
+      } else {
+       type = TYPE_PG;
+      }
+      removal_seq = 0;
     }
+    break;
+
+  case 2:
+    {
+      __u8 _type;
+      snapid_t snap;
+      ::decode(_type, bl);
+      ::decode(pgid, bl);
+      ::decode(snap, bl);
+      type = (type_t)_type;
+      removal_seq = 0;
     }
     break;
-  }
 
   case 3:
-    ::decode(str, bl);
+    {
+      string str;
+      ::decode(str, bl);
+      bool ok = parse(str);
+      if (!ok)
+       throw std::domain_error(std::string("unable to parse pg ") + str);
+    }
     break;
-    
-  default: {
-    ostringstream oss;
-    oss << "coll_t::decode(): don't know how to decode version "
-       << struct_v;
-    throw std::domain_error(oss.str());
-  }
+
+  default:
+    {
+      ostringstream oss;
+      oss << "coll_t::decode(): don't know how to decode version "
+         << struct_v;
+      throw std::domain_error(oss.str());
+    }
   }
 }
 
 void coll_t::dump(Formatter *f) const
 {
-  f->dump_string("name", str);
+  f->dump_unsigned("type_id", (unsigned)type);
+  if (type != TYPE_META)
+    f->dump_stream("pgid") << pgid;
+  f->dump_string("name", to_str());
 }
 
 void coll_t::generate_test_instances(list<coll_t*>& o)
 {
-  o.push_back(new coll_t);
-  o.push_back(new coll_t("meta"));
-  o.push_back(new coll_t("temp"));
-  o.push_back(new coll_t("foo"));
-  o.push_back(new coll_t("bar"));
+  o.push_back(new coll_t());
+  o.push_back(new coll_t(spg_t(pg_t(1, 0), shard_id_t::NO_SHARD)));
+  o.push_back(new coll_t(o.back()->get_temp()));
+  o.push_back(new coll_t(spg_t(pg_t(3, 2), shard_id_t(12))));
+  o.push_back(new coll_t(o.back()->get_temp()));
+  o.push_back(new coll_t());
+  o.back()->parse("FORREMOVAL_0_0.1");
+  o.back()->parse("FORREMOVAL_123_2.2a3f");
 }
 
 // ---
index 0d0145fe52fdfec468bd3e7ddd2aec95a64bae0b..032aaf8e9dc4b0fd8a0be820a12360532657a269 100644 (file)
@@ -478,76 +478,95 @@ ostream& operator<<(ostream& out, const spg_t &pg);
 // ----------------------
 
 class coll_t {
-  explicit coll_t(const std::string &str_)
-    : str(str_)
-  { }
+  enum type_t {
+    TYPE_META = 0,
+    TYPE_LEGACY_TEMP = 1,  /* no longer used */
+    TYPE_PG = 2,
+    TYPE_PG_TEMP = 3,
+    TYPE_PG_REMOVAL = 4,   /* note: deprecated, not encoded */
+  };
+  type_t type;
+  spg_t pgid;
+  uint64_t removal_seq;  // note: deprecated, not encoded
 
 public:
-  coll_t()
-    : str("meta")
+  coll_t() : type(TYPE_META), removal_seq(0)
   { }
 
-  coll_t(const coll_t& other) : str(other.str) {}
+  coll_t(const coll_t& other)
+    : type(other.type), pgid(other.pgid), removal_seq(other.removal_seq) {}
 
-  explicit coll_t(spg_t pgid, snapid_t snap = CEPH_NOSNAP)
-    : str(pg_and_snap_to_str(pgid, snap))
+  explicit coll_t(spg_t pgid)
+    : type(TYPE_PG), pgid(pgid)
   { }
 
-  const std::string& to_str() const {
-    return str;
+  std::string to_str() const;
+  bool parse(const std::string& s);
+
+  int operator<(const coll_t &rhs) const {
+    return type < rhs.type ||
+                 (type == rhs.type && pgid < rhs.pgid);
   }
-  bool parse(const std::string& s) {
-    if (s == "meta") {
-      str = s;
+
+  bool is_meta() const {
+    return type == TYPE_META;
+  }
+  bool is_pg_prefix(spg_t *pgid_) const {
+    if (type == TYPE_PG || type == TYPE_PG_TEMP || type == TYPE_PG_REMOVAL) {
+      *pgid_ = pgid;
       return true;
     }
-    if (s.find("_head") == s.length() - 5 ||
-       s.find("_TEMP") == s.length() - 5) {
-      spg_t pgid;
-      if (pgid.parse(s.substr(0, s.length() - 5))) {
-       str = s;
-       return true;
-      }
+    return false;
+  }
+  bool is_pg() const {
+    return type == TYPE_PG;
+  }
+  bool is_pg(spg_t *pgid_) const {
+    if (type == TYPE_PG) {
+      *pgid_ = pgid;
+      return true;
     }
     return false;
   }
-
-  const char* c_str() const {
-    return str.c_str();
+  bool is_temp() const {
+    return type == TYPE_PG_TEMP;
   }
-
-  int operator<(const coll_t &rhs) const {
-    return str < rhs.str;
+  bool is_temp(spg_t *pgid_) const {
+    if (type == TYPE_PG_TEMP) {
+      *pgid_ = pgid;
+      return true;
+    }
+    return false;
   }
-
-  bool is_meta() const {
-    return str == string("meta");
+  bool is_removal() const {
+    return type == TYPE_PG_REMOVAL;
   }
-  bool is_pg_prefix(spg_t *pgid) const;
-  bool is_pg(spg_t *pgid) const;
-  bool is_pg() const {
-    spg_t pgid;
-    return is_pg(&pgid);
+  bool is_removal(spg_t *pgid_) const {
+    if (type == TYPE_PG_REMOVAL) {
+      *pgid_ = pgid;
+      return true;
+    }
+    return false;
   }
-  bool is_temp(spg_t *pgid) const;
-  bool is_temp() const;
-  bool is_removal(spg_t *pgid) const;
+
   void encode(bufferlist& bl) const;
   void decode(bufferlist::iterator& bl);
+
   inline bool operator==(const coll_t& rhs) const {
-    return str == rhs.str;
+    return type == rhs.type && pgid == rhs.pgid;
   }
   inline bool operator!=(const coll_t& rhs) const {
-    return str != rhs.str;
+    return !(*this == rhs);
   }
 
   // get a TEMP collection that corresponds to the current collection,
   // which we presume is a pg collection.
   coll_t get_temp() {
-    spg_t pgid;
-    bool valid = is_pg(&pgid);
-    assert(valid);
-    return coll_t(str.substr(0, str.length() - 4) + "TEMP");
+    assert(type == TYPE_PG);
+    coll_t other;
+    other.type = TYPE_PG_TEMP;
+    other.pgid = pgid;
+    return other;
   }
 
   void dump(Formatter *f) const;
@@ -564,8 +583,6 @@ private:
     oss << p << "_TEMP";
     return oss.str();
   }
-
-  std::string str;
 };
 
 WRITE_CLASS_ENCODER(coll_t)
index c363089dcb3ac8eced1985ba8af010fb0cfd0fe7..42f5279631a04f405ac0c942b20aef6cd32f3ea7 100644 (file)
@@ -234,12 +234,9 @@ struct pgid_object_list {
         cout << std::endl;
       }
       f->open_array_section("pgid_object");
-      string pgid = i->first.c_str();
-      std::size_t pos = pgid.find("_");
-      if (pos == string::npos)
-        f->dump_string("pgid", pgid);
-      else
-        f->dump_string("pgid", pgid.substr(0, pos));
+      spg_t pgid;
+      if (i->first.is_pg(&pgid))
+        f->dump_string("pgid", stringify(pgid));
       f->open_object_section("ghobject");
       i->second.dump(f);
       f->close_section();