OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef NET_QUIC_STREAM_SEQUENCER_BUFFER_H_ |
| 6 #define NET_QUIC_STREAM_SEQUENCER_BUFFER_H_ |
| 7 |
| 8 // StreamSequencerBuffer implements QuicStreamSequencerBufferInterface. |
| 9 // It is a circular stream buffer with random write and |
| 10 // in-sequence read. It consists of an std::vector of pointers pointing |
| 11 // to memory blocks created as needed and a std::list of Gaps to indicate |
| 12 // the missing data between the data already written into the buffer. |
| 13 // - Data are written in with offset indicating where it should be in the |
| 14 // stream, and the buffer grown as needed (up to the maximum buffer capacity), |
| 15 // without expensive copying (extra blocks are allocated). |
| 16 // - Data can be read from the buffer if there is no gap before it, |
| 17 // and the buffer shrinks as the data are consumed. |
| 18 // - An upper limit on the number of blocks in the buffer provides an upper |
| 19 // bound on memory use. |
| 20 // |
| 21 // This class is thread-unsafe. |
| 22 // |
| 23 // StreamSequencerBuffer maintains a concept of the readable region, which |
| 24 // contains all written data that has not been read. |
| 25 // It promises stability of the underlying memory addresses in the readable |
| 26 // region, so pointers into it can be maintained, and the offset of a pointer |
| 27 // from the start of the read region can be calculated. |
| 28 // |
| 29 // Expected Use: |
| 30 // StreamSequencerBuffer buffer(2.5 * 8 * 1024); |
| 31 // std::string source(1024, 'a'); |
| 32 // base::StringPiece std::string_piece(source.data(), source.size()); |
| 33 // size_t written = 0; |
| 34 // buffer.OnStreamData(800, std::string_piece, GetEpollClockNow(), &written); |
| 35 // source = std::string{800, 'b'}; |
| 36 // base::StringPiece std::string_piece1(source.data(), 800); |
| 37 // // Try to write to [1, 801), but should fail due to overlapping, |
| 38 // // res should be QUIC_INVALID_STREAM_DATA |
| 39 // auto res = buffer.OnStreamData(1, std::string_piece1, &written)); |
| 40 // // write to [0, 800), res should be QUIC_NO_ERROR |
| 41 // auto res = buffer.OnStreamData(0, std::string_piece1, GetEpollClockNow(), |
| 42 // &written); |
| 43 // |
| 44 // // Read into a iovec array with total capacity of 120 bytes. |
| 45 // char dest[120]; |
| 46 // iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, |
| 47 // iovec{dest + 80, 40}}; |
| 48 // size_t read = buffer.Readv(iovecs, 3); |
| 49 // |
| 50 // // Get single readable region with timestamp. |
| 51 // QuicTime t; |
| 52 // iovec iov; |
| 53 // buffer.GetReadableRegion(iov, &t); |
| 54 // |
| 55 // // Get readable regions from [256, 1024) and consume some of it. |
| 56 // iovec iovs[2]; |
| 57 // int iov_count = buffer.GetReadableRegions(iovs, 2); |
| 58 // // Consume some bytes in iovs, returning number of bytes having been |
| 59 // consumed. |
| 60 // size_t consumed = consume_iovs(iovs, iov_count); |
| 61 // buffer.MarkConsumed(consumed); |
| 62 |
| 63 #include <functional> |
| 64 #include <list> |
| 65 #include <memory> |
| 66 |
| 67 #include "base/macros.h" |
| 68 #include "net/quic/quic_protocol.h" |
| 69 #include "net/quic/quic_stream_sequencer_buffer_interface.h" |
| 70 |
| 71 namespace net { |
| 72 |
| 73 namespace test { |
| 74 class StreamSequencerBufferPeer; |
| 75 } // namespace test |
| 76 |
| 77 class NET_EXPORT_PRIVATE StreamSequencerBuffer |
| 78 : public QuicStreamSequencerBufferInterface { |
| 79 public: |
| 80 // A Gap indicates a missing chunk of bytes between |
| 81 // [begin_offset, end_offset) in the stream |
| 82 struct Gap { |
| 83 Gap(QuicStreamOffset begin_offset, QuicStreamOffset end_offset); |
| 84 QuicStreamOffset begin_offset; |
| 85 QuicStreamOffset end_offset; |
| 86 }; |
| 87 |
| 88 // A FrameInfo stores the length of a frame and the time it arrived. |
| 89 struct NET_EXPORT_PRIVATE FrameInfo { |
| 90 FrameInfo(); |
| 91 FrameInfo(size_t length, QuicTime timestamp); |
| 92 |
| 93 size_t length; |
| 94 QuicTime timestamp; |
| 95 }; |
| 96 |
| 97 // Size of blocks used by this buffer. |
| 98 // Choose 8K to make block large enough to hold multiple frames, each of |
| 99 // which could be up to 1.5 KB. |
| 100 static const size_t kBlockSizeBytes = 8 * 1024; // 8KB |
| 101 |
| 102 // The basic storage block used by this buffer. |
| 103 struct BufferBlock { |
| 104 char buffer[kBlockSizeBytes]; |
| 105 }; |
| 106 |
| 107 explicit StreamSequencerBuffer(size_t max_capacity_bytes); |
| 108 |
| 109 ~StreamSequencerBuffer() override; |
| 110 |
| 111 // QuicStreamSequencerBufferInterface implementation. |
| 112 void Clear() override; |
| 113 bool Empty() const override; |
| 114 QuicErrorCode OnStreamData(QuicStreamOffset offset, |
| 115 base::StringPiece data, |
| 116 QuicTime timestamp, |
| 117 size_t* bytes_buffered) override; |
| 118 size_t Readv(const struct iovec* dest_iov, size_t dest_count) override; |
| 119 int GetReadableRegions(struct iovec* iov, int iov_len) const override; |
| 120 bool GetReadableRegion(iovec* iov, QuicTime* timestamp) const override; |
| 121 bool MarkConsumed(size_t bytes_buffered) override; |
| 122 size_t FlushBufferedFrames() override; |
| 123 bool HasBytesToRead() const override; |
| 124 QuicStreamOffset BytesConsumed() const override; |
| 125 size_t BytesBuffered() const override; |
| 126 |
| 127 private: |
| 128 friend class test::StreamSequencerBufferPeer; |
| 129 |
| 130 // Dispose the given buffer block. |
| 131 // After calling this method, blocks_[index] is set to nullptr |
| 132 // in order to indicate that no memory set is allocated for that block. |
| 133 void RetireBlock(size_t index); |
| 134 |
| 135 // Should only be called after the indexed block is read till the end of the |
| 136 // block or a gap has been reached. |
| 137 // If the block at |block_index| contains no buffered data, then the block is |
| 138 // retired. |
| 139 void RetireBlockIfEmpty(size_t block_index); |
| 140 |
| 141 // Called within OnStreamData() to update the gap OnStreamData() writes into |
| 142 // (remove, split or change begin/end offset). |
| 143 void UpdateGapList(std::list<Gap>::iterator gap_with_new_data_written, |
| 144 QuicStreamOffset start_offset, |
| 145 size_t bytes_written); |
| 146 |
| 147 // Calculate the capacity of block at specified index. |
| 148 // Return value should be either kBlockSizeBytes for non-trailing blocks and |
| 149 // max_buffer_capacity % kBlockSizeBytes for trailing block. |
| 150 size_t GetBlockCapacity(size_t index) const; |
| 151 |
| 152 // Does not check if offset is within reasonable range. |
| 153 size_t GetBlockIndex(QuicStreamOffset offset) const; |
| 154 |
| 155 // Given an offset in the stream, return the offset from the beginning of the |
| 156 // block which contains this data. |
| 157 size_t GetInBlockOffset(QuicStreamOffset offset) const; |
| 158 |
| 159 // Get offset relative to index 0 in logical 1st block to start next read. |
| 160 size_t ReadOffset() const; |
| 161 |
| 162 // Get the index of the logical 1st block to start next read. |
| 163 size_t NextBlockToRead() const; |
| 164 |
| 165 // Returns number of bytes available to be read out. |
| 166 size_t ReadableBytes() const; |
| 167 |
| 168 // Called after Readv() and MarkConsumed() to keep frame_arrival_time_map_ |
| 169 // up to date. |
| 170 // |offset| is the byte next read should start from. All frames before it |
| 171 // should be removed from the map. |
| 172 void UpdateFrameArrivalMap(QuicStreamOffset offset); |
| 173 |
| 174 // The maximum total capacity of this buffer in byte, as constructed. |
| 175 const size_t max_buffer_capacity_bytes_; |
| 176 |
| 177 // How many blocks this buffer would need when it reaches full capacity. |
| 178 const size_t blocks_count_; |
| 179 |
| 180 // Number of bytes read out of buffer. |
| 181 QuicStreamOffset total_bytes_read_; |
| 182 |
| 183 // Contains Gaps which represents currently missing data. |
| 184 std::list<Gap> gaps_; |
| 185 |
| 186 // An ordered, variable-length std::list of blocks, with the length limited |
| 187 // such that the number of blocks never exceeds blocks_count_. |
| 188 // Each std::list entry can hold up to kBlockSizeBytes bytes. |
| 189 std::vector<BufferBlock*> blocks_; |
| 190 |
| 191 // Number of bytes in buffer. |
| 192 size_t num_bytes_buffered_; |
| 193 |
| 194 // Stores all the buffered frames' start offset, length and arrival time. |
| 195 std::map<QuicStreamOffset, FrameInfo> frame_arrival_time_map_; |
| 196 |
| 197 DISALLOW_COPY_AND_ASSIGN(StreamSequencerBuffer); |
| 198 }; |
| 199 } // namespace net |
| 200 |
| 201 #endif // NET_QUIC_STREAM_SEQUENCER_BUFFER_H_ |
OLD | NEW |