mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-11-09 10:00:57 +03:00
Summary: **Context** The `BufAccessor` is used to access a contiguous section of memory. Right now, it works with a `Buf` under the hood. **Overall plan** The plan is to change the `BufAccessor` to use a `uint8_t*` instead. Since we're using section of contiguous memory, there's no need to use a chained buffer abstraction here. This'll move us closer to deprecating the usage `folly::IOBuf`. **What this diff is doing** Most use cases of the `BufAccessor` look like the following: ``` auto buf = bufAccessor.obtain(); // Do something with buf, like calling trimEnd bufAccessor.release(buf) ``` I'm adding APIs to the `BufAccessor` so that there's no need to `obtain()` and `release()` the `Buf`. We'd instead just call an API on the `BufAccessor`, which would call that same API on the underlying `folly::IOBuf`. Later on, we'll change the `BufAccessor` to use a `uint8_t*` under the hood. I'm currently leaving in the `obtain()`, `release()`, and `buf()` APIs because Fizz and the AsyncUDPSocket expect `folly::IOBuf` as inputs in many of their APIs. Once those callsites are migrated off `folly::IOBuf`, we can remove these APIs. Reviewed By: mjoras Differential Revision: D60973166 fbshipit-source-id: 52aa3541d0c4878c7ee8525d70ac280508b61e24
179 lines
4.3 KiB
C++
179 lines
4.3 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include <quic/api/QuicBatchWriter.h>
|
|
|
|
namespace quic {
|
|
// BatchWriter
|
|
bool BatchWriter::needsFlush(size_t /*unused*/) {
|
|
return false;
|
|
}
|
|
|
|
// SinglePacketBatchWriter
|
|
void SinglePacketBatchWriter::reset() {
|
|
buf_.reset();
|
|
}
|
|
|
|
bool SinglePacketBatchWriter::append(
|
|
std::unique_ptr<folly::IOBuf>&& buf,
|
|
size_t /*unused*/,
|
|
const folly::SocketAddress& /*unused*/,
|
|
QuicAsyncUDPSocket* /*unused*/) {
|
|
buf_ = std::move(buf);
|
|
|
|
// needs to be flushed
|
|
return true;
|
|
}
|
|
|
|
ssize_t SinglePacketBatchWriter::write(
|
|
QuicAsyncUDPSocket& sock,
|
|
const folly::SocketAddress& address) {
|
|
return sock.write(address, buf_);
|
|
}
|
|
|
|
// SinglePacketInplaceBatchWriter
|
|
void SinglePacketInplaceBatchWriter::reset() {
|
|
conn_.bufAccessor->clear();
|
|
}
|
|
|
|
bool SinglePacketInplaceBatchWriter::append(
|
|
std::unique_ptr<folly::IOBuf>&& /* buf */,
|
|
size_t /*unused*/,
|
|
const folly::SocketAddress& /*unused*/,
|
|
QuicAsyncUDPSocket* /*unused*/) {
|
|
// Always flush. This should trigger a write afterwards.
|
|
return true;
|
|
}
|
|
|
|
ssize_t SinglePacketInplaceBatchWriter::write(
|
|
QuicAsyncUDPSocket& sock,
|
|
const folly::SocketAddress& address) {
|
|
auto& buf = conn_.bufAccessor->buf();
|
|
CHECK(!conn_.bufAccessor->isChained());
|
|
auto ret = sock.write(address, buf);
|
|
conn_.bufAccessor->clear();
|
|
return ret;
|
|
}
|
|
|
|
bool SinglePacketInplaceBatchWriter::empty() const {
|
|
return conn_.bufAccessor->length() == 0;
|
|
}
|
|
|
|
// SinglePacketBackpressureBatchWriter
|
|
SinglePacketBackpressureBatchWriter::SinglePacketBackpressureBatchWriter(
|
|
QuicConnectionStateBase& conn)
|
|
: conn_(conn) {
|
|
// If we have a write to retry from a previous attempt, pick that up.
|
|
if (conn_.pendingWriteBatch_.buf) {
|
|
buf_.swap(conn_.pendingWriteBatch_.buf);
|
|
lastWriteSuccessful_ = false;
|
|
}
|
|
}
|
|
|
|
SinglePacketBackpressureBatchWriter::~SinglePacketBackpressureBatchWriter() {
|
|
if (buf_ && !buf_->empty()) {
|
|
conn_.pendingWriteBatch_.buf.swap(buf_);
|
|
}
|
|
}
|
|
|
|
void SinglePacketBackpressureBatchWriter::reset() {
|
|
// Only clear the buffer if it's been written successfully.
|
|
// Otherwise, retain it so it can be retried.
|
|
if (lastWriteSuccessful_) {
|
|
buf_.reset(nullptr);
|
|
}
|
|
}
|
|
|
|
bool SinglePacketBackpressureBatchWriter::append(
|
|
std::unique_ptr<folly::IOBuf>&& buf,
|
|
size_t /* unused */,
|
|
const folly::SocketAddress& /*unused*/,
|
|
QuicAsyncUDPSocket* /*unused*/) {
|
|
buf_ = std::move(buf);
|
|
|
|
// needs to be flushed
|
|
return true;
|
|
}
|
|
|
|
ssize_t SinglePacketBackpressureBatchWriter::write(
|
|
QuicAsyncUDPSocket& sock,
|
|
const folly::SocketAddress& address) {
|
|
auto written = sock.write(address, buf_);
|
|
lastWriteSuccessful_ = written > 0;
|
|
return written;
|
|
}
|
|
|
|
// SendmmsgPacketBatchWriter
|
|
SendmmsgPacketBatchWriter::SendmmsgPacketBatchWriter(size_t maxBufs)
|
|
: maxBufs_(maxBufs) {
|
|
bufs_.reserve(maxBufs);
|
|
}
|
|
|
|
bool SendmmsgPacketBatchWriter::empty() const {
|
|
return !currSize_;
|
|
}
|
|
|
|
size_t SendmmsgPacketBatchWriter::size() const {
|
|
return currSize_;
|
|
}
|
|
|
|
void SendmmsgPacketBatchWriter::reset() {
|
|
bufs_.clear();
|
|
currSize_ = 0;
|
|
}
|
|
|
|
bool SendmmsgPacketBatchWriter::append(
|
|
std::unique_ptr<folly::IOBuf>&& buf,
|
|
size_t size,
|
|
const folly::SocketAddress& /*unused*/,
|
|
QuicAsyncUDPSocket* /*unused*/) {
|
|
CHECK_LT(bufs_.size(), maxBufs_);
|
|
bufs_.emplace_back(std::move(buf));
|
|
currSize_ += size;
|
|
|
|
// reached max buffers
|
|
if (FOLLY_UNLIKELY(bufs_.size() == maxBufs_)) {
|
|
return true;
|
|
}
|
|
|
|
// does not need to be flushed yet
|
|
return false;
|
|
}
|
|
|
|
ssize_t SendmmsgPacketBatchWriter::write(
|
|
QuicAsyncUDPSocket& sock,
|
|
const folly::SocketAddress& address) {
|
|
CHECK_GT(bufs_.size(), 0);
|
|
if (bufs_.size() == 1) {
|
|
return sock.write(address, bufs_[0]);
|
|
}
|
|
|
|
int ret = sock.writem(
|
|
folly::range(&address, &address + 1), bufs_.data(), bufs_.size());
|
|
|
|
if (ret <= 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (static_cast<size_t>(ret) == bufs_.size()) {
|
|
return currSize_;
|
|
}
|
|
|
|
// this is a partial write - we just need to
|
|
// return a different number than currSize_
|
|
return 0;
|
|
}
|
|
|
|
bool useSinglePacketInplaceBatchWriter(
|
|
uint32_t maxBatchSize,
|
|
quic::DataPathType dataPathType) {
|
|
return maxBatchSize == 1 &&
|
|
dataPathType == quic::DataPathType::ContinuousMemory;
|
|
}
|
|
|
|
} // namespace quic
|