From a554766338a5ad7e4ba4f57aa2744eb65e4251ef Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 31 Oct 2014 21:29:42 -0700 Subject: [PATCH] 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 --- src/common/buffer.cc | 23 ++++++++++++++++++++++- src/include/buffer.h | 5 +++++ src/test/bufferlist.cc | 17 +++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) 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'); -- 2.47.3