mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-07-30 14:43:05 +03:00
paused priority support
Reviewed By: afrind Differential Revision: D67988645 fbshipit-source-id: 465f8c56177e5b703dbc1511b73521e6c26c1f3e
This commit is contained in:
committed by
Facebook GitHub Bot
parent
d438b82cf2
commit
38d77ba81f
@ -2818,4 +2818,58 @@ TEST_F(QuicPacketSchedulerTest, RstStreamSchedulerReliableReset) {
|
|||||||
EXPECT_FALSE(conn.pendingEvents.resets.contains(stream->id));
|
EXPECT_FALSE(conn.pendingEvents.resets.contains(stream->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(QuicPacketSchedulerTest, PausedPriorityInitial) {
|
||||||
|
static const auto kSequentialPriority = Priority(3, false);
|
||||||
|
static const auto kPausedPriority = Priority(0, false, 0, true /* paused */);
|
||||||
|
QuicServerConnectionState conn(
|
||||||
|
FizzServerQuicHandshakeContext::Builder().build());
|
||||||
|
conn.streamManager->setMaxLocalBidirectionalStreams(10);
|
||||||
|
conn.flowControlState.peerAdvertisedMaxOffset = 100000;
|
||||||
|
conn.flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiRemote = 100000;
|
||||||
|
auto pausedStreamId =
|
||||||
|
(*conn.streamManager->createNextBidirectionalStream())->id;
|
||||||
|
auto regularStreamId =
|
||||||
|
(*conn.streamManager->createNextBidirectionalStream())->id;
|
||||||
|
auto pausedStream = conn.streamManager->findStream(pausedStreamId);
|
||||||
|
auto regularStream = conn.streamManager->findStream(regularStreamId);
|
||||||
|
pausedStream->priority = kPausedPriority;
|
||||||
|
regularStream->priority = kSequentialPriority;
|
||||||
|
|
||||||
|
writeDataToQuicStream(
|
||||||
|
*conn.streamManager->findStream(pausedStream->id),
|
||||||
|
folly::IOBuf::copyBuffer("paused_data"),
|
||||||
|
false);
|
||||||
|
writeDataToQuicStream(
|
||||||
|
*conn.streamManager->findStream(regularStream->id),
|
||||||
|
folly::IOBuf::copyBuffer("regular_data"),
|
||||||
|
false);
|
||||||
|
|
||||||
|
// Should write frames for only regular stream.
|
||||||
|
StreamFrameScheduler scheduler(conn);
|
||||||
|
NiceMock<MockQuicPacketBuilder> mockBuilder;
|
||||||
|
EXPECT_CALL(mockBuilder, remainingSpaceInPkt()).WillRepeatedly(Return(4096));
|
||||||
|
EXPECT_CALL(mockBuilder, appendFrame(_)).WillRepeatedly(Invoke([&](auto f) {
|
||||||
|
mockBuilder.frames_.push_back(f);
|
||||||
|
}));
|
||||||
|
scheduler.writeStreams(mockBuilder);
|
||||||
|
auto& frames = mockBuilder.frames_;
|
||||||
|
ASSERT_EQ(frames.size(), 1);
|
||||||
|
WriteStreamFrame regularFrame(regularStream->id, 0, 12, false);
|
||||||
|
ASSERT_TRUE(frames[0].asWriteStreamFrame());
|
||||||
|
EXPECT_EQ(*frames[0].asWriteStreamFrame(), regularFrame);
|
||||||
|
conn.streamManager->removeWritable(*regularStream);
|
||||||
|
|
||||||
|
// Unpause the stream. Expect the scheduleor to write the data.
|
||||||
|
conn.streamManager->setStreamPriority(pausedStreamId, kSequentialPriority);
|
||||||
|
scheduler.writeStreams(mockBuilder);
|
||||||
|
ASSERT_EQ(frames.size(), 2);
|
||||||
|
WriteStreamFrame pausedFrame(pausedStream->id, 0, 11, false);
|
||||||
|
ASSERT_TRUE(frames[1].asWriteStreamFrame());
|
||||||
|
EXPECT_EQ(*frames[1].asWriteStreamFrame(), pausedFrame);
|
||||||
|
|
||||||
|
// Pause the stream again. Expect no more data writable.
|
||||||
|
conn.streamManager->setStreamPriority(pausedStreamId, kPausedPriority);
|
||||||
|
ASSERT_FALSE(conn.streamManager->hasWritable());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace quic::test
|
} // namespace quic::test
|
||||||
|
@ -41,14 +41,15 @@ using OrderedStreamSet = std::set<OrderedStream, ordered_stream_cmp>;
|
|||||||
struct Priority {
|
struct Priority {
|
||||||
uint8_t level : 3;
|
uint8_t level : 3;
|
||||||
bool incremental : 1;
|
bool incremental : 1;
|
||||||
OrderId orderId : 58;
|
OrderId orderId : 57;
|
||||||
|
bool paused : 1;
|
||||||
|
|
||||||
Priority(uint8_t l, bool i, OrderId o = 0)
|
Priority(uint8_t l, bool i, OrderId o = 0, bool p = false)
|
||||||
: level(l), incremental(i), orderId(o) {}
|
: level(l), incremental(i), orderId(o), paused(p) {}
|
||||||
|
|
||||||
bool operator==(Priority other) const noexcept {
|
bool operator==(Priority other) const noexcept {
|
||||||
return level == other.level && incremental == other.incremental &&
|
return level == other.level && incremental == other.incremental &&
|
||||||
orderId == other.orderId;
|
orderId == other.orderId && paused == other.paused;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -212,11 +213,13 @@ struct PriorityQueue {
|
|||||||
void updateIfExist(StreamId id, Priority priority) {
|
void updateIfExist(StreamId id, Priority priority) {
|
||||||
auto iter = writableStreamsToLevel_.find(id);
|
auto iter = writableStreamsToLevel_.find(id);
|
||||||
if (iter != writableStreamsToLevel_.end()) {
|
if (iter != writableStreamsToLevel_.end()) {
|
||||||
|
CHECK(!priority.paused);
|
||||||
updateExistingStreamPriority(iter, priority);
|
updateExistingStreamPriority(iter, priority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertOrUpdate(StreamId id, Priority pri) {
|
void insertOrUpdate(StreamId id, Priority pri) {
|
||||||
|
CHECK(!pri.paused);
|
||||||
auto it = writableStreamsToLevel_.find(id);
|
auto it = writableStreamsToLevel_.find(id);
|
||||||
auto index = priority2index(pri);
|
auto index = priority2index(pri);
|
||||||
if (it != writableStreamsToLevel_.end()) {
|
if (it != writableStreamsToLevel_.end()) {
|
||||||
|
@ -239,6 +239,7 @@ bool QuicStreamManager::setStreamPriority(StreamId id, Priority newPriority) {
|
|||||||
}
|
}
|
||||||
notifyStreamPriorityChanges();
|
notifyStreamPriorityChanges();
|
||||||
}
|
}
|
||||||
|
updateWritableStreams(*stream);
|
||||||
writeQueue_.updateIfExist(id, stream->priority);
|
writeQueue_.updateIfExist(id, stream->priority);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -669,6 +670,10 @@ void QuicStreamManager::updateWritableStreams(QuicStreamState& stream) {
|
|||||||
removeWritable(stream);
|
removeWritable(stream);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (stream.priority.paused) {
|
||||||
|
removeWritable(stream);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (stream.hasWritableData()) {
|
if (stream.hasWritableData()) {
|
||||||
writableStreams_.emplace(stream.id);
|
writableStreams_.emplace(stream.id);
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user