1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-08-09 20:42:44 +03:00
Files
mvfst/quic/api/QuicBatchWriter.cpp
Konstantin Tsoy 15a619fccf Add SinglePacketInplaceBatchWriter
Summary:
The new writer will use a single IOBuf for in-place writes via a
accessor.

Reviewed By: jbeshay, mjoras

Differential Revision: D47648606

fbshipit-source-id: c6094eb3445587337f8a03e203aeadb2954f76b1
2023-07-27 17:00:41 -07:00

151 lines
3.4 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;
}
void BatchWriter::setSock(QuicAsyncUDPSocketType* sock) {
if (sock && !evb_.getBackingEventBase()) {
fd_ = ::dup(getSocketFd(*sock));
evb_.setBackingEventBase(sock->getEventBase());
}
}
QuicEventBase* BatchWriter::evb() {
return &evb_;
}
int BatchWriter::getAndResetFd() {
auto ret = fd_;
fd_ = -1;
return ret;
}
// SinglePacketBatchWriter
void SinglePacketBatchWriter::reset() {
buf_.reset();
}
bool SinglePacketBatchWriter::append(
std::unique_ptr<folly::IOBuf>&& buf,
size_t /*unused*/,
const folly::SocketAddress& /*unused*/,
QuicAsyncUDPSocketType* /*unused*/) {
buf_ = std::move(buf);
// needs to be flushed
return true;
}
ssize_t SinglePacketBatchWriter::write(
QuicAsyncUDPSocketType& sock,
const folly::SocketAddress& address) {
return sock.write(address, buf_);
}
// SinglePacketInplaceBatchWriter
void SinglePacketInplaceBatchWriter::reset() {
ScopedBufAccessor scopedBufAccessor(conn_.bufAccessor);
auto& buf = scopedBufAccessor.buf();
buf->clear();
}
bool SinglePacketInplaceBatchWriter::append(
std::unique_ptr<folly::IOBuf>&& /* buf */,
size_t /*unused*/,
const folly::SocketAddress& /*unused*/,
QuicAsyncUDPSocketType* /*unused*/) {
// Always flush. This should trigger a write afterwards.
return true;
}
ssize_t SinglePacketInplaceBatchWriter::write(
QuicAsyncUDPSocketType& sock,
const folly::SocketAddress& address) {
ScopedBufAccessor scopedBufAccessor(conn_.bufAccessor);
auto& buf = scopedBufAccessor.buf();
CHECK(!buf->isChained());
auto ret = sock.write(address, buf);
buf->clear();
return ret;
}
bool SinglePacketInplaceBatchWriter::empty() const {
ScopedBufAccessor scopedBufAccessor(conn_.bufAccessor);
auto& buf = scopedBufAccessor.buf();
return buf->length() == 0;
}
// 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*/,
QuicAsyncUDPSocketType* /*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(
QuicAsyncUDPSocketType& 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;
}
} // namespace quic