OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/core/quic_stream_sequencer_buffer.h" | 5 #include "net/quic/core/quic_stream_sequencer_buffer.h" |
6 | 6 |
7 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 num_bytes_buffered_ = 0; | 73 num_bytes_buffered_ = 0; |
74 // Reset gaps_ so that buffer is in a state as if all data before | 74 // Reset gaps_ so that buffer is in a state as if all data before |
75 // total_bytes_read_ has been consumed, and those after total_bytes_read_ | 75 // total_bytes_read_ has been consumed, and those after total_bytes_read_ |
76 // has never arrived. | 76 // has never arrived. |
77 gaps_ = std::list<Gap>( | 77 gaps_ = std::list<Gap>( |
78 1, Gap(total_bytes_read_, std::numeric_limits<QuicStreamOffset>::max())), | 78 1, Gap(total_bytes_read_, std::numeric_limits<QuicStreamOffset>::max())), |
79 frame_arrival_time_map_.clear(); | 79 frame_arrival_time_map_.clear(); |
80 } | 80 } |
81 | 81 |
82 bool QuicStreamSequencerBuffer::RetireBlock(size_t idx) { | 82 bool QuicStreamSequencerBuffer::RetireBlock(size_t idx) { |
83 if (FLAGS_quic_stream_sequencer_buffer_debug && blocks_[idx] == nullptr) { | 83 if (blocks_[idx] == nullptr) { |
84 QUIC_BUG << "Try to retire block twice"; | 84 QUIC_BUG << "Try to retire block twice"; |
85 return false; | 85 return false; |
86 } | 86 } |
87 delete blocks_[idx]; | 87 delete blocks_[idx]; |
88 blocks_[idx] = nullptr; | 88 blocks_[idx] = nullptr; |
89 DVLOG(1) << "Retired block with index: " << idx; | 89 DVLOG(1) << "Retired block with index: " << idx; |
90 return true; | 90 return true; |
91 } | 91 } |
92 | 92 |
93 QuicErrorCode QuicStreamSequencerBuffer::OnStreamData( | 93 QuicErrorCode QuicStreamSequencerBuffer::OnStreamData( |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 bytes_avail = total_bytes_read_ + max_buffer_capacity_bytes_ - offset; | 181 bytes_avail = total_bytes_read_ + max_buffer_capacity_bytes_ - offset; |
182 } | 182 } |
183 | 183 |
184 if (reduce_sequencer_buffer_memory_life_time_ && blocks_ == nullptr) { | 184 if (reduce_sequencer_buffer_memory_life_time_ && blocks_ == nullptr) { |
185 blocks_.reset(new BufferBlock*[blocks_count_]()); | 185 blocks_.reset(new BufferBlock*[blocks_count_]()); |
186 for (size_t i = 0; i < blocks_count_; ++i) { | 186 for (size_t i = 0; i < blocks_count_; ++i) { |
187 blocks_[i] = nullptr; | 187 blocks_[i] = nullptr; |
188 } | 188 } |
189 } | 189 } |
190 | 190 |
191 if (FLAGS_quic_stream_sequencer_buffer_debug && | 191 if (write_block_num >= blocks_count_) { |
192 write_block_num >= blocks_count_) { | |
193 *error_details = StringPrintf( | 192 *error_details = StringPrintf( |
194 "QuicStreamSequencerBuffer error: OnStreamData() exceed array bounds." | 193 "QuicStreamSequencerBuffer error: OnStreamData() exceed array bounds." |
195 "write offset = %" PRIu64 " write_block_num = %" PRIuS | 194 "write offset = %" PRIu64 " write_block_num = %" PRIuS |
196 " blocks_count_ = %" PRIuS, | 195 " blocks_count_ = %" PRIuS, |
197 offset, write_block_num, blocks_count_); | 196 offset, write_block_num, blocks_count_); |
198 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 197 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
199 } | 198 } |
200 if (blocks_ == nullptr) { | 199 if (blocks_ == nullptr) { |
201 *error_details = | 200 *error_details = |
202 "QuicStreamSequencerBuffer error: OnStreamData() blocks_ is null"; | 201 "QuicStreamSequencerBuffer error: OnStreamData() blocks_ is null"; |
203 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 202 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
204 } | 203 } |
205 if (blocks_[write_block_num] == nullptr) { | 204 if (blocks_[write_block_num] == nullptr) { |
206 // TODO(danzh): Investigate if using a freelist would improve performance. | 205 // TODO(danzh): Investigate if using a freelist would improve performance. |
207 // Same as RetireBlock(). | 206 // Same as RetireBlock(). |
208 blocks_[write_block_num] = new BufferBlock(); | 207 blocks_[write_block_num] = new BufferBlock(); |
209 } | 208 } |
210 | 209 |
211 const size_t bytes_to_copy = min<size_t>(bytes_avail, source_remaining); | 210 const size_t bytes_to_copy = min<size_t>(bytes_avail, source_remaining); |
212 char* dest = blocks_[write_block_num]->buffer + write_block_offset; | 211 char* dest = blocks_[write_block_num]->buffer + write_block_offset; |
213 DVLOG(1) << "Write at offset: " << offset << " length: " << bytes_to_copy; | 212 DVLOG(1) << "Write at offset: " << offset << " length: " << bytes_to_copy; |
214 | 213 |
215 if (FLAGS_quic_stream_sequencer_buffer_debug && | 214 if (dest == nullptr || source == nullptr) { |
216 (dest == nullptr || source == nullptr)) { | |
217 *error_details = StringPrintf( | 215 *error_details = StringPrintf( |
218 "QuicStreamSequencerBuffer error: OnStreamData()" | 216 "QuicStreamSequencerBuffer error: OnStreamData()" |
219 " dest == nullptr: %s" | 217 " dest == nullptr: %s" |
220 " source == nullptr: %s" | 218 " source == nullptr: %s" |
221 " Writing at offset %" PRIu64 | 219 " Writing at offset %" PRIu64 |
222 " Gaps: %s" | 220 " Gaps: %s" |
223 " Remaining frames: %s" | 221 " Remaining frames: %s" |
224 " total_bytes_read_ = %" PRIu64, | 222 " total_bytes_read_ = %" PRIu64, |
225 (dest == nullptr ? "true" : "false"), | 223 (dest == nullptr ? "true" : "false"), |
226 (source == nullptr ? "true" : "false"), offset, | 224 (source == nullptr ? "true" : "false"), offset, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 size_t dest_remaining = dest_iov[i].iov_len; | 283 size_t dest_remaining = dest_iov[i].iov_len; |
286 while (dest_remaining > 0 && ReadableBytes() > 0) { | 284 while (dest_remaining > 0 && ReadableBytes() > 0) { |
287 size_t block_idx = NextBlockToRead(); | 285 size_t block_idx = NextBlockToRead(); |
288 size_t start_offset_in_block = ReadOffset(); | 286 size_t start_offset_in_block = ReadOffset(); |
289 size_t block_capacity = GetBlockCapacity(block_idx); | 287 size_t block_capacity = GetBlockCapacity(block_idx); |
290 size_t bytes_available_in_block = | 288 size_t bytes_available_in_block = |
291 min<size_t>(ReadableBytes(), block_capacity - start_offset_in_block); | 289 min<size_t>(ReadableBytes(), block_capacity - start_offset_in_block); |
292 size_t bytes_to_copy = | 290 size_t bytes_to_copy = |
293 min<size_t>(bytes_available_in_block, dest_remaining); | 291 min<size_t>(bytes_available_in_block, dest_remaining); |
294 DCHECK_GT(bytes_to_copy, 0UL); | 292 DCHECK_GT(bytes_to_copy, 0UL); |
295 if (FLAGS_quic_stream_sequencer_buffer_debug && | 293 if (blocks_[block_idx] == nullptr || dest == nullptr) { |
296 (blocks_[block_idx] == nullptr || dest == nullptr)) { | |
297 *error_details = StringPrintf( | 294 *error_details = StringPrintf( |
298 "QuicStreamSequencerBuffer error:" | 295 "QuicStreamSequencerBuffer error:" |
299 " Readv() dest == nullptr: %s" | 296 " Readv() dest == nullptr: %s" |
300 " blocks_[%" PRIuS "] == nullptr: %s", | 297 " blocks_[%" PRIuS "] == nullptr: %s", |
301 (dest == nullptr ? "true" : "false"), block_idx, | 298 (dest == nullptr ? "true" : "false"), block_idx, |
302 (blocks_[block_idx] == nullptr ? "true" : "false")); | 299 (blocks_[block_idx] == nullptr ? "true" : "false")); |
303 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 300 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
304 } | 301 } |
305 memcpy(dest, blocks_[block_idx]->buffer + start_offset_in_block, | 302 memcpy(dest, blocks_[block_idx]->buffer + start_offset_in_block, |
306 bytes_to_copy); | 303 bytes_to_copy); |
307 dest += bytes_to_copy; | 304 dest += bytes_to_copy; |
308 dest_remaining -= bytes_to_copy; | 305 dest_remaining -= bytes_to_copy; |
309 num_bytes_buffered_ -= bytes_to_copy; | 306 num_bytes_buffered_ -= bytes_to_copy; |
310 total_bytes_read_ += bytes_to_copy; | 307 total_bytes_read_ += bytes_to_copy; |
311 *bytes_read += bytes_to_copy; | 308 *bytes_read += bytes_to_copy; |
312 | 309 |
313 // Retire the block if all the data is read out and no other data is | 310 // Retire the block if all the data is read out and no other data is |
314 // stored in this block. | 311 // stored in this block. |
315 // In case of failing to retire a block which is ready to retire, return | 312 // In case of failing to retire a block which is ready to retire, return |
316 // immediately. | 313 // immediately. |
317 if (bytes_to_copy == bytes_available_in_block) { | 314 if (bytes_to_copy == bytes_available_in_block) { |
318 bool retire_successfully = RetireBlockIfEmpty(block_idx); | 315 bool retire_successfully = RetireBlockIfEmpty(block_idx); |
319 if (FLAGS_quic_stream_sequencer_buffer_debug && !retire_successfully) { | 316 if (!retire_successfully) { |
320 *error_details = StringPrintf( | 317 *error_details = StringPrintf( |
321 "QuicStreamSequencerBuffer error: fail to retire block %" PRIuS | 318 "QuicStreamSequencerBuffer error: fail to retire block %" PRIuS |
322 " as the block is already released + total_bytes_read_ = %" PRIu64 | 319 " as the block is already released + total_bytes_read_ = %" PRIu64 |
323 " Gaps: %s", | 320 " Gaps: %s", |
324 block_idx, total_bytes_read_, GapsDebugString().c_str()); | 321 block_idx, total_bytes_read_, GapsDebugString().c_str()); |
325 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 322 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
326 } | 323 } |
327 } | 324 } |
328 } | 325 } |
329 } | 326 } |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 } | 582 } |
586 return current_gaps_string; | 583 return current_gaps_string; |
587 } | 584 } |
588 | 585 |
589 string QuicStreamSequencerBuffer::ReceivedFramesDebugString() { | 586 string QuicStreamSequencerBuffer::ReceivedFramesDebugString() { |
590 string current_frames_string; | 587 string current_frames_string; |
591 for (auto it : frame_arrival_time_map_) { | 588 for (auto it : frame_arrival_time_map_) { |
592 QuicStreamOffset current_frame_begin_offset = it.first; | 589 QuicStreamOffset current_frame_begin_offset = it.first; |
593 QuicStreamOffset current_frame_end_offset = | 590 QuicStreamOffset current_frame_end_offset = |
594 it.second.length + current_frame_begin_offset; | 591 it.second.length + current_frame_begin_offset; |
595 if (FLAGS_quic_stream_sequencer_buffer_debug) { | 592 current_frames_string = string(StringPrintf( |
596 current_frames_string = string(StringPrintf( | 593 "%s[%" PRIu64 ", %" PRIu64 ") ", current_frames_string.c_str(), |
597 "%s[%" PRIu64 ", %" PRIu64 ") receiving time %" PRId64 " ", | 594 current_frame_begin_offset, current_frame_end_offset)); |
598 current_frames_string.c_str(), current_frame_begin_offset, | |
599 current_frame_end_offset, it.second.timestamp.ToDebuggingValue())); | |
600 } else { | |
601 current_frames_string = string(StringPrintf( | |
602 "%s[%" PRIu64 ", %" PRIu64 ") ", current_frames_string.c_str(), | |
603 current_frame_begin_offset, current_frame_end_offset)); | |
604 } | |
605 } | 595 } |
606 return current_frames_string; | 596 return current_frames_string; |
607 } | 597 } |
608 | 598 |
609 } // namespace net | 599 } // namespace net |
OLD | NEW |