]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
buffer: implement list::get_contiguous 2849/head
authorSage Weil <sage@redhat.com>
Sat, 1 Nov 2014 04:29:42 +0000 (21:29 -0700)
committerSage Weil <sage@redhat.com>
Sat, 1 Nov 2014 04:29:42 +0000 (21:29 -0700)
Return a pointer to a contiguous range of the bufferlist, rebuilding
into a contiguous region as needed.  For now, if we need to rebuild,
we just do the whole thing.  We can obviously optimize this later to
rebuild on the necessary region, but this is good enough for the
(presumably) common case where the needed region is already in fact
contiguous.

Signed-off-by: Sage Weil <sage@redhat.com>
src/common/buffer.cc
src/include/buffer.h
src/test/bufferlist.cc

index aa201b7b206454ef70641e9f6ab0caf98e4d6927..cd434417098992f444f122b02c4ecee712550023 100644 (file)
@@ -1353,13 +1353,34 @@ void buffer::list::rebuild_page_aligned()
     return _buffers.front().c_str();  // good, we're already contiguous.
   }
 
+  char *buffer::list::get_contiguous(unsigned orig_off, unsigned len)
+  {
+    if (orig_off + len > length())
+      throw end_of_buffer();
+
+    unsigned off = orig_off;
+    std::list<ptr>::iterator curbuf = _buffers.begin();
+    while (off > 0 && off >= curbuf->length()) {
+      off -= curbuf->length();
+      ++curbuf;
+    }
+
+    if (off + len > curbuf->length()) {
+      // FIXME we'll just rebuild the whole list for now.
+      rebuild();
+      return c_str() + orig_off;
+    }
+
+    return curbuf->c_str() + off;
+  }
+
   void buffer::list::substr_of(const list& other, unsigned off, unsigned len)
   {
     if (off + len > other.length())
       throw end_of_buffer();
 
     clear();
-      
+
     // skip off
     std::list<ptr>::const_iterator curbuf = other._buffers.begin();
     while (off > 0 &&
index 3cd0a7a19a0727447bd6f9d7bf3de16a86a31674..7f23f8db44081c0b69094d4bb70460753ad6d721 100644 (file)
@@ -433,6 +433,11 @@ public:
     char *c_str();
     void substr_of(const list& other, unsigned off, unsigned len);
 
+    /// return a pointer to a contiguous extent of the buffer,
+    /// reallocating as needed
+    char *get_contiguous(unsigned off,  ///< offset
+                        unsigned len); ///< length
+
     // funky modifer
     void splice(unsigned off, unsigned len, list *claim_by=0 /*, bufferlist& replace_with */);
     void write(int off, int len, std::ostream& out) const;
index f1caeff7c77e4ec2f1632943f51af6c29b1b9131..d2bd8c9c1987c781ff23ebcca72d224088b53f1b 100644 (file)
@@ -1076,6 +1076,23 @@ TEST(BufferList, buffers) {
   ASSERT_EQ((unsigned)1, bl.buffers().size());
 }
 
+TEST(BufferList, get_contiguous) {
+  bufferptr a("foobarbaz", 9);
+  bufferptr b("123456789", 9);
+  bufferptr c("ABCDEFGHI", 9);
+  bufferlist bl;
+  bl.append(a);
+  bl.append(b);
+  bl.append(c);
+  ASSERT_EQ(3, bl.buffers().size());
+  ASSERT_EQ(0, memcmp("bar", bl.get_contiguous(3, 3), 3));
+  ASSERT_EQ(0, memcmp("456", bl.get_contiguous(12, 3), 3));
+  ASSERT_EQ(0, memcmp("ABC", bl.get_contiguous(18, 3), 3));
+  ASSERT_EQ(3, bl.buffers().size());
+  ASSERT_EQ(0, memcmp("789ABC", bl.get_contiguous(15, 6), 6));
+  ASSERT_LT(bl.buffers().size(), 3);
+}
+
 TEST(BufferList, swap) {
   bufferlist b1;
   b1.append('A');