Commit b5888d39 authored by Renjie's avatar Renjie Committed by Commit Bot

Deprecate WritevData by converting iovs into MemSliceSpan and then calling

WriteMemSlices.

Flag protected by quic_reloadable_flag_quic_call_write_mem_slices.

Merge internal change: 220883112

Change-Id: I55210e7812ca6e51b860b5df3aa303e49a369df6
Reviewed-on: https://chromium-review.googlesource.com/c/1332773
Commit-Queue: Renjie Tang <renjietang@chromium.org>
Reviewed-by: default avatarRyan Hamilton <rch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607775}
parent b757a245
...@@ -1536,6 +1536,7 @@ component("net") { ...@@ -1536,6 +1536,7 @@ component("net") {
"third_party/quic/platform/api/quic_map_util.h", "third_party/quic/platform/api/quic_map_util.h",
"third_party/quic/platform/api/quic_mem_slice.h", "third_party/quic/platform/api/quic_mem_slice.h",
"third_party/quic/platform/api/quic_mem_slice_span.h", "third_party/quic/platform/api/quic_mem_slice_span.h",
"third_party/quic/platform/api/quic_mem_slice_storage.h",
"third_party/quic/platform/api/quic_mutex.cc", "third_party/quic/platform/api/quic_mutex.cc",
"third_party/quic/platform/api/quic_mutex.h", "third_party/quic/platform/api/quic_mutex.h",
"third_party/quic/platform/api/quic_pcc_sender.h", "third_party/quic/platform/api/quic_pcc_sender.h",
...@@ -1580,6 +1581,8 @@ component("net") { ...@@ -1580,6 +1581,8 @@ component("net") {
"third_party/quic/platform/impl/quic_mem_slice_impl.h", "third_party/quic/platform/impl/quic_mem_slice_impl.h",
"third_party/quic/platform/impl/quic_mem_slice_span_impl.cc", "third_party/quic/platform/impl/quic_mem_slice_span_impl.cc",
"third_party/quic/platform/impl/quic_mem_slice_span_impl.h", "third_party/quic/platform/impl/quic_mem_slice_span_impl.h",
"third_party/quic/platform/impl/quic_mem_slice_storage_impl.cc",
"third_party/quic/platform/impl/quic_mem_slice_storage_impl.h",
"third_party/quic/platform/impl/quic_mutex_impl.cc", "third_party/quic/platform/impl/quic_mutex_impl.cc",
"third_party/quic/platform/impl/quic_mutex_impl.h", "third_party/quic/platform/impl/quic_mutex_impl.h",
"third_party/quic/platform/impl/quic_pcc_sender_impl.h", "third_party/quic/platform/impl/quic_pcc_sender_impl.h",
...@@ -5189,6 +5192,7 @@ test("net_unittests") { ...@@ -5189,6 +5192,7 @@ test("net_unittests") {
"third_party/quic/platform/api/quic_endian_test.cc", "third_party/quic/platform/api/quic_endian_test.cc",
"third_party/quic/platform/api/quic_hostname_utils_test.cc", "third_party/quic/platform/api/quic_hostname_utils_test.cc",
"third_party/quic/platform/api/quic_mem_slice_span_test.cc", "third_party/quic/platform/api/quic_mem_slice_span_test.cc",
"third_party/quic/platform/api/quic_mem_slice_storage_test.cc",
"third_party/quic/platform/api/quic_mem_slice_test.cc", "third_party/quic/platform/api/quic_mem_slice_test.cc",
"third_party/quic/platform/api/quic_reference_counted_test.cc", "third_party/quic/platform/api/quic_reference_counted_test.cc",
"third_party/quic/platform/api/quic_singleton_test.cc", "third_party/quic/platform/api/quic_singleton_test.cc",
......
...@@ -308,3 +308,7 @@ QUIC_FLAG(bool, ...@@ -308,3 +308,7 @@ QUIC_FLAG(bool,
// If true, public reset packets sent from GFE will include a kEPID tag. // If true, public reset packets sent from GFE will include a kEPID tag.
QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_spurious_ack_alarm, false) QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_spurious_ack_alarm, false)
// If true, QuicSpdyStream::WritevBody() will convert iovs into QuicMemSliceSpan
// and call WriteMemSlices instead.
QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_call_write_mem_slices, false)
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "net/third_party/quic/core/quic_utils.h" #include "net/third_party/quic/core/quic_utils.h"
#include "net/third_party/quic/core/quic_write_blocked_list.h" #include "net/third_party/quic/core/quic_write_blocked_list.h"
#include "net/third_party/quic/platform/api/quic_bug_tracker.h" #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quic/platform/api/quic_flags.h"
#include "net/third_party/quic/platform/api/quic_logging.h" #include "net/third_party/quic/platform/api/quic_logging.h"
#include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string.h"
#include "net/third_party/quic/platform/api/quic_string_piece.h" #include "net/third_party/quic/platform/api/quic_string_piece.h"
...@@ -103,7 +105,15 @@ size_t QuicSpdyStream::WriteTrailers( ...@@ -103,7 +105,15 @@ size_t QuicSpdyStream::WriteTrailers(
QuicConsumedData QuicSpdyStream::WritevBody(const struct iovec* iov, QuicConsumedData QuicSpdyStream::WritevBody(const struct iovec* iov,
int count, int count,
bool fin) { bool fin) {
return WritevData(iov, count, fin); if (!GetQuicReloadableFlag(quic_call_write_mem_slices)) {
return WritevData(iov, count, fin);
}
QUIC_FLAG_COUNT(quic_reloadable_flag_quic_call_write_mem_slices);
QuicMemSliceStorage storage(
iov, count,
session()->connection()->helper()->GetStreamSendBufferAllocator(),
GetQuicFlag(FLAGS_quic_send_buffer_max_data_slice_size));
return WriteMemSlices(storage.ToSpan(), fin);
} }
QuicConsumedData QuicSpdyStream::WriteBodySlices(QuicMemSliceSpan slices, QuicConsumedData QuicSpdyStream::WriteBodySlices(QuicMemSliceSpan slices,
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "net/third_party/quic/core/quic_stream_sequencer.h" #include "net/third_party/quic/core/quic_stream_sequencer.h"
#include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/platform/api/quic_export.h"
#include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_flags.h"
#include "net/third_party/quic/platform/api/quic_mem_slice_storage.h"
#include "net/third_party/quic/platform/api/quic_socket_address.h" #include "net/third_party/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string.h"
#include "net/third_party/spdy/core/spdy_framer.h" #include "net/third_party/spdy/core/spdy_framer.h"
......
...@@ -1714,7 +1714,10 @@ TEST_P(QuicSessionTestServer, WritevDataOnReadUnidirectionalStream) { ...@@ -1714,7 +1714,10 @@ TEST_P(QuicSessionTestServer, WritevDataOnReadUnidirectionalStream) {
.Times(1); .Times(1);
QuicString body(100, '.'); QuicString body(100, '.');
struct iovec iov = {const_cast<char*>(body.data()), body.length()}; struct iovec iov = {const_cast<char*>(body.data()), body.length()};
stream4->WritevData(&iov, 1, false); QuicMemSliceStorage storage(
&iov, 1, session_.connection()->helper()->GetStreamSendBufferAllocator(),
1024);
stream4->WriteMemSlices(storage.ToSpan(), false);
} }
TEST_P(QuicSessionTestServer, WriteMemSlicesOnReadUnidirectionalStream) { TEST_P(QuicSessionTestServer, WriteMemSlicesOnReadUnidirectionalStream) {
......
...@@ -881,7 +881,10 @@ TEST_F(QuicStreamTest, WriteBufferedData) { ...@@ -881,7 +881,10 @@ TEST_F(QuicStreamTest, WriteBufferedData) {
EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Return(QuicConsumedData(0, false))); .WillOnce(Return(QuicConsumedData(0, false)));
struct iovec iov = {const_cast<char*>(data.data()), data.length()}; struct iovec iov = {const_cast<char*>(data.data()), data.length()};
QuicConsumedData consumed = stream_->WritevData(&iov, 1, false); QuicMemSliceStorage storage(
&iov, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(),
1024);
QuicConsumedData consumed = stream_->WriteMemSlices(storage.ToSpan(), false);
// There is no buffered data before, all data should be consumed without // There is no buffered data before, all data should be consumed without
// respecting buffered data upper limit. // respecting buffered data upper limit.
EXPECT_EQ(data.length(), consumed.bytes_consumed); EXPECT_EQ(data.length(), consumed.bytes_consumed);
...@@ -890,7 +893,10 @@ TEST_F(QuicStreamTest, WriteBufferedData) { ...@@ -890,7 +893,10 @@ TEST_F(QuicStreamTest, WriteBufferedData) {
EXPECT_FALSE(stream_->CanWriteNewData()); EXPECT_FALSE(stream_->CanWriteNewData());
EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0); EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0);
consumed = stream_->WritevData(&iov, 1, false); QuicMemSliceStorage storage2(
&iov, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(),
1024);
consumed = stream_->WriteMemSlices(storage2.ToSpan(), false);
// No Data can be consumed as buffered data is beyond upper limit. // No Data can be consumed as buffered data is beyond upper limit.
EXPECT_EQ(0u, consumed.bytes_consumed); EXPECT_EQ(0u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(consumed.fin_consumed);
...@@ -912,7 +918,10 @@ TEST_F(QuicStreamTest, WriteBufferedData) { ...@@ -912,7 +918,10 @@ TEST_F(QuicStreamTest, WriteBufferedData) {
EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0); EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0);
// All data can be consumed as buffered data is below upper limit. // All data can be consumed as buffered data is below upper limit.
consumed = stream_->WritevData(&iov, 1, false); QuicMemSliceStorage storage3(
&iov, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(),
1024);
consumed = stream_->WriteMemSlices(storage3.ToSpan(), false);
EXPECT_EQ(data.length(), consumed.bytes_consumed); EXPECT_EQ(data.length(), consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(consumed.fin_consumed);
EXPECT_EQ(data.length() + GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1, EXPECT_EQ(data.length() + GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1,
...@@ -928,11 +937,17 @@ TEST_F(QuicStreamTest, WritevDataReachStreamLimit) { ...@@ -928,11 +937,17 @@ TEST_F(QuicStreamTest, WritevDataReachStreamLimit) {
EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Invoke(&(MockQuicSession::ConsumeData))); .WillOnce(Invoke(&(MockQuicSession::ConsumeData)));
struct iovec iov = {const_cast<char*>(data.data()), 5u}; struct iovec iov = {const_cast<char*>(data.data()), 5u};
QuicConsumedData consumed = stream_->WritevData(&iov, 1u, false); QuicMemSliceStorage storage(
&iov, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(),
1024);
QuicConsumedData consumed = stream_->WriteMemSlices(storage.ToSpan(), false);
EXPECT_EQ(data.length(), consumed.bytes_consumed); EXPECT_EQ(data.length(), consumed.bytes_consumed);
struct iovec iov2 = {const_cast<char*>(data.data()), 1u}; struct iovec iov2 = {const_cast<char*>(data.data()), 1u};
QuicMemSliceStorage storage2(
&iov2, 1,
session_->connection()->helper()->GetStreamSendBufferAllocator(), 1024);
EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _)); EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _));
EXPECT_QUIC_BUG(stream_->WritevData(&iov2, 1u, false), EXPECT_QUIC_BUG(stream_->WriteMemSlices(storage2.ToSpan(), false),
"Write too many data via stream"); "Write too many data via stream");
} }
......
...@@ -35,6 +35,9 @@ class QUIC_EXPORT_PRIVATE QuicMemSliceSpan { ...@@ -35,6 +35,9 @@ class QUIC_EXPORT_PRIVATE QuicMemSliceSpan {
return impl_.SaveMemSlicesInSendBuffer(send_buffer); return impl_.SaveMemSlicesInSendBuffer(send_buffer);
} }
// Return data of the span at |index| by the form of a QuicStringPiece.
QuicStringPiece GetData(int index) { return impl_.GetData(index); }
bool empty() const { return impl_.empty(); } bool empty() const { return impl_.empty(); }
private: private:
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_MEM_SLICE_STORAGE_H_
#define NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_MEM_SLICE_STORAGE_H_
#include "net/third_party/quic/platform/api/quic_export.h"
#include "net/third_party/quic/platform/impl/quic_mem_slice_storage_impl.h"
namespace quic {
// QuicMemSliceStorage is a container class that store QuicMemSlices for further
// use cases such as turning into QuicMemSliceSpan.
class QUIC_EXPORT_PRIVATE QuicMemSliceStorage {
public:
QuicMemSliceStorage(const struct iovec* iov,
int iov_count,
QuicBufferAllocator* allocator,
const QuicByteCount max_slice_len)
: impl_(iov, iov_count, allocator, max_slice_len) {}
QuicMemSliceStorage(const QuicMemSliceStorage& other) = default;
QuicMemSliceStorage& operator=(const QuicMemSliceStorage& other) = default;
QuicMemSliceStorage(QuicMemSliceStorage&& other) = default;
QuicMemSliceStorage& operator=(QuicMemSliceStorage&& other) = default;
~QuicMemSliceStorage() = default;
// Return a QuicMemSliceSpan form of the storage.
QuicMemSliceSpan ToSpan() { return impl_.ToSpan(); }
private:
QuicMemSliceStorageImpl impl_;
};
} // namespace quic
#endif // NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_MEM_SLICE_STORAGE_H_
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/third_party/quic/platform/api/quic_mem_slice_storage.h"
#include "net/third_party/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quic/platform/api/quic_test.h"
namespace quic {
namespace test {
namespace {
class QuicMemSliceStorageImplTest : public QuicTest {
public:
QuicMemSliceStorageImplTest() = default;
};
TEST_F(QuicMemSliceStorageImplTest, EmptyIov) {
QuicMemSliceStorage storage(nullptr, 0, nullptr, 1024);
EXPECT_TRUE(storage.ToSpan().empty());
}
TEST_F(QuicMemSliceStorageImplTest, SingleIov) {
SimpleBufferAllocator allocator;
QuicString body(3, 'c');
struct iovec iov = {const_cast<char*>(body.data()), body.length()};
QuicMemSliceStorage storage(&iov, 1, &allocator, 1024);
auto span = storage.ToSpan();
EXPECT_EQ("ccc", span.GetData(0));
EXPECT_NE(static_cast<const void*>(span.GetData(0).data()), body.data());
}
TEST_F(QuicMemSliceStorageImplTest, MultipleIovInSingleSlice) {
SimpleBufferAllocator allocator;
QuicString body1(3, 'a');
QuicString body2(4, 'b');
struct iovec iov[] = {{const_cast<char*>(body1.data()), body1.length()},
{const_cast<char*>(body2.data()), body2.length()}};
QuicMemSliceStorage storage(iov, 2, &allocator, 1024);
auto span = storage.ToSpan();
EXPECT_EQ("aaabbbb", span.GetData(0));
}
TEST_F(QuicMemSliceStorageImplTest, MultipleIovInMultipleSlice) {
SimpleBufferAllocator allocator;
QuicString body1(4, 'a');
QuicString body2(4, 'b');
struct iovec iov[] = {{const_cast<char*>(body1.data()), body1.length()},
{const_cast<char*>(body2.data()), body2.length()}};
QuicMemSliceStorage storage(iov, 2, &allocator, 4);
auto span = storage.ToSpan();
EXPECT_EQ("aaaa", span.GetData(0));
EXPECT_EQ("bbbb", span.GetData(1));
}
} // namespace
} // namespace test
} // namespace quic
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "net/base/io_buffer.h" #include "net/base/io_buffer.h"
#include "net/third_party/quic/core/quic_types.h" #include "net/third_party/quic/core/quic_types.h"
#include "net/third_party/quic/platform/api/quic_string_piece.h"
namespace quic { namespace quic {
...@@ -31,6 +32,10 @@ class QUIC_EXPORT_PRIVATE QuicMemSliceSpanImpl { ...@@ -31,6 +32,10 @@ class QUIC_EXPORT_PRIVATE QuicMemSliceSpanImpl {
// saved mem slices. // saved mem slices.
QuicByteCount SaveMemSlicesInSendBuffer(QuicStreamSendBuffer* send_buffer); QuicByteCount SaveMemSlicesInSendBuffer(QuicStreamSendBuffer* send_buffer);
QuicStringPiece GetData(size_t index) {
return QuicStringPiece(buffers_[index]->data(), lengths_[index]);
}
bool empty() const { return num_buffers_ == 0; } bool empty() const { return num_buffers_ == 0; }
private: private:
......
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/third_party/quic/platform/impl/quic_mem_slice_storage_impl.h"
#include "net/third_party/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quic/core/quic_utils.h"
namespace quic {
QuicMemSliceStorageImpl::QuicMemSliceStorageImpl(
const struct iovec* iov,
int iov_count,
QuicBufferAllocator* allocator,
const QuicByteCount max_slice_len) {
if (iov == nullptr) {
return;
}
QuicByteCount write_len = 0;
for (int i = 0; i < iov_count; ++i) {
write_len += iov[i].iov_len;
}
DCHECK_LT(0u, write_len);
size_t iov_offset = 0;
while (write_len > 0) {
size_t slice_len = std::min(write_len, max_slice_len);
auto io_buffer = base::MakeRefCounted<net::IOBuffer>(slice_len);
QuicUtils::CopyToBuffer(iov, iov_count, iov_offset, slice_len,
const_cast<char*>(io_buffer->data()));
buffers_.push_back(std::move(io_buffer));
lengths_.push_back(slice_len);
write_len -= slice_len;
iov_offset += slice_len;
}
}
} // namespace quic
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_MEM_SLICE_STORAGE_IMPL_H_
#define NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_MEM_SLICE_STORAGE_IMPL_H_
#include "base/memory/ref_counted.h"
#include "net/base/io_buffer.h"
#include "net/third_party/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quic/core/quic_types.h"
#include "net/third_party/quic/platform/api/quic_mem_slice_span.h"
#include "net/third_party/quic/platform/impl/quic_iovec_impl.h"
namespace quic {
class QUIC_EXPORT_PRIVATE QuicMemSliceStorageImpl {
public:
QuicMemSliceStorageImpl(const struct iovec* iov,
int iov_count,
QuicBufferAllocator* allocator,
const QuicByteCount max_slice_len);
QuicMemSliceStorageImpl(const QuicMemSliceStorageImpl& other) = default;
QuicMemSliceStorageImpl& operator=(const QuicMemSliceStorageImpl& other) =
default;
QuicMemSliceStorageImpl(QuicMemSliceStorageImpl&& other) = default;
QuicMemSliceStorageImpl& operator=(QuicMemSliceStorageImpl&& other) = default;
~QuicMemSliceStorageImpl() = default;
QuicMemSliceSpan ToSpan() {
return QuicMemSliceSpan(QuicMemSliceSpanImpl(
buffers_.data(), lengths_.data(), buffers_.size()));
}
private:
std::vector<scoped_refptr<net::IOBuffer>> buffers_;
std::vector<int> lengths_;
};
} // namespace quic
#endif // NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_MEM_SLICE_STORAGE_IMPL_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment