]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
objectcacher: add is_cached method
authorSage Weil <sage@newdream.net>
Fri, 4 Sep 2009 22:09:59 +0000 (15:09 -0700)
committerSage Weil <sage@newdream.net>
Fri, 4 Sep 2009 22:09:59 +0000 (15:09 -0700)
Helps us see what we have cached...

src/osdc/ObjectCacher.cc
src/osdc/ObjectCacher.h

index 96ecf002ed8e95ae8cba972cff9974eddc374bcb..6418a9b810a41f0376394acd2ecc10b22474f18e 100644 (file)
@@ -126,6 +126,40 @@ void ObjectCacher::Object::try_merge_bh(BufferHead *bh)
     merge_left(bh, p->second);
 }
 
+/*
+ * count bytes we have cached in given range
+ */
+bool ObjectCacher::Object::is_cached(loff_t cur, loff_t left)
+{
+  map<loff_t, BufferHead*>::iterator p = data.lower_bound(cur);
+  
+  if (p != data.begin() && 
+      (p == data.end() || p->first > cur)) {
+    p--;     // might overlap!
+    if (p->first + p->second->length() <= cur) 
+      p++;   // doesn't overlap.
+  }
+  
+  while (left > 0) {
+    if (p == data.end())
+      return false;
+
+    if (p->first <= cur) {
+      // have part of it
+      loff_t lenfromcur = MIN(p->second->end() - cur, left);
+      cur += lenfromcur;
+      left -= lenfromcur;
+      p++;
+      continue;
+    } else if (p->first > cur) {
+      // gap
+      return false;
+    } else
+      assert(0);
+  }
+
+  return true;
+}
 
 /*
  * map a range of bytes into buffer_heads.
@@ -748,6 +782,25 @@ void ObjectCacher::trim(loff_t max)
 
 /* public */
 
+bool ObjectCacher::is_cached(inodeno_t ino, vector<ObjectExtent>& extents, snapid_t snapid)
+{
+  for (vector<ObjectExtent>::iterator ex_it = extents.begin();
+       ex_it != extents.end();
+       ex_it++) {
+    dout(10) << "is_cached " << *ex_it << dendl;
+
+    // get Object cache
+    sobject_t soid(ex_it->oid, snapid);
+    Object *o = get_object_maybe(soid, ino, ex_it->layout);
+    if (!o)
+      return false;
+    if (!o->is_cached(ex_it->offset, ex_it->length))
+      return false;
+  }
+  return true;
+}
+
+
 /*
  * returns # bytes read (if in cache).  onfinish is untouched (caller must delete it)
  * returns 0 if doing async read
@@ -1569,6 +1622,38 @@ loff_t ObjectCacher::release_set(inodeno_t ino)
   return unclean;
 }
 
+
+__u64 ObjectCacher::release_all()
+{
+  dout(10) << "release_all" << dendl;
+  __u64 unclean = 0;
+  
+  hash_map<sobject_t, Object*>::iterator p = objects.begin();
+  while (p != objects.end()) {
+    hash_map<sobject_t, Object*>::iterator n = p;
+    n++;
+
+    Object *ob = p->second;
+
+    loff_t o_unclean = release(ob);
+    unclean += o_unclean;
+
+    if (o_unclean) 
+      dout(10) << "release_all " << *ob 
+               << " has " << o_unclean << " bytes left"
+               << dendl;
+  }
+
+  if (unclean) {
+    dout(10) << "release_all unclean " << unclean << " bytes left" << dendl;
+  }
+
+  return unclean;
+}
+
+
+
+
 void ObjectCacher::truncate_set(inodeno_t ino, vector<ObjectExtent>& exls)
 {
   if (objects_by_ino.count(ino) == 0) {
index 1b6ac910bec74fd7170de7d1d98c7e5b93c08cda..19422c3e33f777ecd767a08e74aaefc74be6ac67 100644 (file)
@@ -224,6 +224,7 @@ class ObjectCacher {
     void merge_left(BufferHead *left, BufferHead *right);
     void try_merge_bh(BufferHead *bh);
 
+    bool is_cached(loff_t off, loff_t len);
     int map_read(OSDRead *rd,
                  map<loff_t, BufferHead*>& hits,
                  map<loff_t, BufferHead*>& missing,
@@ -269,6 +270,13 @@ class ObjectCacher {
   
 
   // objects
+  Object *get_object_maybe(sobject_t oid, inodeno_t ino, ceph_object_layout &l) {
+    // have it?
+    if (objects.count(oid))
+      return objects[oid];
+    return NULL;
+  }
+
   Object *get_object(sobject_t oid, inodeno_t ino, ceph_object_layout &l) {
     // have it?
     if (objects.count(oid))
@@ -514,6 +522,7 @@ class ObjectCacher {
   // non-blocking.  async.
   int readx(OSDRead *rd, inodeno_t ino, Context *onfinish);
   int writex(OSDWrite *wr, inodeno_t ino);
+  bool is_cached(inodeno_t ino, vector<ObjectExtent>& extents, snapid_t snapid);
 
   // write blocking
   bool wait_for_write(size_t len, Mutex& lock);
@@ -534,6 +543,7 @@ class ObjectCacher {
   void purge_set(inodeno_t ino);
 
   loff_t release_set(inodeno_t ino);  // returns # of bytes not released (ie non-clean)
+  __u64 release_all();
 
   void truncate_set(inodeno_t ino, vector<ObjectExtent>& ex);
 
@@ -544,6 +554,13 @@ class ObjectCacher {
   // file functions
 
   /*** async+caching (non-blocking) file interface ***/
+  int file_is_cached(inodeno_t ino, ceph_file_layout *layout, snapid_t snapid,
+                    loff_t offset, size_t len) {
+    vector<ObjectExtent> extents;
+    filer.file_to_extents(ino, layout, offset, len, extents);
+    return is_cached(ino, extents, snapid);
+  }
+
   int file_read(inodeno_t ino, ceph_file_layout *layout, snapid_t snapid,
                 loff_t offset, size_t len, 
                 bufferlist *bl,