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::fbvector<struct iovec> IOBuf::getIov() const {
folly::fbvector<struct iovec> iov;
iov.reserve(countChainElements());
+ appendToIov(&iov);
+ return iov;
+}
+
+void IOBuf::appendToIov(folly::fbvector<struct iovec>* 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<size_t>(p->length())});
+ iov->push_back({(void*)p->data(), folly::to<size_t>(p->length())});
}
p = p->next();
} while (p != this);
- return iov;
}
size_t IOBufHash::operator()(const IOBuf& buf) 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.
* These perform specialized memory management to help support
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) {