diff options
author | jar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-27 06:22:01 +0000 |
---|---|---|
committer | jar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-27 06:22:01 +0000 |
commit | 3530cd9023fed0204e7df17b11f121d89ca6303a (patch) | |
tree | b229d5401cecff76cad5738384246b930719c3e4 /chrome/renderer/net/predictor_queue.cc | |
parent | c6c3877915cab1a18268dd21e4c6c3cf7b3863b1 (diff) | |
download | chromium_src-3530cd9023fed0204e7df17b11f121d89ca6303a.zip chromium_src-3530cd9023fed0204e7df17b11f121d89ca6303a.tar.gz chromium_src-3530cd9023fed0204e7df17b11f121d89ca6303a.tar.bz2 |
Rename Dns prefetching files to Predictor files
We are now doing more than DNS pre-resolution, and want
to do TCP/IP pre-warming. This change uses the updated
class names etc., and tries to use Predictor as the
common element in most names.
r=mbelshe
Review URL: http://codereview.chromium.org/2866026
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50951 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/net/predictor_queue.cc')
-rw-r--r-- | chrome/renderer/net/predictor_queue.cc | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/chrome/renderer/net/predictor_queue.cc b/chrome/renderer/net/predictor_queue.cc new file mode 100644 index 0000000..40996e5 --- /dev/null +++ b/chrome/renderer/net/predictor_queue.cc @@ -0,0 +1,146 @@ +// Copyright (c) 2006-2008 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. + +// See header file for description of DnsQueue class + +#include "chrome/renderer/net/predictor_queue.h" + +#include "base/logging.h" +#include "base/stats_counters.h" + +DnsQueue::DnsQueue(BufferSize size) + : buffer_(new char[size + 2]), + buffer_size_(size + 1), + buffer_sentinel_(size + 1), + size_(0) { + CHECK(0 < static_cast<BufferSize>(size + 3)); // Avoid overflow worries. + buffer_[buffer_sentinel_] = '\0'; // Guard byte to help reading data. + readable_ = writeable_ = 0; // Buffer starts empty. +} + +DnsQueue::~DnsQueue(void) { +} + +// Push takes an unterminated string plus its length. +// The string must not contain a null terminator. +// Exactly length chars are written, or nothing is written. +// Returns true for success, false there was no room to push. +DnsQueue::PushResult DnsQueue::Push(const char* source, + const size_t unsigned_length) { + BufferSize length = static_cast<BufferSize>(unsigned_length); + if (0 > length+1) // Avoid overflows in conversion to signed. + return OVERFLOW_PUSH; + + // To save on sites with a LOT of links to the SAME domain, we have a + // a compaction hack that removes duplicates when we try to push() a + // match with the last push. + if (0 < size_ && readable_ + length < buffer_sentinel_ && + 0 == strncmp(source, &buffer_[readable_], unsigned_length) && + '\0' == buffer_[readable_ + unsigned_length]) { + SIMPLE_STATS_COUNTER("DNS.PrefetchDnsRedundantPush"); + + // We already wrote this name to the queue, so we'll skip this repeat. + return REDUNDANT_PUSH; + } + + // Calling convention precludes nulls. + DCHECK(!length || '\0' != source[length - 1]); + + DCHECK(Validate()); + + BufferSize available_space = readable_ - writeable_; + + if (0 >= available_space) { + available_space += buffer_size_; + } + + if (length + 1 >= available_space) { + SIMPLE_STATS_COUNTER("DNS.PrefetchDnsQueueFull"); + return OVERFLOW_PUSH; // Not enough space to push. + } + + BufferSize dest = writeable_; + BufferSize space_till_wrap = buffer_sentinel_ - dest; + if (space_till_wrap < length + 1) { + // Copy until we run out of room at end of buffer. + std::memcpy(&buffer_[dest], source, space_till_wrap); + // Ensure caller didn't have embedded '\0' and also + // ensure trailing sentinel was in place. + // Relies on sentinel. + DCHECK(static_cast<size_t>(space_till_wrap) == strlen(&buffer_[dest])); + + length -= space_till_wrap; + source += space_till_wrap; + dest = 0; // Continue writing at start of buffer. + } + + // Copy any remaining portion of source. + std::memcpy(&buffer_[dest], source, length); + DCHECK(dest + length < buffer_sentinel_); + buffer_[dest + length] = '\0'; // We need termination in our buffer. + // Preclude embedded '\0'. + DCHECK(static_cast<size_t>(length) == strlen(&buffer_[dest])); + + dest += length + 1; + if (dest == buffer_sentinel_) + dest = 0; + + writeable_ = dest; + size_++; + DCHECK(Validate()); + return SUCCESSFUL_PUSH; +} + +// Extracts the next available string from the buffer. +// The returned string is null terminated, and hence has length +// that is exactly one greater than the written string. +// If the buffer is empty, then the Pop and returns false. +bool DnsQueue::Pop(std::string* out_string) { + DCHECK(Validate()); + // Sentinel will preclude memory reads beyond buffer's end. + DCHECK('\0' == buffer_[buffer_sentinel_]); + + if (readable_ == writeable_) { + return false; // buffer was empty + } + + // Constructor *may* rely on sentinel for null termination. + (*out_string) = &buffer_[readable_]; + // Our sentinel_ at end of buffer precludes an overflow in cast. + BufferSize first_fragment_size = static_cast<BufferSize> (out_string->size()); + + BufferSize terminal_null; + if (readable_ + first_fragment_size >= buffer_sentinel_) { + // Sentinel was used, so we need the portion after the wrap. + out_string->append(&buffer_[0]); // Fragment at start of buffer. + // Sentinel precludes overflow in cast to signed type. + terminal_null = static_cast<BufferSize>(out_string->size()) + - first_fragment_size; + } else { + terminal_null = readable_ + first_fragment_size; + } + DCHECK('\0' == buffer_[terminal_null]); + + BufferSize new_readable = terminal_null + 1; + if (buffer_sentinel_ == new_readable) + new_readable = 0; + + readable_ = new_readable; + size_--; + if (readable_ == writeable_ || 0 == size_) { + // Queue is empty, so reset to start of buffer to help with peeking. + readable_ = writeable_ = 0; + } + DCHECK(Validate()); + return true; +} + +bool DnsQueue::Validate() { + return (readable_ >= 0) && + readable_ < buffer_sentinel_ && + writeable_ >= 0 && + writeable_ < buffer_sentinel_ && + '\0' == buffer_[buffer_sentinel_] && + ((0 == size_) == (readable_ == writeable_)); +} |