add IOBuf::appendToIov()
authorAdam Simpkins <simpkins@fb.com>
Thu, 15 Jan 2015 00:00:31 +0000 (16:00 -0800)
committerwoo <woo@fb.com>
Mon, 2 Feb 2015 21:12:19 +0000 (13:12 -0800)
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
folly/io/IOBuf.h
folly/io/test/IOBufTest.cpp

index 90517aea7d6c0445c7369a754d8cc66ffd6f0167..33e848ba071939b05c630c4c3c740b50695e74d7 100644 (file)
@@ -870,15 +870,19 @@ IOBuf::Iterator IOBuf::cend() const {
 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 {
index dccd57b0104b1bebefa80a8aca876388fc612b6d..3513798bd1a581f455de8c70eaba5816aeb2064a 100644 (file)
@@ -1041,6 +1041,17 @@ class IOBuf {
    */
   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
index b11859ecef6f7ae229b2dccc789f3d44df04e129..72a35dba33ec163186c2b7dc4b7effb0ade4034c 100644 (file)
@@ -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) {