From: Sage Weil Date: Sat, 1 Nov 2014 04:29:42 +0000 (-0700) Subject: buffer: implement list::get_contiguous X-Git-Tag: v0.89~70^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a554766338a5ad7e4ba4f57aa2744eb65e4251ef;p=ceph.git buffer: implement list::get_contiguous 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 --- diff --git a/src/common/buffer.cc b/src/common/buffer.cc index aa201b7b2064..cd4344170989 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -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::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::const_iterator curbuf = other._buffers.begin(); while (off > 0 && diff --git a/src/include/buffer.h b/src/include/buffer.h index 3cd0a7a19a07..7f23f8db4408 100644 --- a/src/include/buffer.h +++ b/src/include/buffer.h @@ -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; diff --git a/src/test/bufferlist.cc b/src/test/bufferlist.cc index f1caeff7c77e..d2bd8c9c1987 100644 --- a/src/test/bufferlist.cc +++ b/src/test/bufferlist.cc @@ -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');