Add QpackHeaderTable::MaxInsertSizeWithoutEvictingGivenEntry().
gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 260535294
Change-Id: Ica02434e33e5a60d51d297f7837e0726dc1cbd3c
diff --git a/quic/core/qpack/qpack_header_table.cc b/quic/core/qpack/qpack_header_table.cc
index 92eb072..3c9296d 100644
--- a/quic/core/qpack/qpack_header_table.cc
+++ b/quic/core/qpack/qpack_header_table.cc
@@ -141,6 +141,28 @@
return new_entry;
}
+uint64_t QpackHeaderTable::MaxInsertSizeWithoutEvictingGivenEntry(
+ uint64_t index) const {
+ DCHECK_LE(dropped_entry_count_, index);
+
+ if (index > inserted_entry_count()) {
+ // All entries are allowed to be evicted.
+ return dynamic_table_capacity_;
+ }
+
+ // Initialize to current available capacity.
+ uint64_t max_insert_size = dynamic_table_capacity_ - dynamic_table_size_;
+
+ for (const auto& entry : dynamic_entries_) {
+ if (entry.InsertionIndex() >= index) {
+ break;
+ }
+ max_insert_size += entry.Size();
+ }
+
+ return max_insert_size;
+}
+
bool QpackHeaderTable::SetDynamicTableCapacity(uint64_t capacity) {
if (capacity > maximum_dynamic_table_capacity_) {
return false;
diff --git a/quic/core/qpack/qpack_header_table.h b/quic/core/qpack/qpack_header_table.h
index 54b0829..4e3b77c 100644
--- a/quic/core/qpack/qpack_header_table.h
+++ b/quic/core/qpack/qpack_header_table.h
@@ -70,6 +70,12 @@
// is larger than the capacity of the dynamic table.
const QpackEntry* InsertEntry(QuicStringPiece name, QuicStringPiece value);
+ // Returns the size of the largest entry that could be inserted into the
+ // dynamic table without evicting entry |index|. |index| might be larger than
+ // inserted_entry_count(), in which case the capacity of the table is
+ // returned. |index| must not be smaller than dropped_entry_count().
+ uint64_t MaxInsertSizeWithoutEvictingGivenEntry(uint64_t index) const;
+
// Change dynamic table capacity to |capacity|. Returns true on success.
// Returns false is |capacity| exceeds maximum dynamic table capacity.
bool SetDynamicTableCapacity(uint64_t capacity);
diff --git a/quic/core/qpack/qpack_header_table_test.cc b/quic/core/qpack/qpack_header_table_test.cc
index 7d1044b..592d2cb 100644
--- a/quic/core/qpack/qpack_header_table_test.cc
+++ b/quic/core/qpack/qpack_header_table_test.cc
@@ -365,6 +365,55 @@
/* expected_is_static = */ false, 2u);
}
+// Returns the size of the largest entry that could be inserted into the
+// dynamic table without evicting entry |index|.
+TEST_F(QpackHeaderTableTest, MaxInsertSizeWithoutEvictingGivenEntry) {
+ const uint64_t dynamic_table_capacity = 100;
+ QpackHeaderTable table;
+ table.SetMaximumDynamicTableCapacity(dynamic_table_capacity);
+
+ // Empty table can take an entry up to its capacity.
+ EXPECT_EQ(dynamic_table_capacity,
+ table.MaxInsertSizeWithoutEvictingGivenEntry(0));
+
+ const uint64_t entry_size1 = QpackEntry::Size("foo", "bar");
+ EXPECT_TRUE(table.InsertEntry("foo", "bar"));
+ EXPECT_EQ(dynamic_table_capacity - entry_size1,
+ table.MaxInsertSizeWithoutEvictingGivenEntry(0));
+ // Table can take an entry up to its capacity if all entries are allowed to be
+ // evicted.
+ EXPECT_EQ(dynamic_table_capacity,
+ table.MaxInsertSizeWithoutEvictingGivenEntry(1));
+
+ const uint64_t entry_size2 = QpackEntry::Size("baz", "foobar");
+ EXPECT_TRUE(table.InsertEntry("baz", "foobar"));
+ // Table can take an entry up to its capacity if all entries are allowed to be
+ // evicted.
+ EXPECT_EQ(dynamic_table_capacity,
+ table.MaxInsertSizeWithoutEvictingGivenEntry(2));
+ // Second entry must stay.
+ EXPECT_EQ(dynamic_table_capacity - entry_size2,
+ table.MaxInsertSizeWithoutEvictingGivenEntry(1));
+ // First and second entry must stay.
+ EXPECT_EQ(dynamic_table_capacity - entry_size2 - entry_size1,
+ table.MaxInsertSizeWithoutEvictingGivenEntry(0));
+
+ // Third entry evicts first one.
+ const uint64_t entry_size3 = QpackEntry::Size("last", "entry");
+ EXPECT_TRUE(table.InsertEntry("last", "entry"));
+ EXPECT_EQ(1u, table.dropped_entry_count());
+ // Table can take an entry up to its capacity if all entries are allowed to be
+ // evicted.
+ EXPECT_EQ(dynamic_table_capacity,
+ table.MaxInsertSizeWithoutEvictingGivenEntry(3));
+ // Third entry must stay.
+ EXPECT_EQ(dynamic_table_capacity - entry_size3,
+ table.MaxInsertSizeWithoutEvictingGivenEntry(2));
+ // Second and third entry must stay.
+ EXPECT_EQ(dynamic_table_capacity - entry_size3 - entry_size2,
+ table.MaxInsertSizeWithoutEvictingGivenEntry(1));
+}
+
TEST_F(QpackHeaderTableTest, Observer) {
StrictMock<MockObserver> observer1;
RegisterObserver(&observer1, 1);