Make HpackEntry::insertion_index_ start from 0 for dynamic entries.

Adding a constant offset of 61 does not add any value.  The calculation of
the HPACK index (which is 61 for the most recently added entry and growing for
older entries) involves a subtraction in GetByName() and GetByNameAndValue(),
and this offset cancels between total_insertion_ and entry->InsertionIndex(),
that's why that formula does not change with this CL.

Also add a couple of CHECKs involving InsertionIndex() to validate the formula
that will be used in the next CL which removes InsertionIndex().

PiperOrigin-RevId: 363924862
Change-Id: Ieea5a0a906229427f4af2c14f57074cf1e299b63
diff --git a/quic/core/qpack/qpack_header_table.cc b/quic/core/qpack/qpack_header_table.cc
index 36dddfc..9c12524 100644
--- a/quic/core/qpack/qpack_header_table.cc
+++ b/quic/core/qpack/qpack_header_table.cc
@@ -163,10 +163,14 @@
   // Initialize to current available capacity.
   uint64_t max_insert_size = dynamic_table_capacity_ - dynamic_table_size_;
 
+  uint64_t entry_index = dropped_entry_count_;
   for (const auto& entry : dynamic_entries_) {
+    // TODO(b/182789212): Remove InsertionIndex(), use entry_index instead.
+    QUICHE_CHECK_EQ(entry_index, entry.InsertionIndex());
     if (entry.InsertionIndex() >= index) {
       break;
     }
+    ++entry_index;
     max_insert_size += entry.Size();
   }
 
@@ -232,14 +236,18 @@
   }
 
   auto it = dynamic_entries_.begin();
+  uint64_t entry_index = dropped_entry_count_;
   while (space_above_draining_index < required_space) {
     space_above_draining_index += it->Size();
+    QUICHE_CHECK_EQ(entry_index, it->InsertionIndex());
     ++it;
+    ++entry_index;
     if (it == dynamic_entries_.end()) {
       return inserted_entry_count();
     }
   }
 
+  // TODO(b/182789212): Remove InsertionIndex(), use entry_index instead.
   return it->InsertionIndex();
 }
 
@@ -248,11 +256,15 @@
     QUICHE_DCHECK(!dynamic_entries_.empty());
 
     QpackEntry* const entry = &dynamic_entries_.front();
-    const uint64_t entry_size = entry->Size();
 
+    const uint64_t entry_size = entry->Size();
     QUICHE_DCHECK_GE(dynamic_table_size_, entry_size);
     dynamic_table_size_ -= entry_size;
 
+    // TODO(b/182789212): Remove InsertionIndex(), use dropped_entry_count_
+    // instead.
+    QUICHE_CHECK_EQ(dropped_entry_count_, entry->InsertionIndex());
+
     auto index_it = dynamic_index_.find({entry->name(), entry->value()});
     // Remove |dynamic_index_| entry only if it points to the same
     // QpackEntry in |dynamic_entries_|.
diff --git a/spdy/core/hpack/hpack_entry.h b/spdy/core/hpack/hpack_entry.h
index fb37640..1db5297 100644
--- a/spdy/core/hpack/hpack_entry.h
+++ b/spdy/core/hpack/hpack_entry.h
@@ -43,9 +43,9 @@
 class QUICHE_EXPORT_PRIVATE HpackEntry {
  public:
   // Copies |name| and |value| in the constructor.
-  // |insertion_index| is this entry's index in the total set of entries ever
-  // inserted into the header table (including static entries).  This allows an
-  // HpackEntryTable to determine the index of an HpackEntry in O(1) time.
+  // TODO(b/182789212): Remove |insertion_index|.
+  // |insertion_index| starts from 0, separately for static entries and dynamic
+  // entries.
   HpackEntry(absl::string_view name,
              absl::string_view value,
              size_t insertion_index);
@@ -75,8 +75,9 @@
   std::string name_;
   std::string value_;
 
-  // The entry's index in the total set of entries ever inserted into the header
-  // table.
+  // TODO(b/182789212): Remove |insertion_index_|.
+  // |insertion_index_| starts from 0, separately for static entries and dynamic
+  // entries.
   size_t insertion_index_;
 };
 
diff --git a/spdy/core/hpack/hpack_header_table.cc b/spdy/core/hpack/hpack_header_table.cc
index be8cef9..0f0fafc 100644
--- a/spdy/core/hpack/hpack_header_table.cc
+++ b/spdy/core/hpack/hpack_header_table.cc
@@ -21,7 +21,7 @@
       settings_size_bound_(kDefaultHeaderTableSizeSetting),
       size_(0),
       max_size_(kDefaultHeaderTableSizeSetting),
-      total_insertions_(kStaticTableSize) {}
+      dynamic_table_insertions_(0) {}
 
 HpackHeaderTable::~HpackHeaderTable() = default;
 
@@ -50,7 +50,7 @@
   {
     NameToEntryMap::const_iterator it = dynamic_name_index_.find(name);
     if (it != dynamic_name_index_.end()) {
-      return total_insertions_ - it->second->InsertionIndex() +
+      return dynamic_table_insertions_ - it->second->InsertionIndex() +
              kStaticTableSize;
     }
   }
@@ -69,7 +69,7 @@
   {
     auto it = dynamic_index_.find(query);
     if (it != dynamic_index_.end()) {
-      return total_insertions_ - it->second->InsertionIndex() +
+      return dynamic_table_insertions_ - it->second->InsertionIndex() +
              kStaticTableSize;
     }
   }
