]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Added Files:
authorcarlosm <carlosm@29311d96-e01e-0410-9327-a35deaab8ce9>
Wed, 8 Jun 2005 06:28:10 +0000 (06:28 +0000)
committercarlosm <carlosm@29311d96-e01e-0410-9327-a35deaab8ce9>
Wed, 8 Jun 2005 06:28:10 +0000 (06:28 +0000)
  buffercache.h

git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@282 29311d96-e01e-0410-9327-a35deaab8ce9

ceph/client/buffercache.h [new file with mode: 0644]

diff --git a/ceph/client/buffercache.h b/ceph/client/buffercache.h
new file mode 100644 (file)
index 0000000..f8a0a05
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef __BUFFERCACHE_H
+#define __BUFFERCACHE_H
+
+#include "include/buffer.h"
+#include "include/bufferlist.h"
+#include "include/lru.h"
+
+/** map<off_t, bufferptr> buffer_map;
+
+for writes:
+
+void map_or_alloc(size_t len, off_t off, bufferlist &blist);
+- build a bufferlist that includes bufferptr's for existing buffers 
+  in the map and (if necessary) newly allocated ones.  caller can then use
+
+  blist.copy_from(int off, int len, char *buf);
+
+  to copy data into the bufferlist.  (copy() copies data _out_, and append appends, 
+  but copy_from or copy_into or whatever doesn't exist yet.)
+
+
+  for reads:
+  void map_existing(size_t len, off_t off, map<off_t, bufferlist>& hits, map<off_t, size_t>& holes)
+  
+- gives caller map of hits and holes.
+
+
+both of those could be wrapped up in a tidy class, aside from 2 things:
+
+- buffers need to be put in an lru of some sort with last_accessed etc. 
+  so we can flush them intelligently
+
+- maybe the buffers should be allocated w/ fixed size?  for writes at least, 
+  the new buffers can always be created as 256k (or whatever) and the bufferptrs 
+  that reference them (in buffer_map) will point to the relevant substring.  
+  the map_or_alloc() bit just needs to be smart then to check the underlying 
+  buffer's alloc'd size and adjust those subsets as necessary.
+
+  for reads, we'll be getting buffers of weird sizes coming from osds, 
+  so the cache should work with weird sized buffers regardless.  
+  (even if we always prefetch large blocks, files tails will come back small.)
+
+
+  so somewhere in there there should be a buffer_head struct or something. maybe it shoudl be
+
+  map<off_t, bufferhead> buffer_map;
+
+  we can reuse the LRU (include/lru.h) thinger to handle lru stuff pretty easily. 
+  maybe
+
+  class bufferhead : public LRUObject {
+  bufferptr bptr;
+  time_t    last_written;
+  int       state;  // clean, dirty, writing, reading
+  };
+
+gets weird too if say multiple reads are issued on the same (or overlapping) ranges of bytes.. 
+only want to submit a single read request.
+
+s
+*/
+
+// bufferhead states
+#define BUFHD_STATE_CLEAN      1
+#define BUFHD_STATE_DIRTY      2
+#define BUFHD_STATE_WRITING    3
+#define BUFHD_STATE_READING    4
+
+class bufferhead : public LRUObject {
+  bufferptr    bptr;
+  time_t       last_written;
+  int          state;
+};
+
+class buffercache {
+ private:
+  map<off_t, bufferhead> buffer_map;
+  
+  map<off_t, bufferhead>::iterator overlap(size_t len, off_t off)
+  {
+    // returns iterator to buffer overlapping specified extent or end() if no overlap exists
+    map<off_t, bufferhead>::iterator it = buffer_map.lower_bound(off);
+    if (it == buffer_map.end() || (*it)->first < off + len) {
+      return it;
+    } else if (it == buffer_map.begin()) {
+      return buffer_map.end();
+    } else {
+      --it;
+      if ((*it)->first + (*it)->second.bptr.length() > off) {
+        return it;
+      } else {
+        return buffer_map.end();
+      }
+    }
+  }
+
+ public:
+  /* for writes
+     build a bufferlist that includes bufferptr's for existing buffers 
+     in the map and (if necessary) newly allocated ones.  caller can then use
+        
+        blist.copy_from(int off, int len, char *buf);
+        
+        to copy data into the bufferlist. (copy() copies data _out_, and append appends, 
+        but copy_from or copy_into or whatever doesn't exist yet.)
+  */
+  void map_or_alloc(size_t len, off_t off, bufferlist &blist)
+  {
+  }
+
+  /* for reads
+     gives caller maps of hits and holes
+  */
+  void map_existing(size_t len, off_t off, map<off_t, bufferhead>& hits, map<off_t, size_t>& holes)
+  {
+    off_t next_off = off;
+    for (map<off_t, bufferhead>::iterator it = overlap(len, off);
+         it != buffer_map.end() && (*it)->first < off + len;
+         it++) {
+      if ((*it)->first > next_off) {
+        holes[next_off] = (size_t) ((*it)->first - next_off);
+      }
+      hits[(*it)->first] = (*it)->second;
+      next_off = (*it)->first + (*it)->second.bptr.length();
+    }
+    if (next_off < off + len) {
+      holes[next_off] = (size_t) (off + len - next_off);
+    }
+  }
+};
+
+#endif
+