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);