]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
filestore: make collection dir have better name; move coll_t type around
authorSage Weil <sage@newdream.net>
Mon, 28 Sep 2009 22:22:42 +0000 (15:22 -0700)
committerSage Weil <sage@newdream.net>
Mon, 28 Sep 2009 22:23:09 +0000 (15:23 -0700)
src/include/object.h
src/os/FileStore.cc
src/os/ObjectStore.h
src/osd/OSD.cc
src/osd/PG.cc
src/osd/ReplicatedPG.cc
src/osd/osd_types.h

index 1d397f9abc1fa94e0237a5698f9ae9d7ee86b073..a3227b7c55a925a5f4e132e3c10410fde0a5c2b2 100644 (file)
@@ -172,55 +172,4 @@ namespace __gnu_cxx {
 
 // ---------------------------
 
-struct coll_t {
-  __u64 pgid;
-  snapid_t snap;
-
-  coll_t(__u64 p=0, snapid_t s=0) : pgid(p), snap(s) {}
-  
-  void encode(bufferlist& bl) const {
-    ::encode(pgid, bl);
-    ::encode(snap, bl);
-  }
-  void decode(bufferlist::iterator& bl) {
-    ::decode(pgid, bl);
-    ::decode(snap, bl);
-  }
-};
-WRITE_CLASS_ENCODER(coll_t)
-
-inline ostream& operator<<(ostream& out, const coll_t& c) {
-  return out << hex << c.pgid << '.' << c.snap << dec;
-}
-
-inline bool operator<(const coll_t& l, const coll_t& r) {
-  return l.pgid < r.pgid || (l.pgid == r.pgid && l.snap < r.snap);
-}
-inline bool operator<=(const coll_t& l, const coll_t& r) {
-  return l.pgid < r.pgid || (l.pgid == r.pgid && l.snap <= r.snap);
-}
-inline bool operator==(const coll_t& l, const coll_t& r) {
-  return l.pgid == r.pgid && l.snap == r.snap;
-}
-inline bool operator!=(const coll_t& l, const coll_t& r) {
-  return l.pgid != r.pgid || l.snap != r.snap;
-}
-inline bool operator>(const coll_t& l, const coll_t& r) {
-  return l.pgid > r.pgid || (l.pgid == r.pgid && l.snap > r.snap);
-}
-inline bool operator>=(const coll_t& l, const coll_t& r) {
-  return l.pgid > r.pgid || (l.pgid == r.pgid && l.snap >= r.snap);
-}
-
-namespace __gnu_cxx {
-  template<> struct hash<coll_t> {
-    size_t operator()(const coll_t &c) const { 
-      static rjhash<uint32_t> H;
-      static rjhash<uint64_t> I;
-      return H(c.pgid) ^ I(c.snap);
-    }
-  };
-}
-
-
 #endif
index 69c19eed3a0aa3f630c2b3d521be548a6d9ebb0e..465fb34c664c44bcd82f37130d90b4933fceb909 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "FileJournal.h"
 
+#include "osd/osd_types.h"
+
 #include "common/Timer.h"
 
 #include <unistd.h>
@@ -40,6 +42,8 @@
 #include <sys/mount.h>
 #endif // DARWIN
 
+#include <sstream>
+
 
 #define ATTR_MAX 80
 
@@ -253,23 +257,15 @@ bool FileStore::parse_object(char *s, sobject_t& o)
 
 bool FileStore::parse_coll(char *s, coll_t& c)
 {
-  if (strlen(s) == 33 && s[16] == '.') {
-    s[16] = 0;
-    c.pgid = strtoull(s, 0, 16);
-    c.snap = strtoull(s+17, 0, 16);
-    return true;
-  } else 
-    return false;
+  bool r = c.parse(s);
+  dout(0) << "parse " << s << " -> " << c << " = " << r << dendl;
+  return r;
 }
 
 void FileStore::get_cdir(coll_t cid, char *s) 
 {
-  assert(sizeof(cid) == 16);
-#ifdef __LP64__
-  sprintf(s, "%s/%016lx.%016lx", basedir.c_str(), cid.pgid, (__u64)cid.snap);
-#else
-  sprintf(s, "%s/%016llx.%016llx", basedir.c_str(), cid.pgid, (__u64)cid.snap);
-#endif
+  s += sprintf(s, "%s/", basedir.c_str());
+  s += cid.print(s);
 }
 
 void FileStore::get_coname(coll_t cid, const sobject_t& oid, char *s) 
index cb641cd5b562d027cbc2c6ea751e934b30efc7d9..adbd025553fb1af1ef7dbb932b411b9cb2ab5e5e 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "include/Distribution.h"
 
+#include "osd/osd_types.h"
+
 #include <sys/stat.h>
 
 #ifdef DARWIN
index 70014c7d97664159c29a880aff9bdb85eee11035..b5e30365d2d5f84ca5ee89abada16e19d38fa30b 100644 (file)
@@ -665,8 +665,8 @@ PG *OSD::_create_lock_pg(pg_t pgid, ObjectStore::Transaction& t)
   PG *pg = _open_lock_pg(pgid);
 
   // create collection
-  assert(!store->collection_exists(pgid.to_coll()));
-  t.create_collection(pgid.to_coll());
+  assert(!store->collection_exists(coll_t::build_pg_coll(pgid)));
+  t.create_collection(coll_t::build_pg_coll(pgid));
 
   pg->write_info(t);
   pg->write_log(t);
@@ -683,8 +683,8 @@ PG *OSD::_create_lock_new_pg(pg_t pgid, vector<int>& acting, ObjectStore::Transa
 
   PG *pg = _open_lock_pg(pgid, true);
 
-  assert(!store->collection_exists(pgid.to_coll()));
-  t.create_collection(pgid.to_coll());
+  assert(!store->collection_exists(coll_t::build_pg_coll(pgid)));
+  t.create_collection(coll_t::build_pg_coll(pgid));
 
   pg->set_role(0);
   pg->acting.swap(acting);
@@ -732,7 +732,7 @@ void OSD::load_pgs()
        it++) {
     if (*it == 0)
       continue;
-    if (it->snap != 0)
+    if (it->snap != CEPH_NOSNAP)
       continue;
     pg_t pgid = it->pgid;
     PG *pg = _open_lock_pg(pgid);
@@ -2537,7 +2537,7 @@ void OSD::split_pg(PG *parent, map<pg_t,PG*>& children, ObjectStore::Transaction
   pg_t parentid = parent->info.pgid;
 
   vector<sobject_t> olist;
-  store->collection_list(parent->info.pgid.to_coll(), olist);  
+  store->collection_list(coll_t::build_pg_coll(parent->info.pgid), olist);  
 
   for (vector<sobject_t>::iterator p = olist.begin(); p != olist.end(); p++) {
     sobject_t poid = *p;
@@ -2550,8 +2550,8 @@ void OSD::split_pg(PG *parent, map<pg_t,PG*>& children, ObjectStore::Transaction
       bufferlist bv;
 
       struct stat st;
-      store->stat(parentid.to_coll(), poid, &st);
-      store->getattr(parentid.to_coll(), poid, OI_ATTR, bv);
+      store->stat(coll_t::build_pg_coll(parentid), poid, &st);
+      store->getattr(coll_t::build_pg_coll(parentid), poid, OI_ATTR, bv);
       object_info_t oi(bv);
 
       if (oi.version > child->info.last_update) {
@@ -2561,16 +2561,16 @@ void OSD::split_pg(PG *parent, map<pg_t,PG*>& children, ObjectStore::Transaction
        dout(25) << "    not tagging pg with v " << oi.version << " <= " << child->info.last_update << dendl;
       }
 
-      t.collection_add(pgid.to_coll(), parentid.to_coll(), poid);
-      t.collection_remove(parentid.to_coll(), poid);
+      t.collection_add(coll_t::build_pg_coll(pgid), coll_t::build_pg_coll(parentid), poid);
+      t.collection_remove(coll_t::build_pg_coll(parentid), poid);
       if (oi.snaps.size()) {
        snapid_t first = oi.snaps[0];
-       t.collection_add(pgid.to_snap_coll(first), parentid.to_coll(), poid);
-       t.collection_remove(parentid.to_snap_coll(first), poid);
+       t.collection_add(coll_t::build_snap_pg_coll(pgid, first), coll_t::build_pg_coll(parentid), poid);
+       t.collection_remove(coll_t::build_snap_pg_coll(parentid, first), poid);
        if (oi.snaps.size() > 1) {
          snapid_t last = oi.snaps[oi.snaps.size()-1];
-         t.collection_add(pgid.to_snap_coll(last), parentid.to_coll(), poid);
-         t.collection_remove(parentid.to_snap_coll(last), poid);
+         t.collection_add(coll_t::build_snap_pg_coll(pgid, last), coll_t::build_pg_coll(parentid), poid);
+         t.collection_remove(coll_t::build_snap_pg_coll(parentid, last), poid);
        }
       }
 
@@ -3266,14 +3266,14 @@ void OSD::_remove_pg(PG *pg)
        p != pg->snap_collections.end();
        p++) {
     vector<sobject_t> olist;      
-    store->collection_list(pgid.to_snap_coll(*p), olist);
+    store->collection_list(coll_t::build_snap_pg_coll(pgid, *p), olist);
     dout(10) << "_remove_pg " << pgid << " snap " << *p << " " << olist.size() << " objects" << dendl;
     for (vector<sobject_t>::iterator q = olist.begin();
         q != olist.end();
         q++) {
       ObjectStore::Transaction t;
-      t.remove(pgid.to_snap_coll(*p), *q);
-      t.remove(pgid.to_coll(), *q);          // we may hit this twice, but it's harmless
+      t.remove(coll_t::build_snap_pg_coll(pgid, *p), *q);
+      t.remove(coll_t::build_pg_coll(pgid), *q);          // we may hit this twice, but it's harmless
       store->apply_transaction(t);
 
       if ((++n & 0xff) == 0) {
@@ -3287,19 +3287,19 @@ void OSD::_remove_pg(PG *pg)
       }
     }
     ObjectStore::Transaction t;
-    t.remove_collection(pgid.to_snap_coll(*p));
+    t.remove_collection(coll_t::build_snap_pg_coll(pgid, *p));
     store->apply_transaction(t);
   }
 
   // (what remains of the) main collection
   vector<sobject_t> olist;
-  store->collection_list(pgid.to_coll(), olist);
+  store->collection_list(coll_t::build_pg_coll(pgid), olist);
   dout(10) << "_remove_pg " << pgid << " " << olist.size() << " objects" << dendl;
   for (vector<sobject_t>::iterator p = olist.begin();
        p != olist.end();
        p++) {
     ObjectStore::Transaction t;
-    t.remove(pgid.to_coll(), *p);
+    t.remove(coll_t::build_pg_coll(pgid), *p);
     store->apply_transaction(t);
 
     if ((++n & 0xff) == 0) {
@@ -3328,7 +3328,7 @@ void OSD::_remove_pg(PG *pg)
 
   {
     ObjectStore::Transaction t;
-    t.remove_collection(pgid.to_coll());
+    t.remove_collection(coll_t::build_pg_coll(pgid));
     store->apply_transaction(t);
   }
   
index c3e674b59420485d70b8de3e76e149656bde93e4..e5841903828c8e974bbedc341a6f8222f1c60673 100644 (file)
@@ -316,7 +316,7 @@ bool PG::merge_old_entry(ObjectStore::Transaction& t, Log::Entry& oe)
       dout(20) << "merge_old_entry  had " << oe << " new dne : ok" << dendl;      
     } else {
       dout(20) << "merge_old_entry  had " << oe << " new dne : deleting" << dendl;
-      t.remove(info.pgid.to_coll(), oe.soid);
+      t.remove(coll_t::build_pg_coll(info.pgid), oe.soid);
       missing.rm(oe.soid, oe.version);
     }
   }
@@ -374,7 +374,7 @@ void PG::merge_log(ObjectStore::Transaction& t,
       dout(20) << "merge_log merging " << ne << dendl;
       missing.add_next_event(ne);
       if (ne.is_delete())
-       t.remove(info.pgid.to_coll(), ne.soid);
+       t.remove(coll_t::build_pg_coll(info.pgid), ne.soid);
     }
 
     // find any divergent or removed items in old log.
@@ -459,7 +459,7 @@ void PG::merge_log(ObjectStore::Transaction& t,
        log.index(ne);
        missing.add_next_event(ne);
        if (ne.is_delete())
-         t.remove(info.pgid.to_coll(), ne.soid);
+         t.remove(coll_t::build_pg_coll(info.pgid), ne.soid);
       }
       
       // move aside divergent items
@@ -545,7 +545,7 @@ bool PG::build_backlog_map(map<eversion_t,Log::Entry>& omap)
   unlock();
 
   vector<sobject_t> olist;
-  osd->store->collection_list(info.pgid.to_coll(), olist);
+  osd->store->collection_list(coll_t::build_pg_coll(info.pgid), olist);
 
   for (vector<sobject_t>::iterator it = olist.begin();
        it != olist.end();
@@ -555,7 +555,7 @@ bool PG::build_backlog_map(map<eversion_t,Log::Entry>& omap)
     Log::Entry e;
     e.soid = poid;
     bufferlist bv;
-    int r = osd->store->getattr(info.pgid.to_coll(), poid, OI_ATTR, bv);
+    int r = osd->store->getattr(coll_t::build_pg_coll(info.pgid), poid, OI_ATTR, bv);
     if (r < 0)
       continue;  // musta just been deleted!
     object_info_t oi(bv);
@@ -1794,18 +1794,18 @@ void PG::write_info(ObjectStore::Transaction& t)
   bufferlist infobl;
   ::encode(info, infobl);
   dout(20) << "write_info info " << infobl.length() << dendl;
-  t.collection_setattr(info.pgid.to_coll(), "info", infobl);
+  t.collection_setattr(coll_t::build_pg_coll(info.pgid), "info", infobl);
  
   // local state
   bufferlist snapbl;
   ::encode(snap_collections, snapbl);
   dout(20) << "write_info snap " << snapbl.length() << dendl;
-  t.collection_setattr(info.pgid.to_coll(), "snap_collections", snapbl);
+  t.collection_setattr(coll_t::build_pg_coll(info.pgid), "snap_collections", snapbl);
 
   bufferlist ki;
   ::encode(past_intervals, ki);
   dout(20) << "write_info pastintervals " << ki.length() << dendl;
-  t.collection_setattr(info.pgid.to_coll(), "past_intervals", ki);
+  t.collection_setattr(coll_t::build_pg_coll(info.pgid), "past_intervals", ki);
 
   dirty_info = false;
 }
@@ -1846,7 +1846,7 @@ void PG::write_log(ObjectStore::Transaction& t)
 
   bufferlist blb(sizeof(ondisklog));
   ::encode(ondisklog, blb);
-  t.collection_setattr(info.pgid.to_coll(), "ondisklog", blb);
+  t.collection_setattr(coll_t::build_pg_coll(info.pgid), "ondisklog", blb);
   
   dout(10) << "write_log to " << ondisklog.tail << "~" << ondisklog.length() << dendl;
   dirty_log = false;
@@ -1896,7 +1896,7 @@ void PG::trim_ondisklog_to(ObjectStore::Transaction& t, eversion_t v)
   
   bufferlist blb(sizeof(ondisklog));
   ::encode(ondisklog, blb);
-  t.collection_setattr(info.pgid.to_coll(), "ondisklog", blb);
+  t.collection_setattr(coll_t::build_pg_coll(info.pgid), "ondisklog", blb);
 
   if (!g_conf.osd_preserve_trimmed_log)
     t.zero(0, log_oid, 0, ondisklog.tail & ~4095);
@@ -1948,7 +1948,7 @@ void PG::append_log(ObjectStore::Transaction &t, bufferlist& bl,
 
   bufferlist blb(sizeof(ondisklog));
   ::encode(ondisklog, blb);
-  t.collection_setattr(info.pgid.to_coll(), "ondisklog", blb);
+  t.collection_setattr(coll_t::build_pg_coll(info.pgid), "ondisklog", blb);
   dout(10) << "append_log  now " << ondisklog.tail << "~" << ondisklog.length() << dendl;
 }
 
@@ -1958,7 +1958,7 @@ void PG::read_log(ObjectStore *store)
   ondisklog.tail = ondisklog.head = 0;
 
   bufferlist blb;
-  store->collection_getattr(info.pgid.to_coll(), "ondisklog", blb);
+  store->collection_getattr(coll_t::build_pg_coll(info.pgid), "ondisklog", blb);
   bufferlist::iterator p = blb.begin();
   ::decode(ondisklog, p);
 
@@ -2059,7 +2059,7 @@ void PG::read_log(ObjectStore *store)
       
       bufferlist bv;
       struct stat st;
-      int r = osd->store->getattr(info.pgid.to_coll(), i->soid, OI_ATTR, bv);
+      int r = osd->store->getattr(coll_t::build_pg_coll(info.pgid), i->soid, OI_ATTR, bv);
       if (r >= 0) {
        object_info_t oi(bv);
        if (oi.version < i->version) {
@@ -2067,7 +2067,7 @@ void PG::read_log(ObjectStore *store)
          missing.add(i->soid, i->version, oi.version);
        }
       } else if (i->soid.snap == CEPH_NOSNAP &&
-                osd->store->stat(info.pgid.to_coll(), i->soid, &st) == 0) {
+                osd->store->stat(coll_t::build_pg_coll(info.pgid), i->soid, &st) == 0) {
        dout(0) << "read_log  rebuilding missing xattr on " << *i << dendl;
        object_info_t oi(i->soid);
        oi.version = i->version;
@@ -2078,7 +2078,7 @@ void PG::read_log(ObjectStore *store)
        bufferlist bl;
        ::encode(oi, bl);
        ObjectStore::Transaction t;
-       t.setattr(info.pgid.to_coll(), i->soid, OI_ATTR, bl);
+       t.setattr(coll_t::build_pg_coll(info.pgid), i->soid, OI_ATTR, bl);
        osd->store->apply_transaction(t);
 
        stringstream ss;
@@ -2101,19 +2101,19 @@ void PG::read_state(ObjectStore *store)
   bufferlist::iterator p;
 
   // info
-  store->collection_getattr(info.pgid.to_coll(), "info", bl);
+  store->collection_getattr(coll_t::build_pg_coll(info.pgid), "info", bl);
   p = bl.begin();
   ::decode(info, p);
   
   // snap_collections
   bl.clear();
-  store->collection_getattr(info.pgid.to_coll(), "snap_collections", bl);
+  store->collection_getattr(coll_t::build_pg_coll(info.pgid), "snap_collections", bl);
   p = bl.begin();
   ::decode(snap_collections, p);
 
   // past_intervals
   bl.clear();
-  store->collection_getattr(info.pgid.to_coll(), "past_intervals", bl);
+  store->collection_getattr(coll_t::build_pg_coll(info.pgid), "past_intervals", bl);
   if (bl.length()) {
     p = bl.begin();
     ::decode(past_intervals, p);
@@ -2124,13 +2124,13 @@ void PG::read_state(ObjectStore *store)
 
 coll_t PG::make_snap_collection(ObjectStore::Transaction& t, snapid_t s)
 {
-  coll_t c = info.pgid.to_snap_coll(s);
+  coll_t c = coll_t::build_snap_pg_coll(info.pgid, s);
   if (snap_collections.count(s) == 0) {
     snap_collections.insert(s);
     dout(10) << "create_snap_collection " << c << ", set now " << snap_collections << dendl;
     bufferlist bl;
     ::encode(snap_collections, bl);
-    t.collection_setattr(info.pgid.to_coll(), "snap_collections", bl);
+    t.collection_setattr(coll_t::build_pg_coll(info.pgid), "snap_collections", bl);
     t.create_collection(c);
   }
   return c;
@@ -2219,7 +2219,7 @@ void PG::sub_op_scrub_reply(MOSDSubOpReply *op)
 void PG::build_scrub_map(ScrubMap &map)
 {
   dout(10) << "build_scrub_map" << dendl;
-  coll_t c = info.pgid.to_coll();
+  coll_t c = coll_t::build_pg_coll(info.pgid);
 
   // objects
   vector<sobject_t> ls;
index 37666c2043dc684da1befda749d74dec07b7cab4..d084bffeb116a3d1423d74f5f3615a7e4a617247 100644 (file)
@@ -391,7 +391,7 @@ void ReplicatedPG::do_pg_op(MOSDOp *op)
         PGLSResponse response;
         response.handle = (collection_list_handle_t)(__u64)(p->op.pgls_cookie);
         vector<sobject_t> sentries;
-       result = osd->store->collection_list_partial(info.pgid.to_coll(), snapid,
+       result = osd->store->collection_list_partial(coll_t::build_pg_coll(info.pgid), snapid,
                                                     sentries, p->op.length,
                                                     &response.handle);
        if (result == 0) {
@@ -405,13 +405,13 @@ void ReplicatedPG::do_pg_op(MOSDOp *op)
              // skip items not defined for this snapshot
              if (iter->snap == CEPH_NOSNAP) {
                bufferlist bl;
-               osd->store->getattr(info.pgid.to_coll(), *iter, SS_ATTR, bl);
+               osd->store->getattr(coll_t::build_pg_coll(info.pgid), *iter, SS_ATTR, bl);
                SnapSet snapset(bl);
                if (snapid <= snapset.seq)
                  continue;
              } else {
                bufferlist bl;
-               osd->store->getattr(info.pgid.to_coll(), *iter, OI_ATTR, bl);
+               osd->store->getattr(coll_t::build_pg_coll(info.pgid), *iter, OI_ATTR, bl);
                object_info_t oi(bl);
                bool exists = false;
                for (vector<snapid_t>::iterator i = oi.snaps.begin(); i != oi.snaps.end(); ++i)
@@ -731,7 +731,7 @@ bool ReplicatedPG::snap_trimmer()
   while (info.snap_trimq.size() &&
         is_active()) {
     snapid_t sn = *info.snap_trimq.begin();
-    coll_t c = info.pgid.to_snap_coll(sn);
+    coll_t c = coll_t::build_snap_pg_coll(info.pgid, sn);
     vector<sobject_t> ls;
     osd->store->collection_list(c, ls);
     if (ls.size() != info.stats.num_objects)
@@ -746,7 +746,7 @@ bool ReplicatedPG::snap_trimmer()
 
       // load clone info
       bufferlist bl;
-      osd->store->getattr(info.pgid.to_coll(), coid, OI_ATTR, bl);
+      osd->store->getattr(coll_t::build_pg_coll(info.pgid), coid, OI_ATTR, bl);
       object_info_t coi(bl);
 
       // get snap set context
@@ -771,10 +771,10 @@ bool ReplicatedPG::snap_trimmer()
       if (newsnaps.empty()) {
        // remove clone
        dout(10) << coid << " snaps " << snaps << " -> " << newsnaps << " ... deleting" << dendl;
-       t.remove(info.pgid.to_coll(), coid);
-       t.collection_remove(info.pgid.to_snap_coll(snaps[0]), coid);
+       t.remove(coll_t::build_pg_coll(info.pgid), coid);
+       t.collection_remove(coll_t::build_snap_pg_coll(info.pgid, snaps[0]), coid);
        if (snaps.size() > 1)
-         t.collection_remove(info.pgid.to_snap_coll(snaps[snaps.size()-1]), coid);
+         t.collection_remove(coll_t::build_snap_pg_coll(info.pgid, snaps[snaps.size()-1]), coid);
 
        // ...from snapset
        snapid_t last = coid.snap;
@@ -805,16 +805,16 @@ bool ReplicatedPG::snap_trimmer()
        coi.snaps.swap(newsnaps);
        bl.clear();
        ::encode(coi, bl);
-       t.setattr(info.pgid.to_coll(), coid, OI_ATTR, bl);
+       t.setattr(coll_t::build_pg_coll(info.pgid), coid, OI_ATTR, bl);
 
        if (snaps[0] != newsnaps[0]) {
-         t.collection_remove(info.pgid.to_snap_coll(snaps[0]), coid);
-         t.collection_add(info.pgid.to_snap_coll(newsnaps[0]), info.pgid.to_coll(), coid);
+         t.collection_remove(coll_t::build_snap_pg_coll(info.pgid, snaps[0]), coid);
+         t.collection_add(coll_t::build_snap_pg_coll(info.pgid, newsnaps[0]), coll_t::build_pg_coll(info.pgid), coid);
        }
        if (snaps.size() > 1 && snaps[snaps.size()-1] != newsnaps[newsnaps.size()-1]) {
-         t.collection_remove(info.pgid.to_snap_coll(snaps[snaps.size()-1]), coid);
+         t.collection_remove(coll_t::build_snap_pg_coll(info.pgid, snaps[snaps.size()-1]), coid);
          if (newsnaps.size() > 1)
-           t.collection_add(info.pgid.to_snap_coll(newsnaps[newsnaps.size()-1]), info.pgid.to_coll(), coid);
+           t.collection_add(coll_t::build_snap_pg_coll(info.pgid, newsnaps[newsnaps.size()-1]), coll_t::build_pg_coll(info.pgid), coid);
        }             
       }
 
@@ -824,11 +824,11 @@ bool ReplicatedPG::snap_trimmer()
       sobject_t snapoid(coid.oid, snapset.head_exists ? CEPH_NOSNAP:CEPH_SNAPDIR);
       if (snapset.clones.empty() && !snapset.head_exists) {
        dout(10) << coid << " removing " << snapoid << dendl;
-       t.remove(info.pgid.to_coll(), snapoid);
+       t.remove(coll_t::build_pg_coll(info.pgid), snapoid);
       } else {
        bl.clear();
        ::encode(snapset, bl);
-       t.setattr(info.pgid.to_coll(), snapoid, SS_ATTR, bl);
+       t.setattr(coll_t::build_pg_coll(info.pgid), snapoid, SS_ATTR, bl);
       }
 
       osd->store->apply_transaction(t);
@@ -919,7 +919,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
       {
        // read into a buffer
        bufferlist bl;
-       int r = osd->store->read(info.pgid.to_coll(), soid, op.offset, op.length, bl);
+       int r = osd->store->read(coll_t::build_pg_coll(info.pgid), soid, op.offset, op.length, bl);
        if (odata.length() == 0)
          ctx->data_off = op.offset;
        odata.claim(bl);
@@ -969,7 +969,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
       {
        struct stat st;
        memset(&st, sizeof(st), 0);
-       result = osd->store->stat(info.pgid.to_coll(), soid, &st);
+       result = osd->store->stat(coll_t::build_pg_coll(info.pgid), soid, &st);
        if (result >= 0) {
          __u64 size = st.st_size;
          ::encode(size, odata);
@@ -984,7 +984,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
        nstring name(op.name_len + 1);
        name[0] = '_';
        bp.copy(op.name_len, name.data()+1);
-       int r = osd->store->getattr(info.pgid.to_coll(), soid, name.c_str(), odata);
+       int r = osd->store->getattr(coll_t::build_pg_coll(info.pgid), soid, name.c_str(), odata);
        if (r >= 0) {
          op.value_len = r;
          result = 0;
@@ -997,7 +997,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
    case CEPH_OSD_OP_GETXATTRS:
       {
        map<nstring,bufferptr> attrset;
-        result = osd->store->getattrs(info.pgid.to_coll(), soid, attrset, true);
+        result = osd->store->getattrs(coll_t::build_pg_coll(info.pgid), soid, attrset, true);
         map<nstring, bufferptr>::iterator iter;
         map<nstring, bufferlist> newattrs;
         for (iter = attrset.begin(); iter != attrset.end(); ++iter) {
@@ -1087,9 +1087,9 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
         if (op.length) {
          bufferlist nbl;
          bp.copy(op.length, nbl);
-         t.write(info.pgid.to_coll(), soid, op.offset, op.length, nbl);
+         t.write(coll_t::build_pg_coll(info.pgid), soid, op.offset, op.length, nbl);
         } else {
-          t.touch(info.pgid.to_coll(), soid);
+          t.touch(coll_t::build_pg_coll(info.pgid), soid);
         }
        if (ssc->snapset.clones.size()) {
          snapid_t newest = *ssc->snapset.clones.rbegin();
@@ -1115,8 +1115,8 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
       { // write full object
        bufferlist nbl;
        bp.copy(op.length, nbl);
-       t.truncate(info.pgid.to_coll(), soid, 0);
-       t.write(info.pgid.to_coll(), soid, op.offset, op.length, nbl);
+       t.truncate(coll_t::build_pg_coll(info.pgid), soid, 0);
+       t.write(coll_t::build_pg_coll(info.pgid), soid, op.offset, op.length, nbl);
        if (ssc->snapset.clones.size()) {
          snapid_t newest = *ssc->snapset.clones.rbegin();
          ssc->snapset.clone_overlap.erase(newest);
@@ -1139,8 +1139,8 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
       { // zero
        assert(op.length);
        if (!ctx->obs->exists)
-         t.touch(info.pgid.to_coll(), soid);
-       t.zero(info.pgid.to_coll(), soid, op.offset, op.length);
+         t.touch(coll_t::build_pg_coll(info.pgid), soid);
+       t.zero(coll_t::build_pg_coll(info.pgid), soid, op.offset, op.length);
        if (ssc->snapset.clones.size()) {
          snapid_t newest = *ssc->snapset.clones.rbegin();
          interval_set<__u64> ch;
@@ -1159,7 +1159,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
        if (ctx->obs->exists && (flags & CEPH_OSD_OP_FLAG_EXCL))
           result = -EEXIST; /* this is an exclusive create */
         else {
-          t.touch(info.pgid.to_coll(), soid);
+          t.touch(coll_t::build_pg_coll(info.pgid), soid);
           ssc->snapset.head_exists = true;
         }
       }
@@ -1168,8 +1168,8 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
     case CEPH_OSD_OP_TRUNCATE:
       { // truncate
        if (!ctx->obs->exists)
-         t.touch(info.pgid.to_coll(), soid);
-       t.truncate(info.pgid.to_coll(), soid, op.offset);
+         t.touch(coll_t::build_pg_coll(info.pgid), soid);
+       t.truncate(coll_t::build_pg_coll(info.pgid), soid, op.offset);
        if (ssc->snapset.clones.size()) {
          snapid_t newest = *ssc->snapset.clones.rbegin();
          interval_set<__u64> trim;
@@ -1197,7 +1197,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
     
     case CEPH_OSD_OP_DELETE:
       { // delete
-       t.remove(info.pgid.to_coll(), soid);  // no clones, delete!
+       t.remove(coll_t::build_pg_coll(info.pgid), soid);  // no clones, delete!
        if (ssc->snapset.clones.size()) {
          snapid_t newest = *ssc->snapset.clones.rbegin();
          add_interval_usage(ssc->snapset.clone_overlap[newest], info.stats);
@@ -1221,15 +1221,15 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
     case CEPH_OSD_OP_SETXATTR:
       {
        if (!ctx->obs->exists)
-         t.touch(info.pgid.to_coll(), soid);
+         t.touch(coll_t::build_pg_coll(info.pgid), soid);
        nstring name(op.name_len + 1);
        name[0] = '_';
        bp.copy(op.name_len, name.data()+1);
        bufferlist bl;
        bp.copy(op.value_len, bl);
        if (!ctx->obs->exists)  // create object if it doesn't yet exist.
-         t.touch(info.pgid.to_coll(), soid);
-       t.setattr(info.pgid.to_coll(), soid, name, bl);
+         t.touch(coll_t::build_pg_coll(info.pgid), soid);
+       t.setattr(coll_t::build_pg_coll(info.pgid), soid, name, bl);
        ssc->snapset.head_exists = true;
        info.stats.num_wr++;
       }
@@ -1240,7 +1240,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops,
        nstring name(op.name_len + 1);
        name[0] = '_';
        bp.copy(op.name_len, name.data()+1);
-       t.rmattr(info.pgid.to_coll(), soid, name);
+       t.rmattr(coll_t::build_pg_coll(info.pgid), soid, name);
        info.stats.num_wr++;
       }
       break;
@@ -1613,8 +1613,8 @@ void ReplicatedPG::_make_clone(ObjectStore::Transaction& t,
   bufferlist bv;
   ::encode(*poi, bv);
 
-  t.clone(info.pgid.to_coll(), head, coid);
-  t.setattr(info.pgid.to_coll(), coid, OI_ATTR, bv);
+  t.clone(coll_t::build_pg_coll(info.pgid), head, coid);
+  t.setattr(coll_t::build_pg_coll(info.pgid), coid, OI_ATTR, bv);
 }
 
 void ReplicatedPG::make_writeable(OpContext *ctx)
@@ -1668,10 +1668,10 @@ void ReplicatedPG::make_writeable(OpContext *ctx)
     
     // add to snap bound collections
     coll_t fc = make_snap_collection(t, snaps[0]);
-    t.collection_add(fc, info.pgid.to_coll(), coid);
+    t.collection_add(fc, coll_t::build_pg_coll(info.pgid), coid);
     if (snaps.size() > 1) {
       coll_t lc = make_snap_collection(t, snaps[snaps.size()-1]);
-      t.collection_add(lc, info.pgid.to_coll(), coid);
+      t.collection_add(lc, coll_t::build_pg_coll(info.pgid), coid);
     }
     
     info.stats.num_objects++;
@@ -1746,15 +1746,15 @@ int ReplicatedPG::prepare_transaction(OpContext *ctx)
 
     bufferlist bv(sizeof(*poi));
     ::encode(*poi, bv);
-    ctx->op_t.setattr(info.pgid.to_coll(), soid, OI_ATTR, bv);
+    ctx->op_t.setattr(coll_t::build_pg_coll(info.pgid), soid, OI_ATTR, bv);
 
     dout(10) << " final snapset " << ctx->obs->ssc->snapset
             << " in " << soid << dendl;
-    ctx->op_t.setattr(info.pgid.to_coll(), soid, SS_ATTR, bss);   
+    ctx->op_t.setattr(coll_t::build_pg_coll(info.pgid), soid, SS_ATTR, bss);   
     if (!head_existed) {
       // if we logically recreated the head, remove old _snapdir object
       sobject_t snapoid(soid.oid, CEPH_SNAPDIR);
-      ctx->op_t.remove(info.pgid.to_coll(), snapoid);
+      ctx->op_t.remove(coll_t::build_pg_coll(info.pgid), snapoid);
       dout(10) << " removing old " << snapoid << dendl;
     }
   } else if (ctx->obs->ssc->snapset.clones.size()) {
@@ -1762,8 +1762,8 @@ int ReplicatedPG::prepare_transaction(OpContext *ctx)
     sobject_t snapoid(soid.oid, CEPH_SNAPDIR);
     dout(10) << " final snapset " << ctx->obs->ssc->snapset
             << " in " << snapoid << dendl;
-    ctx->op_t.touch(info.pgid.to_coll(), snapoid);
-    ctx->op_t.setattr(info.pgid.to_coll(), snapoid, SS_ATTR, bss);
+    ctx->op_t.touch(coll_t::build_pg_coll(info.pgid), snapoid);
+    ctx->op_t.setattr(coll_t::build_pg_coll(info.pgid), snapoid, SS_ATTR, bss);
   }
 
   // append to log
@@ -2093,7 +2093,7 @@ ReplicatedPG::ObjectContext *ReplicatedPG::get_object_context(const sobject_t& s
   } else {
     // check disk
     bufferlist bv;
-    int r = osd->store->getattr(info.pgid.to_coll(), soid, OI_ATTR, bv);
+    int r = osd->store->getattr(coll_t::build_pg_coll(info.pgid), soid, OI_ATTR, bv);
     if (r < 0 && !can_create)
       return 0;   // -ENOENT!
 
@@ -2237,12 +2237,12 @@ ReplicatedPG::SnapSetContext *ReplicatedPG::get_snapset_context(const object_t&
   } else {
     bufferlist bv;
     sobject_t head(oid, CEPH_NOSNAP);
-    int r = osd->store->getattr(info.pgid.to_coll(), head, SS_ATTR, bv);
+    int r = osd->store->getattr(coll_t::build_pg_coll(info.pgid), head, SS_ATTR, bv);
     if (r < 0) {
       // try _snapset
       sobject_t snapdir(oid, CEPH_SNAPDIR);
       bufferlist bv;
-      int r = osd->store->getattr(info.pgid.to_coll(), snapdir, SS_ATTR, bv);
+      int r = osd->store->getattr(coll_t::build_pg_coll(info.pgid), snapdir, SS_ATTR, bv);
       if (r < 0 && !can_create)
        return NULL;
     }
@@ -2322,8 +2322,8 @@ void ReplicatedPG::put_snapset_context(SnapSetContext *ssc)
     } else {
       // make sure i exist and am balanced, otherwise fw back to acker.
       bool b;
-      if (!osd->store->exists(info.pgid.to_coll(), soid) || 
-         osd->store->getattr(info.pgid.to_coll(), soid, "balance-reads", &b, 1) < 0) {
+      if (!osd->store->exists(coll_t::build_pg_coll(info.pgid), soid) || 
+         osd->store->getattr(coll_t::build_pg_coll(info.pgid), soid, "balance-reads", &b, 1) < 0) {
        dout(-10) << "read on replica, object " << soid 
                  << " dne or no balance-reads, fw back to primary" << dendl;
        osd->messenger->forward_message(op, osd->osdmap->get_inst(get_primary()));
@@ -2338,7 +2338,7 @@ void ReplicatedPG::put_snapset_context(SnapSetContext *ssc)
   // balance-reads set?
   char v;
   if ((op->get_op() != CEPH_OSD_OP_BALANCEREADS && op->get_op() != CEPH_OSD_OP_UNBALANCEREADS) &&
-      (osd->store->getattr(info.pgid.to_coll(), soid, "balance-reads", &v, 1) >= 0 ||
+      (osd->store->getattr(coll_t::build_pg_coll(info.pgid), soid, "balance-reads", &v, 1) >= 0 ||
        balancing_reads.count(soid.oid))) {
     
     if (!unbalancing_reads.count(soid.oid)) {
@@ -2592,7 +2592,7 @@ void ReplicatedPG::calc_head_subsets(SnapSet& snapset, const sobject_t& head,
           << " clone_overlap " << snapset.clone_overlap << dendl;
 
   struct stat st;
-  osd->store->stat(info.pgid.to_coll(), head, &st);
+  osd->store->stat(coll_t::build_pg_coll(info.pgid), head, &st);
 
   interval_set<__u64> cloning;
   interval_set<__u64> prev;
@@ -2786,14 +2786,14 @@ void ReplicatedPG::push_to_replica(const sobject_t& soid, int peer)
 
   // get size
   struct stat st;
-  int r = osd->store->stat(info.pgid.to_coll(), soid, &st);
+  int r = osd->store->stat(coll_t::build_pg_coll(info.pgid), soid, &st);
   assert(r == 0);
   
   map<sobject_t, interval_set<__u64> > clone_subsets;
   interval_set<__u64> data_subset;
 
   bufferlist bv;
-  r = osd->store->getattr(info.pgid.to_coll(), soid, OI_ATTR, bv);
+  r = osd->store->getattr(coll_t::build_pg_coll(info.pgid), soid, OI_ATTR, bv);
   assert(r >= 0);
   object_info_t oi(bv);
   
@@ -2866,7 +2866,7 @@ void ReplicatedPG::push(const sobject_t& soid, int peer,
 
   if (data_subset.size() || clone_subsets.size()) {
     struct stat st;
-    int r = osd->store->stat(info.pgid.to_coll(), soid, &st);
+    int r = osd->store->stat(coll_t::build_pg_coll(info.pgid), soid, &st);
     assert(r == 0);
     size = st.st_size;
 
@@ -2874,15 +2874,15 @@ void ReplicatedPG::push(const sobject_t& soid, int peer,
         p != data_subset.m.end();
         p++) {
       bufferlist bit;
-      osd->store->read(info.pgid.to_coll(), soid, p->first, p->second, bit);
+      osd->store->read(coll_t::build_pg_coll(info.pgid), soid, p->first, p->second, bit);
       bl.claim_append(bit);
     }
   } else {
-    osd->store->read(info.pgid.to_coll(), soid, 0, 0, bl);
+    osd->store->read(coll_t::build_pg_coll(info.pgid), soid, 0, 0, bl);
     size = bl.length();
   }
 
-  osd->store->getattrs(info.pgid.to_coll(), soid, attrset);
+  osd->store->getattrs(coll_t::build_pg_coll(info.pgid), soid, attrset);
 
   bufferlist bv;
   bv.push_back(attrset[OI_ATTR]);
@@ -3103,7 +3103,7 @@ void ReplicatedPG::sub_op_push(MOSDSubOp *op)
 
   // write object and add it to the PG
   ObjectStore::Transaction t;
-  t.remove(info.pgid.to_coll(), soid);  // in case old version exists
+  t.remove(coll_t::build_pg_coll(info.pgid), soid);  // in case old version exists
 
   __u64 boff = 0;
   for (map<sobject_t, interval_set<__u64> >::iterator p = clone_subsets.begin();
@@ -3113,22 +3113,22 @@ void ReplicatedPG::sub_op_push(MOSDSubOp *op)
         q != p->second.m.end(); 
         q++) {
       dout(15) << " clone_range " << p->first << " " << q->first << "~" << q->second << dendl;
-      t.clone_range(info.pgid.to_coll(), soid, p->first, q->first, q->second);
+      t.clone_range(coll_t::build_pg_coll(info.pgid), soid, p->first, q->first, q->second);
     }
   for (map<__u64,__u64>::iterator p = data_subset.m.begin();
        p != data_subset.m.end(); 
        p++) {
     bufferlist bit;
     bit.substr_of(data, boff, p->second);
-    t.write(info.pgid.to_coll(), soid, p->first, p->second, bit);
+    t.write(coll_t::build_pg_coll(info.pgid), soid, p->first, p->second, bit);
     dout(15) << " write " << p->first << "~" << p->second << dendl;
     boff += p->second;
   }
 
   if (data_subset.empty())
-    t.touch(info.pgid.to_coll(), soid);
+    t.touch(coll_t::build_pg_coll(info.pgid), soid);
 
-  t.setattrs(info.pgid.to_coll(), soid, op->attrset);
+  t.setattrs(coll_t::build_pg_coll(info.pgid), soid, op->attrset);
   if (soid.snap && soid.snap < CEPH_NOSNAP &&
       op->attrset.count(OI_ATTR)) {
     bufferlist bl;
@@ -3136,10 +3136,10 @@ void ReplicatedPG::sub_op_push(MOSDSubOp *op)
     object_info_t oi(bl);
     if (oi.snaps.size()) {
       coll_t lc = make_snap_collection(t, oi.snaps[0]);
-      t.collection_add(lc, info.pgid.to_coll(), soid);
+      t.collection_add(lc, coll_t::build_pg_coll(info.pgid), soid);
       if (oi.snaps.size() > 1) {
        coll_t hc = make_snap_collection(t, oi.snaps[oi.snaps.size()-1]);
-       t.collection_add(hc, info.pgid.to_coll(), soid);
+       t.collection_add(hc, coll_t::build_pg_coll(info.pgid), soid);
       }
     }
   }
@@ -3511,7 +3511,7 @@ void ReplicatedPG::clean_up_local(ObjectStore::Transaction& t)
     
     // be thorough.
     vector<sobject_t> ls;
-    osd->store->collection_list(info.pgid.to_coll(), ls);
+    osd->store->collection_list(coll_t::build_pg_coll(info.pgid), ls);
     if (ls.size() != info.stats.num_objects)
       dout(10) << " WARNING: " << ls.size() << " != num_objects " << info.stats.num_objects << dendl;
 
@@ -3533,7 +3533,7 @@ void ReplicatedPG::clean_up_local(ObjectStore::Transaction& t)
         if (s.count(p->soid)) {
           dout(10) << " deleting " << p->soid
                    << " when " << p->version << dendl;
-          t.remove(info.pgid.to_coll(), p->soid);
+          t.remove(coll_t::build_pg_coll(info.pgid), p->soid);
         }
         s.erase(p->soid);
       } else {
@@ -3546,7 +3546,7 @@ void ReplicatedPG::clean_up_local(ObjectStore::Transaction& t)
          i != s.end();
          i++) {
       dout(10) << " deleting stray " << *i << dendl;
-      t.remove(info.pgid.to_coll(), *i);
+      t.remove(coll_t::build_pg_coll(info.pgid), *i);
     }
 
   } else {
@@ -3561,7 +3561,7 @@ void ReplicatedPG::clean_up_local(ObjectStore::Transaction& t)
       if (p->is_delete()) {
         dout(10) << " deleting " << p->soid
                  << " when " << p->version << dendl;
-        t.remove(info.pgid.to_coll(), p->soid);
+        t.remove(coll_t::build_pg_coll(info.pgid), p->soid);
       } else {
         // keep old(+missing) objects, just for kicks.
       }
@@ -3580,7 +3580,7 @@ int ReplicatedPG::_scrub(ScrubMap& scrubmap, int& errors, int& fixed)
 {
   dout(10) << "_scrub" << dendl;
 
-  coll_t c = info.pgid.to_coll();
+  coll_t c = coll_t::build_pg_coll(info.pgid);
   bool repair = state_test(PG_STATE_REPAIR);
   const char *mode = repair ? "repair":"scrub";
 
index cd6077b6ce64a9ea9864f523a32f7e621403c485..0451daf71fddc25645ddf6f085f706d3b75b64e6 100644 (file)
@@ -130,22 +130,32 @@ struct pg_t {
   
   operator uint64_t() const { return u.pg64; }
 
-  coll_t to_coll() const {
+  /*coll_t to_coll() const {
     return coll_t(u.pg64, 0); 
   }
   coll_t to_snap_coll(snapid_t sn) const {
     return coll_t(u.pg64, sn);
-  }
+    }*/
 
+  int print(char *o) {
+    if (preferred() >= 0)
+      return sprintf(o, "%d.%xp%d", pool(), ps(), preferred());
+    else
+      return sprintf(o, "%d.%x", pool(), ps());
+  }
   bool parse(const char *s) {
     int pool;
     int ps;
-    int r = sscanf(s, "%d.%x", &pool, &ps);
+    int preferred;
+    int r = sscanf(s, "%d.%xp%x", &pool, &ps, &preferred);
     if (r < 2)
       return false;
     u.pg.pool = pool;
     u.pg.ps = ps;
-    u.pg.preferred = -1;
+    if (r == 3)
+      u.pg.preferred = preferred;
+    else
+      u.pg.preferred = -1;
     return true;
   }
 
@@ -183,6 +193,94 @@ namespace __gnu_cxx {
 }
 
 
+// ----------------------
+
+struct coll_t {
+  pg_t pgid;
+  snapid_t snap;
+
+  coll_t(__u64 p=0, snapid_t s=0) : pgid(p), snap(s) {}
+  
+  static coll_t build_pg_coll(pg_t p) {
+    return coll_t(p, CEPH_NOSNAP);
+  }
+  static coll_t build_snap_pg_coll(pg_t p, snapid_t s) {
+    return coll_t(p, s);
+  }
+
+  int print(char *o) {
+    if (pgid == pg_t() && snap == 0)
+      return sprintf(o, "meta");
+    int len = pgid.print(o);
+    if (snap != CEPH_NOSNAP)
+      len += sprintf(o+len, "_%llx", (long long unsigned)snap);
+    else {
+      strcat(o+len, "_head");
+      len += 5;
+    }
+    return len;
+  }
+  bool parse(char *s) {
+    if (strncmp(s, "meta", 4) == 0) {
+      *this = coll_t();
+      return true;
+    }
+    if (!pgid.parse(s))
+      return false;
+    char *sn = strchr(s, '_');
+    if (!sn)
+      return false;
+    if (strncmp(sn, "_head", 5) == 0)
+      snap = CEPH_NOSNAP;
+    else
+      snap = strtoull(sn+1, 0, 16);
+    return true;
+  }
+
+  void encode(bufferlist& bl) const {
+    ::encode(pgid, bl);
+    ::encode(snap, bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    ::decode(pgid, bl);
+    ::decode(snap, bl);
+  }
+};
+WRITE_CLASS_ENCODER(coll_t)
+
+inline ostream& operator<<(ostream& out, const coll_t& c) {
+  return out << hex << c.pgid << '_' << c.snap << dec;
+}
+
+inline bool operator<(const coll_t& l, const coll_t& r) {
+  return l.pgid < r.pgid || (l.pgid == r.pgid && l.snap < r.snap);
+}
+inline bool operator<=(const coll_t& l, const coll_t& r) {
+  return l.pgid < r.pgid || (l.pgid == r.pgid && l.snap <= r.snap);
+}
+inline bool operator==(const coll_t& l, const coll_t& r) {
+  return l.pgid == r.pgid && l.snap == r.snap;
+}
+inline bool operator!=(const coll_t& l, const coll_t& r) {
+  return l.pgid != r.pgid || l.snap != r.snap;
+}
+inline bool operator>(const coll_t& l, const coll_t& r) {
+  return l.pgid > r.pgid || (l.pgid == r.pgid && l.snap > r.snap);
+}
+inline bool operator>=(const coll_t& l, const coll_t& r) {
+  return l.pgid > r.pgid || (l.pgid == r.pgid && l.snap >= r.snap);
+}
+
+namespace __gnu_cxx {
+  template<> struct hash<coll_t> {
+    size_t operator()(const coll_t &c) const { 
+      static rjhash<uint32_t> H;
+      static rjhash<uint64_t> I;
+      return H(c.pgid) ^ I(c.snap);
+    }
+  };
+}
+