@@ -125,6 +125,9 @@
   for (size_t i = 0; i != count; ++i) {
     QUICHE_CHECK(!dynamic_entries_.empty());
     HpackEntry* entry = &dynamic_entries_.back();
+    // TODO(b/182789212): Remove InsertionIndex().
+    QUICHE_CHECK_EQ(dynamic_table_insertions_ - dynamic_entries_.size(),
+                    entry->InsertionIndex());
 
     size_ -= entry->Size();
     auto it = dynamic_index_.find({entry->name(), entry->value()});
@@ -161,7 +164,7 @@
     QUICHE_DCHECK_EQ(0u, size_);
     return nullptr;
   }
-  dynamic_entries_.emplace_front(name, value, total_insertions_);
+  dynamic_entries_.emplace_front(name, value, dynamic_table_insertions_);
   HpackEntry* new_entry = &dynamic_entries_.front();
   auto index_result = dynamic_index_.insert(std::make_pair(
       HpackLookupEntry{new_entry->name(), new_entry->value()}, new_entry));
@@ -196,7 +199,7 @@
   }
 
   size_ += entry_size;
-  ++total_insertions_;
+  ++dynamic_table_insertions_;
 
   return &dynamic_entries_.front();
 }
diff --git a/spdy/core/hpack/hpack_header_table.h b/spdy/core/hpack/hpack_header_table.h
index d82676e..1022d11 100644
--- a/spdy/core/hpack/hpack_header_table.h
+++ b/spdy/core/hpack/hpack_header_table.h
@@ -153,9 +153,9 @@
   size_t size_;
   size_t max_size_;
 
-  // Total number of table insertions which have occurred,
-  // including initial static table insertions.
-  size_t total_insertions_;
+  // Total number of dynamic table insertions so far
+  // (including entries that have been evicted).
+  size_t dynamic_table_insertions_;
 };
 
 }  // namespace spdy
diff --git a/spdy/core/hpack/hpack_header_table_test.cc b/spdy/core/hpack/hpack_header_table_test.cc
index 8dc6c3d..78d22cc 100644
--- a/spdy/core/hpack/hpack_header_table_test.cc
+++ b/spdy/core/hpack/hpack_header_table_test.cc
@@ -31,6 +31,7 @@
   const HpackHeaderTable::EntryTable& static_entries() {
     return table_->static_entries_;
   }
+  // TODO(b/182789212): Remove this method, because it does not add any value.
   size_t index_size() {
     return table_->static_index_.size() + table_->dynamic_index_.size();
   }
@@ -44,7 +45,10 @@
     }
     return result;
   }
-  size_t total_insertions() { return table_->total_insertions_; }
+  size_t dynamic_table_insertions() {
+    return table_->dynamic_table_insertions_;
+  }
+  // TODO(b/182789212): Inline this method.
   size_t dynamic_entries_count() { return table_->dynamic_entries_.size(); }
   size_t EvictionCountForEntry(absl::string_view name,
                                absl::string_view value) {
@@ -127,10 +131,10 @@
   EXPECT_EQ(kDefaultHeaderTableSizeSetting, table_.settings_size_bound());
 
   EXPECT_EQ(0u, peer_.dynamic_entries_count());
-  EXPECT_EQ(peer_.static_entries().size(), peer_.total_insertions());
+  EXPECT_EQ(0u, peer_.dynamic_table_insertions());
 
   // Static entries have been populated and inserted into the table & index.
-  EXPECT_NE(0u, peer_.static_entries().size());
+  EXPECT_EQ(kStaticTableSize, peer_.static_entries().size());
   EXPECT_EQ(peer_.index_size(), peer_.static_entries().size());
   for (size_t i = 0; i != peer_.static_entries().size(); ++i) {
     const HpackEntry* entry = &peer_.static_entries()[i];
@@ -142,8 +146,6 @@
 }
 
 TEST_F(HpackHeaderTableTest, BasicDynamicEntryInsertionAndEviction) {
-  size_t static_count = peer_.total_insertions();
-
   const HpackEntry* first_static_entry = table_.GetByIndex(1);
   EXPECT_EQ(first_static_entry, table_.GetByIndex(1));
 
@@ -155,8 +157,7 @@
   EXPECT_EQ(entry->Size(), table_.size());
   EXPECT_EQ(1u, peer_.dynamic_entries_count());
   EXPECT_EQ(peer_.dynamic_entries().size(), peer_.dynamic_entries_count());
-  EXPECT_EQ(static_count + 1, peer_.total_insertions());
-  EXPECT_EQ(static_count + 1, peer_.index_size());
+  EXPECT_EQ(kStaticTableSize + 1, peer_.index_size());
 
   EXPECT_EQ(entry, table_.GetByIndex(62));
 
@@ -168,8 +169,7 @@
   EXPECT_EQ(0u, table_.size());
   EXPECT_EQ(0u, peer_.dynamic_entries_count());
   EXPECT_EQ(peer_.dynamic_entries().size(), peer_.dynamic_entries_count());
-  EXPECT_EQ(static_count + 1, peer_.total_insertions());
-  EXPECT_EQ(static_count, peer_.index_size());
+  EXPECT_EQ(kStaticTableSize, peer_.index_size());
 
   // Index of |first_static_entry| does not change.
   EXPECT_EQ(first_static_entry, table_.GetByIndex(1));