Commit 5667f45e authored by Adam Simpkins's avatar Adam Simpkins Committed by woo

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:
parent 9f916e14
...@@ -870,15 +870,19 @@ IOBuf::Iterator IOBuf::cend() const { ...@@ -870,15 +870,19 @@ IOBuf::Iterator IOBuf::cend() const {
folly::fbvector<struct iovec> IOBuf::getIov() const { folly::fbvector<struct iovec> IOBuf::getIov() const {
folly::fbvector<struct iovec> iov; folly::fbvector<struct iovec> iov;
iov.reserve(countChainElements()); iov.reserve(countChainElements());
appendToIov(&iov);
return iov;
}
void IOBuf::appendToIov(folly::fbvector<struct iovec>* iov) const {
IOBuf const* p = this; IOBuf const* p = this;
do { do {
// some code can get confused by empty iovs, so skip them // some code can get confused by empty iovs, so skip them
if (p->length() > 0) { if (p->length() > 0) {
iov.push_back({(void*)p->data(), folly::to<size_t>(p->length())}); iov->push_back({(void*)p->data(), folly::to<size_t>(p->length())});
} }
p = p->next(); p = p->next();
} while (p != this); } while (p != this);
return iov;
} }
size_t IOBufHash::operator()(const IOBuf& buf) const { size_t IOBufHash::operator()(const IOBuf& buf) const {
......
...@@ -1041,6 +1041,17 @@ class IOBuf { ...@@ -1041,6 +1041,17 @@ class IOBuf {
*/ */
folly::fbvector<struct iovec> getIov() const; folly::fbvector<struct iovec> 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<struct iovec>* iov) const;
/* /*
* Overridden operator new and delete. * Overridden operator new and delete.
* These perform specialized memory management to help support * These perform specialized memory management to help support
......
...@@ -964,6 +964,19 @@ TEST(IOBuf, getIov) { ...@@ -964,6 +964,19 @@ TEST(IOBuf, getIov) {
buf->prev()->clear(); buf->prev()->clear();
iov = buf->getIov(); iov = buf->getIov();
EXPECT_EQ(count - 3, iov.size()); 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) { TEST(IOBuf, move) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment