From 5667f45e4b2879ebb0d64418d82c0c2d5afc4204 Mon Sep 17 00:00:00 2001 From: Adam Simpkins Date: Wed, 14 Jan 2015 16:00:31 -0800 Subject: [PATCH] add IOBuf::appendToIov() Summary: This splits out some code from the existing getIov() method, to support appending to an existing iovec array, rather than always returning a new one. I have a use case where I have multiple IOBuf chains to write at once, preceded by some header data. appendToIov() makes it easier to populate a single iovec array with this data, and then perform a single writev() call. Test Plan: Updated the unit tests to exercise appendToIov() Reviewed By: jasmeetbagga@fb.com Subscribers: trunkagent, doug, exa, net-systems@, folly-diffs@ FB internal diff: D1783090 Tasks: Signature: t1:1783090:1421450476:d5c89d6e1adbd2f2239057238e020b302df09f23 Blame Revision: --- folly/io/IOBuf.cpp | 8 ++++++-- folly/io/IOBuf.h | 11 +++++++++++ folly/io/test/IOBufTest.cpp | 13 +++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/folly/io/IOBuf.cpp b/folly/io/IOBuf.cpp index 90517aea..33e848ba 100644 --- a/folly/io/IOBuf.cpp +++ b/folly/io/IOBuf.cpp @@ -870,15 +870,19 @@ IOBuf::Iterator IOBuf::cend() const { folly::fbvector IOBuf::getIov() const { folly::fbvector iov; iov.reserve(countChainElements()); + appendToIov(&iov); + return iov; +} + +void IOBuf::appendToIov(folly::fbvector* iov) const { IOBuf const* p = this; do { // some code can get confused by empty iovs, so skip them if (p->length() > 0) { - iov.push_back({(void*)p->data(), folly::to(p->length())}); + iov->push_back({(void*)p->data(), folly::to(p->length())}); } p = p->next(); } while (p != this); - return iov; } size_t IOBufHash::operator()(const IOBuf& buf) const { diff --git a/folly/io/IOBuf.h b/folly/io/IOBuf.h index dccd57b0..3513798b 100644 --- a/folly/io/IOBuf.h +++ b/folly/io/IOBuf.h @@ -1041,6 +1041,17 @@ class IOBuf { */ folly::fbvector getIov() const; + /** + * Update an existing iovec array with the IOBuf data. + * + * New iovecs will be appended to the existing vector; anything already + * present in the vector will be left unchanged. + * + * Naturally, the returned iovec data will be invalid if you modify the + * buffer chain. + */ + void appendToIov(folly::fbvector* iov) const; + /* * Overridden operator new and delete. * These perform specialized memory management to help support diff --git a/folly/io/test/IOBufTest.cpp b/folly/io/test/IOBufTest.cpp index b11859ec..72a35dba 100644 --- a/folly/io/test/IOBufTest.cpp +++ b/folly/io/test/IOBufTest.cpp @@ -964,6 +964,19 @@ TEST(IOBuf, getIov) { buf->prev()->clear(); iov = buf->getIov(); EXPECT_EQ(count - 3, iov.size()); + + // test appending to an existing iovec array + iov.clear(); + const char localBuf[] = "hello"; + iov.push_back({(void*)localBuf, sizeof(localBuf)}); + iov.push_back({(void*)localBuf, sizeof(localBuf)}); + buf->appendToIov(&iov); + EXPECT_EQ(count - 1, iov.size()); + EXPECT_EQ(localBuf, iov[0].iov_base); + EXPECT_EQ(localBuf, iov[1].iov_base); + // The first two IOBufs were cleared, so the next iov entry + // should be the third IOBuf in the chain. + EXPECT_EQ(buf->next()->next()->data(), iov[2].iov_base); } TEST(IOBuf, move) { -- 2.34.1