]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rados: include pool_snap_info in pg_pools
authorSage Weil <sage@newdream.net>
Fri, 5 Jun 2009 04:03:41 +0000 (21:03 -0700)
committerSage Weil <sage@newdream.net>
Fri, 5 Jun 2009 04:03:41 +0000 (21:03 -0700)
Include info about snaps global to each pg_pool in the pg_pool_t (and
thus OSDMap).  These snap contexts will be used when a snapc is not
explicitly specified by the client.

Note that the pool-wide snaps are (presently) mutually exclusive with
client-controlls snaps (as used by ceph) because a mixture of @snaps and
@removed_snaps doesn't clearly defined which snaps do not exist (they
share the namespace).

src/include/encoding.h
src/include/interval_set.h
src/include/rados.h
src/include/types.h
src/osd/osd_types.h

index 4115da802940fb9908a3c05e420d1334be566140..5fbea1802a897d4a7c02efb8cf61b517c9fe372c 100644 (file)
@@ -351,6 +351,24 @@ inline void decode(std::map<T,U>& m, bufferlist::iterator& p)
     decode(m[k], p);
   }
 }
+template<class T, class U>
+inline void encode_nohead(const std::map<T,U>& m, bufferlist& bl)
+{
+  for (typename std::map<T,U>::const_iterator p = m.begin(); p != m.end(); ++p) {
+    encode(p->first, bl);
+    encode(p->second, bl);
+  }
+}
+template<class T, class U>
+inline void decode_nohead(int n, std::map<T,U>& m, bufferlist::iterator& p)
+{
+  m.clear();
+  while (n--) {
+    T k;
+    decode(k, p);
+    decode(m[k], p);
+  }
+}
 
 // multimap
 template<class T, class U>
