Track unacknowledged references on the encoder stream in QpackBlockingManager.

gfe-relnote: n/a, change to QUIC v99-only code.  Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 263116461
Change-Id: I928d3b06dfbc8de7ad8995b739f49c65856237b2
diff --git a/quic/core/qpack/qpack_blocking_manager.cc b/quic/core/qpack/qpack_blocking_manager.cc
index e8e4f87..04d824f 100644
--- a/quic/core/qpack/qpack_blocking_manager.cc
+++ b/quic/core/qpack/qpack_blocking_manager.cc
@@ -23,7 +23,7 @@
 
   const uint64_t required_index_count = RequiredInsertCount(indices);
   if (known_received_count_ < required_index_count) {
-    known_received_count_ = required_index_count;
+    IncreaseKnownReceivedCountTo(required_index_count);
   }
 
   DecreaseReferenceCounts(indices);
@@ -50,7 +50,7 @@
 }
 
 void QpackBlockingManager::OnInsertCountIncrement(uint64_t increment) {
-  known_received_count_ += increment;
+  IncreaseKnownReceivedCountTo(known_received_count_ + increment);
 }
 
 void QpackBlockingManager::OnHeaderBlockSent(QuicStreamId stream_id,
@@ -61,6 +61,16 @@
   header_blocks_[stream_id].push_back(std::move(indices));
 }
 
+void QpackBlockingManager::OnReferenceSentOnEncoderStream(
+    uint64_t inserted_index,
+    uint64_t referred_index) {
+  auto result = unacked_encoder_stream_references_.insert(
+      {inserted_index, referred_index});
+  // Each dynamic table entry can refer to at most one |referred_index|.
+  DCHECK(result.second);
+  IncreaseReferenceCounts({referred_index});
+}
+
 uint64_t QpackBlockingManager::blocked_stream_count() const {
   uint64_t blocked_stream_count = 0;
   for (const auto& header_blocks_for_stream : header_blocks_) {
@@ -86,6 +96,26 @@
   return *indices.rbegin() + 1;
 }
 
+void QpackBlockingManager::IncreaseKnownReceivedCountTo(
+    uint64_t new_known_received_count) {
+  DCHECK_GT(new_known_received_count, known_received_count_);
+
+  known_received_count_ = new_known_received_count;
+
+  // Remove referred indices with key less than new Known Received Count from
+  // |unacked_encoder_stream_references_| and |entry_reference_counts_|.
+  IndexSet acknowledged_references;
+  auto it = unacked_encoder_stream_references_.begin();
+  while (it != unacked_encoder_stream_references_.end() &&
+         it->first < known_received_count_) {
+    acknowledged_references.insert(it->second);
+    ++it;
+  }
+  unacked_encoder_stream_references_.erase(
+      unacked_encoder_stream_references_.begin(), it);
+  DecreaseReferenceCounts(acknowledged_references);
+}
+
 void QpackBlockingManager::IncreaseReferenceCounts(const IndexSet& indices) {
   for (const uint64_t index : indices) {
     auto it = entry_reference_counts_.lower_bound(index);