void IOBuf::markExternallyShared() { IOBuf* current = this; do { current->markExternallySharedOne(); current = current->next_; } while (current != this); }
void checkChain(IOBuf* buf, boost::mt19937& gen) { IOBuf *current = buf; do { checkBuf(current->data(), current->length(), gen); current = current->next(); } while (current != buf); }
BENCHMARK(cloneIntoBenchmark, iters) { IOBuf buf(IOBuf::CREATE, 10); IOBuf copy; while (iters--) { buf.cloneInto(copy); folly::doNotOptimizeAway(copy.capacity()); } }
IOBuf IOBuf::cloneAsValue() const { auto tmp = cloneOneAsValue(); for (IOBuf* current = next_; current != this; current = current->next_) { tmp.prependChain(current->cloneOne()); } return tmp; }
unique_ptr<IOBuf> IOBuf::clone() const { unique_ptr<IOBuf> newHead(cloneOne()); for (IOBuf* current = next_; current != this; current = current->next_) { newHead->prependChain(current->cloneOne()); } return newHead; }
pair<void*,uint64_t> IOBufQueue::preallocateSlow(uint64_t min, uint64_t newAllocationSize, uint64_t max) { // Allocate a new buffer of the requested max size. unique_ptr<IOBuf> newBuf(IOBuf::create(std::max(min, newAllocationSize))); appendToChain(head_, std::move(newBuf), false); IOBuf* last = head_->prev(); return make_pair(last->writableTail(), std::min(max, last->tailroom())); }
void IOBuf::cloneInto(IOBuf& other) const { IOBuf tmp; cloneOneInto(tmp); for (IOBuf* current = next_; current != this; current = current->next_) { tmp.prependChain(current->cloneOne()); } other = std::move(tmp); }
void IOBufQueue::clear() { if (!head_) { return; } IOBuf* buf = head_.get(); do { buf->clear(); buf = buf->next(); } while (buf != head_.get()); chainLength_ = 0; }
void IOBuf::makeManagedChained() { assert(isChained()); IOBuf* current = this; while (true) { current->makeManagedOne(); current = current->next_; if (current == this) { break; } } }
void IOBufQueue::append(const void* buf, size_t len) { auto src = static_cast<const uint8_t*>(buf); while (len != 0) { if ((head_ == nullptr) || head_->prev()->isSharedOne() || (head_->prev()->tailroom() == 0)) { appendToChain(head_, IOBuf::create(std::max(MIN_ALLOC_SIZE, std::min(len, MAX_ALLOC_SIZE))), false); } IOBuf* last = head_->prev(); uint64_t copyLen = std::min(len, (size_t)last->tailroom()); memcpy(last->writableTail(), src, copyLen); src += copyLen; last->append(copyLen); chainLength_ += copyLen; len -= copyLen; } }
TEST(IOBuf, move) { // Default allocate an IOBuf on the stack IOBuf outerBuf; char data[] = "foobar"; uint32_t length = sizeof(data); uint32_t actualCapacity{0}; const void* ptr{nullptr}; { // Create a small IOBuf on the stack. // Note that IOBufs created on the stack always use an external buffer. IOBuf b1(IOBuf::CREATE, 10); actualCapacity = b1.capacity(); EXPECT_GE(actualCapacity, 10); EXPECT_EQ(0, b1.length()); EXPECT_FALSE(b1.isShared()); ptr = b1.data(); ASSERT_TRUE(ptr != nullptr); memcpy(b1.writableTail(), data, length); b1.append(length); EXPECT_EQ(length, b1.length()); // Use the move constructor IOBuf b2(std::move(b1)); EXPECT_EQ(ptr, b2.data()); EXPECT_EQ(length, b2.length()); EXPECT_EQ(actualCapacity, b2.capacity()); EXPECT_FALSE(b2.isShared()); // Use the move assignment operator outerBuf = std::move(b2); // Close scope, destroying b1 and b2 // (which are both be invalid now anyway after moving out of them) } EXPECT_EQ(ptr, outerBuf.data()); EXPECT_EQ(length, outerBuf.length()); EXPECT_EQ(actualCapacity, outerBuf.capacity()); EXPECT_FALSE(outerBuf.isShared()); }
void IOBuf::unshareChained() { // unshareChained() should only be called if we are part of a chain of // multiple IOBufs. The caller should have already verified this. assert(isChained()); IOBuf* current = this; while (true) { if (current->isSharedOne()) { // we have to unshare break; } current = current->next_; if (current == this) { // None of the IOBufs in the chain are shared, // so return without doing anything return; } } // We have to unshare. Let coalesceSlow() do the work. coalesceSlow(); }
IOBuf::IOBuf(const IOBuf& other) { *this = other.cloneAsValue(); }
/** * Some utility functions. */ unique_ptr<folly::IOBuf> KerberosSASLHandshakeUtils::wrapMessage( gss_ctx_id_t context, unique_ptr<folly::IOBuf>&& buf) { #ifdef GSSAPI_EXT_H_ uint64_t numElements = buf->countChainElements(); // Allocate iov vector with header | data blocks ... | padding | trailer std::vector<gss_iov_buffer_desc> iov(numElements + 3); uint64_t headerIdx = 0; uint64_t paddingIdx = numElements + 1; uint64_t trailerIdx = numElements + 2; iov[headerIdx].type = GSS_IOV_BUFFER_TYPE_HEADER; uint64_t count = 1; IOBuf *current = buf.get(); do { iov[count].type = GSS_IOV_BUFFER_TYPE_DATA; iov[count].buffer.value = (void *)current->writableData(); iov[count].buffer.length = current->length(); count++; current = current->next(); } while (current != buf.get()); iov[paddingIdx].type = GSS_IOV_BUFFER_TYPE_PADDING; iov[trailerIdx].type = GSS_IOV_BUFFER_TYPE_TRAILER; // Compute required header / padding / trailer lengths OM_uint32 maj_stat, min_stat; maj_stat = gss_wrap_iov_length( &min_stat, context, 1, GSS_C_QOP_DEFAULT, nullptr, &iov[0], iov.size()); if (maj_stat != GSS_S_COMPLETE) { KerberosSASLHandshakeUtils::throwGSSException( "Error constructing iov chain", maj_stat, min_stat); } // Allocate the additional buffers std::unique_ptr<IOBuf> header = IOBuf::create( iov[headerIdx].buffer.length); header->append(iov[headerIdx].buffer.length); std::unique_ptr<IOBuf> padding = IOBuf::create( iov[paddingIdx].buffer.length); padding->append(iov[paddingIdx].buffer.length); std::unique_ptr<IOBuf> trailer = IOBuf::create( iov[trailerIdx].buffer.length); trailer->append(iov[trailerIdx].buffer.length); iov[headerIdx].buffer.value = (void *)header->writableData(); iov[paddingIdx].buffer.value = (void *)padding->writableData(); iov[trailerIdx].buffer.value = (void *)trailer->writableData(); // Link all the buffers in a chain header->prependChain(std::move(buf)); header->prependChain(std::move(padding)); header->prependChain(std::move(trailer)); // Encrypt in place maj_stat = gss_wrap_iov( &min_stat, context, 1, // conf and integrity requested GSS_C_QOP_DEFAULT, nullptr, &iov[0], iov.size() ); if (maj_stat != GSS_S_COMPLETE) { KerberosSASLHandshakeUtils::throwGSSException( "Error wrapping message", maj_stat, min_stat); } return header; #else // Don't bother with getting things working on an older platform. // Things should never reach this point anyway, because security will // be disabled at a higher level. throw TKerberosException( "Linking against older version of krb5 without support for security."); return std::move(buf); #endif }
IOBuf::IOBuf(const IOBuf& other) { other.cloneInto(*this); }