index 65f18c948c70551cf35d6c6aed6231d234b006cd..8fd7f65bc7dad8552967c9811e25100ca1c8d1dd 100644 (file)
@@ -96,6 +96,9 @@ class interval_set {
   void encode(bufferlist& bl) const {
     ::encode(m, bl);
   }
+  void encode_nohead(bufferlist& bl) const {
+    ::encode_nohead(m, bl);
+  }
   void decode(bufferlist::iterator& bl) {
     ::decode(m, bl);
     _size = 0;
@@ -104,6 +107,14 @@ class interval_set {
          p++)
       _size += p->second;
   }
+  void decode_nohead(int n, bufferlist::iterator& bl) {
+    ::decode_nohead(n, m, bl);
+    _size = 0;
+    for (typename map<T,T>::const_iterator p = m.begin();
+         p != m.end();
+         p++)
+      _size += p->second;
+  }
 
   void clear() {
     m.clear();
index 5b75b02e3a7ada35fa1307eb239ba6ca7ad14cd7..b01ef8bf06af787ed383e69573d8e70a52c10928 100644 (file)
@@ -1,3 +1,6 @@
+// -*- mode:C; tab-width:8; c-basic-offset:8; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=8 smarttab
+
 #ifndef __RADOS_H
 #define __RADOS_H
 
@@ -91,6 +94,10 @@ struct ceph_pg_pool {
        __le32 pg_num, pgp_num;
        __le32 lpg_num, lpgp_num;
        __le32 last_change;     /* most recent epoch changed */
+       __le64 snap_seq;
+       __le32 snap_epoch;
+       __le32 num_snaps;
+       __le32 num_removed_snap_intervals;
 } __attribute__ ((packed));
 
 /*
index 47f816c2ddbb059d4b0e74d9ef02f3eb73fde3ed..709668ee155f7f9ecc90250cbd1ac888795a3082 100644 (file)
@@ -325,6 +325,9 @@ struct SnapContext {
   snapid_t seq;            // 'time' stamp
   vector<snapid_t> snaps;  // existent snaps, in descending order
 
+  SnapContext() {}
+  SnapContext(snapid_t s, vector<snapid_t>& v) : seq(s), snaps(v) {}    
+
   void clear() {
     seq = 0;
     snaps.clear();
index 69e457b9a83e60a2a15794a028e9fbb99fb8d321..fbf1f08366159720f3d1cec7820c5006972e7674 100644 (file)
@@ -379,15 +379,65 @@ static inline std::string pg_state_string(int state) {
 }
 
 
+/*
+ * pool_snap_info_t
+ *
+ * attributes for a single pool snapshot.  
+ */
+struct pool_snap_info_t {
+  snapid_t snapid;
+  utime_t stamp;
+  nstring name;
+
+  void encode(bufferlist& bl) const {
+    ::encode(snapid, bl);
+    ::encode(stamp, bl);
+    ::encode(name, bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    ::decode(snapid, bl);
+    ::decode(stamp, bl);
+    ::decode(name, bl);
+  }
+};
+WRITE_CLASS_ENCODER(pool_snap_info_t)
+
+inline ostream& operator<<(ostream& out, const pool_snap_info_t& si) {
+  return out << si.snapid << '(' << si.name << ' ' << si.stamp << ')';
+}
 
 
 /*
  * pg_pool
  */
 struct pg_pool_t {
-  ceph_pg_pool v;
+  mutable ceph_pg_pool v;
   int pg_num_mask, pgp_num_mask, lpg_num_mask, lpgp_num_mask;
 
+  /*
+   * Pool snaps (global to this pool).  These define a SnapContext for
+   * the pool, unless the client manually specifies an alternate
+   * context.
+   */
+  map<snapid_t, pool_snap_info_t> snaps;
+  /*
+   * Alternatively, if we are definining non-pool snaps (e.g. via the
+   * Ceph MDS), we must track @removed_snaps (since @snaps is not
+   * used).  Snaps and removed_snaps are to be used exclusive of each
+   * other!
+   */
+  interval_set<snapid_t> removed_snaps;
+
+  unsigned get_type() const { return v.type; }
+  unsigned get_size() const { return v.size; }
+  int get_crush_ruleset() const { return v.crush_ruleset; }
+  epoch_t get_last_change() const { return v.last_change; }
+  epoch_t get_snap_epoch() const { return v.snap_epoch; }
+  snapid_t get_snap_seq() const { return snapid_t(v.snap_seq); }
+
+  bool is_rep()   const { return get_type() == CEPH_PG_TYPE_REP; }
+  bool is_raid4() const { return get_type() == CEPH_PG_TYPE_RAID4; }
+
   int get_pg_num() const { return v.pg_num; }
   int get_pgp_num() const { return v.pgp_num; }
   int get_lpg_num() const { return v.lpg_num; }
@@ -406,15 +456,6 @@ struct pg_pool_t {
     }
     return b;
   }
-
-  unsigned get_type() const { return v.type; }
-  unsigned get_size() const { return v.size; }
-  int get_crush_ruleset() const { return v.crush_ruleset; }
-  epoch_t get_last_change() const { return v.last_change; }
-
-  bool is_rep()   const { return get_type() == CEPH_PG_TYPE_REP; }
-  bool is_raid4() const { return get_type() == CEPH_PG_TYPE_RAID4; }
-
   void calc_pg_masks() {
     pg_num_mask = (1 << calc_bits_of(v.pg_num-1)) - 1;
     pgp_num_mask = (1 << calc_bits_of(v.pgp_num-1)) - 1;
@@ -422,6 +463,21 @@ struct pg_pool_t {
     lpgp_num_mask = (1 << calc_bits_of(v.lpgp_num-1)) - 1;
   }
 
+  bool is_removed_snap(snapid_t s) {
+    if (snaps.size())
+      return snaps.count(s) == 0;
+    return s <= get_snap_seq() && removed_snaps.contains(s);
+  }
+  SnapContext get_snap_context() const {
+    vector<snapid_t> s(snaps.size());
+    unsigned i = 0;
+    for (map<snapid_t, pool_snap_info_t>::const_reverse_iterator p = snaps.rbegin();
+        p != snaps.rend();
+        p++)
+      s[i++] = p->first;
+    return SnapContext(get_snap_seq(), s);
+  }
+
   /*
    * map a raw pg (with full precision ps) into an actual pg, for storage
    */
@@ -444,10 +500,16 @@ struct pg_pool_t {
   }
 
   void encode(bufferlist& bl) const {
+    v.num_snaps = snaps.size();
+    v.num_removed_snap_intervals = removed_snaps.m.size();
     ::encode(v, bl);
+    ::encode_nohead(snaps, bl);
+    removed_snaps.encode_nohead(bl);
   }
   void decode(bufferlist::iterator& bl) {
     ::decode(v, bl);
+    ::decode_nohead(v.num_snaps, snaps, bl);
+    removed_snaps.decode_nohead(v.num_removed_snap_intervals, bl);
     calc_pg_masks();
   }
 };