| // Copyright (c) 2011 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. |
| |
| #include "net/curvecp/sent_block_list.h" |
| |
| #include "base/logging.h" |
| #include "net/base/io_buffer.h" |
| |
| namespace net { |
| |
| static const size_t kMaxBlocks = 128; |
| |
| SentBlockList::SentBlockList() |
| : current_message_id_(1), |
| send_sequence_number_(0) { |
| } |
| |
| SentBlockList::~SentBlockList() { |
| } |
| |
| int64 SentBlockList::CreateBlock(IOBufferWithSize* buffer) { |
| DCHECK_LT(0, buffer->size()); |
| |
| if (is_full()) |
| return -1; |
| |
| Block new_block; |
| new_block.position = send_sequence_number_; |
| new_block.length = buffer->size(); |
| new_block.transmissions = 0; |
| new_block.last_message_id = 0; |
| new_block.data= buffer; |
| |
| send_sequence_number_ += buffer->size(); |
| list_.push_back(new_block); |
| return new_block.position; |
| } |
| |
| bool SentBlockList::MarkBlockSent(int64 position, int64 message_id) { |
| int index = FindBlock(position); |
| if (index < 0) { |
| NOTREACHED(); |
| return false; |
| } |
| list_[index].last_message_id = message_id; |
| list_[index].transmissions++; |
| list_[index].last_sent_time = base::TimeTicks::Now(); |
| return true; |
| } |
| |
| void SentBlockList::AcknowledgeBlocks(int64 begin_range, int64 end_range) { |
| if (begin_range == end_range) |
| return; |
| |
| // TODO(mbelshe): use a better data structure. |
| LOG(ERROR) << "ACK of: " << begin_range << " to " << end_range; |
| |
| BlockList::iterator it = list_.begin(); |
| while (it != list_.end()) { |
| int64 position = it->position; |
| int64 length = it->length; |
| if (position >= begin_range && (position + length) <= end_range) { |
| list_.erase(it); |
| it = list_.begin(); // iterator was invalidated, so go to start of list. |
| continue; |
| } |
| |
| // Verify we didn't have a partial block acknowledgement. |
| CHECK(position < begin_range || position >= end_range); |
| CHECK((position + length) < begin_range || (position + length) > end_range); |
| it++; |
| } |
| } |
| |
| int64 SentBlockList::GetNewMessageId() { |
| return current_message_id_++; |
| } |
| |
| IOBufferWithSize* SentBlockList::FindBlockByPosition(int64 position) const { |
| int index = FindBlock(position); |
| if (index < 0) |
| return NULL; |
| return list_[index].data; |
| } |
| |
| base::TimeTicks SentBlockList::FindLastSendTime(int64 last_message_id) const { |
| for (size_t index = 0; index < list_.size(); ++index) |
| if (list_[index].last_message_id == last_message_id) |
| return list_[index].last_sent_time; |
| return base::TimeTicks(); |
| } |
| |
| int SentBlockList::FindBlock(int64 position) const { |
| for (size_t index = 0; index < list_.size(); ++index) |
| if (list_[index].position == position) |
| return index; |
| return -1; |
| } |
| |
| int64 SentBlockList::FindPositionOfOldestSentBlock() const { |
| base::TimeTicks oldest_time; |
| int64 position = -1; |
| |
| LogBlockList(); |
| |
| // Walks the entire list. |
| for (size_t index = 0; index < list_.size(); ++index) { |
| base::TimeTicks last_sent_time = list_[index].last_sent_time; |
| if (!last_sent_time.is_null()) { |
| if (last_sent_time < oldest_time || oldest_time.is_null()) { |
| oldest_time = last_sent_time; |
| position = list_[index].position; |
| } |
| } |
| } |
| return position; |
| } |
| bool SentBlockList::is_full() const { |
| return list_.size() == kMaxBlocks; |
| } |
| |
| void SentBlockList::LogBlockList() const { |
| LOG(INFO) << "Sent Blocks: " << list_.size(); |
| std::string msg; |
| std::ostringstream stream(msg); |
| for (size_t index = 0; index < list_.size(); ++index) |
| stream << "(" << list_[index].position |
| << "," << list_[index].length << ")"; |
| LOG(INFO) << stream.str(); |
| } |
| |
| } // namespace net |