Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(178)

Unified Diff: net/quic/stream_sequencer_buffer.h

Issue 1409053006: Create a new data structure StreamSequencerBuffer for QuicStreamSequencer. Currently QuicStreamSequ… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@106492030
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/quic_stream_sequencer_buffer_interface.h ('k') | net/quic/stream_sequencer_buffer.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/stream_sequencer_buffer.h
diff --git a/net/quic/stream_sequencer_buffer.h b/net/quic/stream_sequencer_buffer.h
new file mode 100644
index 0000000000000000000000000000000000000000..c158c0d2455ecc8ff327bfe066d569488e0cb894
--- /dev/null
+++ b/net/quic/stream_sequencer_buffer.h
@@ -0,0 +1,200 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_STREAM_SEQUENCER_BUFFER_H_
+#define NET_QUIC_STREAM_SEQUENCER_BUFFER_H_
+
+// StreamSequencerBuffer implements QuicStreamSequencerBufferInterface.
+// It is a circular stream buffer with random write and
+// in-sequence read. It consists of an std::vector of pointers pointing
+// to memory blocks created as needed and a std::list of Gaps to indicate
+// the missing data between the data already written into the buffer.
+// - Data are written in with offset indicating where it should be in the
+// stream, and the buffer grown as needed (up to the maximum buffer capacity),
+// without expensive copying (extra blocks are allocated).
+// - Data can be read from the buffer if there is no gap before it,
+// and the buffer shrinks as the data are consumed.
+// - An upper limit on the number of blocks in the buffer provides an upper
+// bound on memory use.
+//
+// This class is thread-unsafe.
+//
+// StreamSequencerBuffer maintains a concept of the readable region, which
+// contains all written data that has not been read.
+// It promises stability of the underlying memory addresses in the readable
+// region, so pointers into it can be maintained, and the offset of a pointer
+// from the start of the read region can be calculated.
+//
+// Expected Use:
+// StreamSequencerBuffer buffer(2.5 * 8 * 1024);
+// std::string source(1024, 'a');
+// base::StringPiece std::string_piece(source.data(), source.size());
+// size_t written = 0;
+// buffer.OnStreamData(800, std::string_piece, GetEpollClockNow(), &written);
+// source = std::string{800, 'b'};
+// base::StringPiece std::string_piece1(source.data(), 800);
+// // Try to write to [1, 801), but should fail due to overlapping,
+// // res should be QUIC_INVALID_STREAM_DATA
+// auto res = buffer.OnStreamData(1, std::string_piece1, &written));
+// // write to [0, 800), res should be QUIC_NO_ERROR
+// auto res = buffer.OnStreamData(0, std::string_piece1, GetEpollClockNow(),
+// &written);
+//
+// // Read into a iovec array with total capacity of 120 bytes.
+// char dest[120];
+// iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40},
+// iovec{dest + 80, 40}};
+// size_t read = buffer.Readv(iovecs, 3);
+//
+// // Get single readable region with timestamp.
+// QuicTime t;
+// iovec iov;
+// buffer.GetReadableRegion(iov, &t);
+//
+// // Get readable regions from [256, 1024) and consume some of it.
+// iovec iovs[2];
+// int iov_count = buffer.GetReadableRegions(iovs, 2);
+// // Consume some bytes in iovs, returning number of bytes having been
+// consumed.
+// size_t consumed = consume_iovs(iovs, iov_count);
+// buffer.MarkConsumed(consumed);
+
+#include <functional>
+#include <list>
+#include <memory>
+
+#include "base/macros.h"
+#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_stream_sequencer_buffer_interface.h"
+
+namespace net {
+
+namespace test {
+class StreamSequencerBufferPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE StreamSequencerBuffer : public QuicStreamSequencerBufferInterface {
+ public:
+ // A Gap indicates a missing chunk of bytes between
+ // [begin_offset, end_offset) in the stream
+ struct Gap {
+ Gap(QuicStreamOffset begin_offset, QuicStreamOffset end_offset);
+ QuicStreamOffset begin_offset;
+ QuicStreamOffset end_offset;
+ };
+
+ // A FrameInfo stores the length of a frame and the time it arrived.
+ struct FrameInfo {
+ FrameInfo();
+ FrameInfo(size_t length, QuicTime timestamp);
+
+ size_t length;
+ QuicTime timestamp;
+ };
+
+ // Size of blocks used by this buffer.
+ // Choose 8K to make block large enough to hold multiple frames, each of
+ // which could be up to 1.5 KB.
+ static const size_t kBlockSizeBytes = 8 * 1024; // 8KB
+
+ // The basic storage block used by this buffer.
+ struct BufferBlock {
+ char buffer[kBlockSizeBytes];
+ };
+
+ explicit StreamSequencerBuffer(size_t max_capacity_bytes);
+
+ ~StreamSequencerBuffer() override;
+
+ // QuicStreamSequencerBufferInterface implementation.
+ void Clear() override;
+ bool Empty() const override;
+ QuicErrorCode OnStreamData(QuicStreamOffset offset,
+ base::StringPiece data,
+ QuicTime timestamp,
+ size_t* bytes_buffered) override;
+ size_t Readv(const struct iovec* dest_iov, size_t dest_count) override;
+ int GetReadableRegions(struct iovec* iov, int iov_len) const override;
+ bool GetReadableRegion(iovec* iov, QuicTime* timestamp) const override;
+ bool MarkConsumed(size_t bytes_buffered) override;
+ size_t FlushBufferedFrames() override;
+ bool HasBytesToRead() const override;
+ QuicStreamOffset BytesConsumed() const override;
+ size_t BytesBuffered() const override;
+
+ private:
+ friend class test::StreamSequencerBufferPeer;
+
+ // Dispose the given buffer block.
+ // After calling this method, blocks_[index] is set to nullptr
+ // in order to indicate that no memory set is allocated for that block.
+ void RetireBlock(size_t index);
+
+ // Should only be called after the indexed block is read till the end of the
+ // block or a gap has been reached.
+ // If the block at |block_index| contains no buffered data, then the block is
+ // retired.
+ void RetireBlockIfEmpty(size_t block_index);
+
+ // Called within OnStreamData() to update the gap OnStreamData() writes into
+ // (remove, split or change begin/end offset).
+ void UpdateGapList(std::list<Gap>::iterator gap_with_new_data_written,
+ QuicStreamOffset start_offset,
+ size_t bytes_written);
+
+ // Calculate the capacity of block at specified index.
+ // Return value should be either kBlockSizeBytes for non-trailing blocks and
+ // max_buffer_capacity % kBlockSizeBytes for trailing block.
+ size_t GetBlockCapacity(size_t index) const;
+
+ // Does not check if offset is within reasonable range.
+ size_t GetBlockIndex(QuicStreamOffset offset) const;
+
+ // Given an offset in the stream, return the offset from the beginning of the
+ // block which contains this data.
+ size_t GetInBlockOffset(QuicStreamOffset offset) const;
+
+ // Get offset relative to index 0 in logical 1st block to start next read.
+ size_t ReadOffset() const;
+
+ // Get the index of the logical 1st block to start next read.
+ size_t NextBlockToRead() const;
+
+ // Returns number of bytes available to be read out.
+ size_t ReadableBytes() const;
+
+ // Called after Readv() and MarkConsumed() to keep frame_arrival_time_map_
+ // up to date.
+ // |offset| is the byte next read should start from. All frames before it
+ // should be removed from the map.
+ void UpdateFrameArrivalMap(QuicStreamOffset offset);
+
+ // The maximum total capacity of this buffer in byte, as constructed.
+ const size_t max_buffer_capacity_bytes_;
+
+ // How many blocks this buffer would need when it reaches full capacity.
+ const size_t blocks_count_;
+
+ // Number of bytes read out of buffer.
+ QuicStreamOffset total_bytes_read_;
+
+ // Contains Gaps which represents currently missing data.
+ std::list<Gap> gaps_;
+
+ // An ordered, variable-length std::list of blocks, with the length limited
+ // such that the number of blocks never exceeds blocks_count_.
+ // Each std::list entry can hold up to kBlockSizeBytes bytes.
+ std::vector<BufferBlock*> blocks_;
+
+ // Number of bytes in buffer.
+ size_t num_bytes_buffered_;
+
+ // Stores all the buffered frames' start offset, length and arrival time.
+ std::map<QuicStreamOffset, FrameInfo> frame_arrival_time_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(StreamSequencerBuffer);
+};
+} // namespace net
+
+#endif // NET_QUIC_STREAM_SEQUENCER_BUFFER_H_
« no previous file with comments | « net/quic/quic_stream_sequencer_buffer_interface.h ('k') | net/quic/stream_sequencer_buffer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698