gfe-relnote: In QUIC bandwidth sampler, only remove packets when RemoveObsoletePackets is called. Protected by --gfe2_reloadable_flag_quic_bw_sampler_remove_packets_once_per_congestion_event.

PiperOrigin-RevId: 285110271
Change-Id: I27567839a190136c03fef54a66261ab34d8c1f82
diff --git a/quic/core/packet_number_indexed_queue.h b/quic/core/packet_number_indexed_queue.h
index 470a58c..269858f 100644
--- a/quic/core/packet_number_indexed_queue.h
+++ b/quic/core/packet_number_indexed_queue.h
@@ -34,6 +34,8 @@
 // just two entries will cause it to consume all of the memory available.
 // Because of that, it is not a general-purpose container and should not be used
 // as one.
+// TODO(wub): Update the comments when deprecating
+// --quic_bw_sampler_remove_packets_once_per_congestion_event.
 template <typename T>
 class QUIC_NO_EXPORT PacketNumberIndexedQueue {
  public:
@@ -60,6 +62,9 @@
   template <typename Function>
   bool Remove(QuicPacketNumber packet_number, Function f);
 
+  // Remove up to, but not including |packet_number|.
+  void RemoveUpTo(QuicPacketNumber packet_number);
+
   bool IsEmpty() const { return number_of_present_entries_ == 0; }
 
   // Returns the number of entries in the queue.
@@ -87,6 +92,9 @@
  private:
   // Wrapper around T used to mark whether the entry is actually in the map.
   struct QUIC_NO_EXPORT EntryWrapper : T {
+    // NOTE(wub): When quic_bw_sampler_remove_packets_once_per_congestion_event
+    // is enabled, |present| is false if and only if this is a placeholder entry
+    // for holes in the parent's |entries|.
     bool present;
 
     EntryWrapper() : present(false) {}
@@ -106,6 +114,9 @@
   }
 
   QuicDeque<EntryWrapper> entries_;
+  // NOTE(wub): When --quic_bw_sampler_remove_packets_once_per_congestion_event
+  // is enabled, |number_of_present_entries_| only represents number of holes,
+  // which does not include number of acked or lost packets.
   size_t number_of_present_entries_;
   QuicPacketNumber first_packet_;
 };
@@ -189,6 +200,21 @@
 }
 
 template <typename T>
+void PacketNumberIndexedQueue<T>::RemoveUpTo(QuicPacketNumber packet_number) {
+  while (!entries_.empty() && first_packet_.IsInitialized() &&
+         first_packet_ < packet_number) {
+    if (entries_.front().present) {
+      number_of_present_entries_--;
+    }
+    entries_.pop_front();
+    first_packet_++;
+  }
+  if (entries_.empty()) {
+    first_packet_.Clear();
+  }
+}
+
+template <typename T>
 void PacketNumberIndexedQueue<T>::Cleanup() {
   while (!entries_.empty() && !entries_.front().present) {
     entries_.pop_front();