diff options
Diffstat (limited to 'net/curvecp/sent_block_list.cc')
-rw-r--r-- | net/curvecp/sent_block_list.cc | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/net/curvecp/sent_block_list.cc b/net/curvecp/sent_block_list.cc new file mode 100644 index 0000000..2eb55dc --- /dev/null +++ b/net/curvecp/sent_block_list.cc @@ -0,0 +1,133 @@ +// 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 |