// -- 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)
__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");
}
// ---
// ----------------------
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;
oss << p << "_TEMP";
return oss.str();
}
-
- std::string str;
};
WRITE_CLASS_ENCODER(coll_t)