X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fio%2FIOBufQueue.cpp;h=6e4715d7d3af94c00135807488194de2e1136afb;hb=74261e41a1b94490607457e38b3b1c54cf6374a4;hp=c313725603b7549a7e5faa4a289773b58406248c;hpb=2ba26b052ea53cfa4126981de54677c2af623f66;p=folly.git diff --git a/folly/io/IOBufQueue.cpp b/folly/io/IOBufQueue.cpp index c3137256..6e4715d7 100644 --- a/folly/io/IOBufQueue.cpp +++ b/folly/io/IOBufQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "folly/io/IOBufQueue.h" +#include #include @@ -29,7 +29,7 @@ namespace { using folly::IOBuf; const size_t MIN_ALLOC_SIZE = 2000; -const size_t MAX_ALLOC_SIZE = 8000; // Must fit within a uint32_t +const size_t MAX_ALLOC_SIZE = 8000; const size_t MAX_PACK_COPY = 4096; /** @@ -46,7 +46,7 @@ appendToChain(unique_ptr& dst, unique_ptr&& src, bool pack) { // reduce wastage (the tail's tailroom and the head's headroom) when // joining two IOBufQueues together. size_t copyRemaining = MAX_PACK_COPY; - uint32_t n; + uint64_t n; while (src && (n = src->length()) < copyRemaining && n < tail->tailroom()) { @@ -71,7 +71,7 @@ IOBufQueue::IOBufQueue(const Options& options) chainLength_(0) { } -IOBufQueue::IOBufQueue(IOBufQueue&& other) +IOBufQueue::IOBufQueue(IOBufQueue&& other) noexcept : options_(other.options_), chainLength_(other.chainLength_), head_(std::move(other.head_)) { @@ -88,7 +88,7 @@ IOBufQueue& IOBufQueue::operator=(IOBufQueue&& other) { return *this; } -std::pair +std::pair IOBufQueue::headroom() { if (head_) { return std::make_pair(head_->writableBuffer(), head_->headroom()); @@ -98,19 +98,17 @@ IOBufQueue::headroom() { } void -IOBufQueue::markPrepended(uint32_t n) { +IOBufQueue::markPrepended(uint64_t n) { if (n == 0) { return; } assert(head_); head_->prepend(n); - if (options_.cacheChainLength) { - chainLength_ += n; - } + chainLength_ += n; } void -IOBufQueue::prepend(const void* buf, uint32_t n) { +IOBufQueue::prepend(const void* buf, uint64_t n) { auto p = headroom(); if (n > p.second) { throw std::overflow_error("Not enough room to prepend"); @@ -152,25 +150,23 @@ IOBufQueue::append(const void* buf, size_t len) { while (len != 0) { if ((head_ == nullptr) || head_->prev()->isSharedOne() || (head_->prev()->tailroom() == 0)) { - appendToChain(head_, std::move( + appendToChain(head_, IOBuf::create(std::max(MIN_ALLOC_SIZE, - std::min(len, MAX_ALLOC_SIZE)))), + std::min(len, MAX_ALLOC_SIZE))), false); } IOBuf* last = head_->prev(); - uint32_t copyLen = std::min(len, (size_t)last->tailroom()); + uint64_t copyLen = std::min(len, (size_t)last->tailroom()); memcpy(last->writableTail(), src, copyLen); src += copyLen; last->append(copyLen); - if (options_.cacheChainLength) { - chainLength_ += copyLen; - } + chainLength_ += copyLen; len -= copyLen; } } void -IOBufQueue::wrapBuffer(const void* buf, size_t len, uint32_t blockSize) { +IOBufQueue::wrapBuffer(const void* buf, size_t len, uint64_t blockSize) { auto src = static_cast(buf); while (len != 0) { size_t n = std::min(len, size_t(blockSize)); @@ -180,19 +176,9 @@ IOBufQueue::wrapBuffer(const void* buf, size_t len, uint32_t blockSize) { } } -pair -IOBufQueue::preallocate(uint32_t min, uint32_t newAllocationSize, - uint32_t max) { - if (head_ != nullptr) { - // If there's enough space left over at the end of the queue, use that. - IOBuf* last = head_->prev(); - if (!last->isSharedOne()) { - uint32_t avail = last->tailroom(); - if (avail >= min) { - return make_pair(last->writableTail(), std::min(max, avail)); - } - } - } +pair +IOBufQueue::preallocateSlow(uint64_t min, uint64_t newAllocationSize, + uint64_t max) { // Allocate a new buffer of the requested max size. unique_ptr newBuf(IOBuf::create(std::max(min, newAllocationSize))); appendToChain(head_, std::move(newBuf), false); @@ -201,26 +187,19 @@ IOBufQueue::preallocate(uint32_t min, uint32_t newAllocationSize, std::min(max, last->tailroom())); } -void -IOBufQueue::postallocate(uint32_t n) { - head_->prev()->append(n); - if (options_.cacheChainLength) { - chainLength_ += n; - } -} - -unique_ptr -IOBufQueue::split(size_t n) { +unique_ptr IOBufQueue::split(size_t n, bool throwOnUnderflow) { unique_ptr result; while (n != 0) { if (head_ == nullptr) { - throw std::underflow_error( - "Attempt to remove more bytes than are present in IOBufQueue"); + if (throwOnUnderflow) { + throw std::underflow_error( + "Attempt to remove more bytes than are present in IOBufQueue"); + } else { + break; + } } else if (head_->length() <= n) { n -= head_->length(); - if (options_.cacheChainLength) { - chainLength_ -= head_->length(); - } + chainLength_ -= head_->length(); unique_ptr remainder = head_->pop(); appendToChain(result, std::move(head_), false); head_ = std::move(remainder); @@ -229,13 +208,11 @@ IOBufQueue::split(size_t n) { clone->trimEnd(clone->length() - n); appendToChain(result, std::move(clone), false); head_->trimStart(n); - if (options_.cacheChainLength) { - chainLength_ -= n; - } + chainLength_ -= n; break; } } - return std::move(result); + return result; } void IOBufQueue::trimStart(size_t amount) { @@ -246,15 +223,11 @@ void IOBufQueue::trimStart(size_t amount) { } if (head_->length() > amount) { head_->trimStart(amount); - if (options_.cacheChainLength) { - chainLength_ -= amount; - } + chainLength_ -= amount; break; } amount -= head_->length(); - if (options_.cacheChainLength) { - chainLength_ -= head_->length(); - } + chainLength_ -= head_->length(); head_ = head_->pop(); } } @@ -267,15 +240,11 @@ void IOBufQueue::trimEnd(size_t amount) { } if (head_->prev()->length() > amount) { head_->prev()->trimEnd(amount); - if (options_.cacheChainLength) { - chainLength_ -= amount; - } + chainLength_ -= amount; break; } amount -= head_->prev()->length(); - if (options_.cacheChainLength) { - chainLength_ -= head_->prev()->length(); - } + chainLength_ -= head_->prev()->length(); if (head_->isChained()) { head_->prev()->unlink(); @@ -289,9 +258,7 @@ std::unique_ptr IOBufQueue::pop_front() { if (!head_) { return nullptr; } - if (options_.cacheChainLength) { - chainLength_ -= head_->length(); - } + chainLength_ -= head_->length(); std::unique_ptr retBuf = std::move(head_); head_ = retBuf->pop(); return retBuf; @@ -306,8 +273,25 @@ void IOBufQueue::clear() { buf->clear(); buf = buf->next(); } while (buf != head_.get()); - if (options_.cacheChainLength) { - chainLength_ = 0; + chainLength_ = 0; +} + +void IOBufQueue::appendToString(std::string& out) const { + if (!head_) { + return; + } + auto len = + options_.cacheChainLength ? chainLength_ : head_->computeChainDataLength(); + out.reserve(out.size() + len); + + for (auto range : *head_) { + out.append(reinterpret_cast(range.data()), range.size()); + } +} + +void IOBufQueue::gather(uint64_t maxLength) { + if (head_ != nullptr) { + head_->gather(maxLength); } }