Index: net/dns/dns_session.cc |
diff --git a/net/dns/dns_session.cc b/net/dns/dns_session.cc |
deleted file mode 100644 |
index 47dcefa1c579c3aa0f1e73bbd7a7b13d1d938ffb..0000000000000000000000000000000000000000 |
--- a/net/dns/dns_session.cc |
+++ /dev/null |
@@ -1,302 +0,0 @@ |
-// Copyright (c) 2012 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/dns/dns_session.h" |
- |
-#include "base/basictypes.h" |
-#include "base/bind.h" |
-#include "base/lazy_instance.h" |
-#include "base/metrics/histogram.h" |
-#include "base/metrics/sample_vector.h" |
-#include "base/rand_util.h" |
-#include "base/stl_util.h" |
-#include "base/time/time.h" |
-#include "net/base/ip_endpoint.h" |
-#include "net/base/net_errors.h" |
-#include "net/dns/dns_config_service.h" |
-#include "net/dns/dns_socket_pool.h" |
-#include "net/socket/stream_socket.h" |
-#include "net/udp/datagram_client_socket.h" |
- |
-namespace net { |
- |
-namespace { |
-// Never exceed max timeout. |
-const unsigned kMaxTimeoutMs = 5000; |
-// Set min timeout, in case we are talking to a local DNS proxy. |
-const unsigned kMinTimeoutMs = 10; |
- |
-// Number of buckets in the histogram of observed RTTs. |
-const size_t kRTTBucketCount = 100; |
-// Target percentile in the RTT histogram used for retransmission timeout. |
-const unsigned kRTOPercentile = 99; |
-} // namespace |
- |
-// Runtime statistics of DNS server. |
-struct DnsSession::ServerStats { |
- ServerStats(base::TimeDelta rtt_estimate_param, RttBuckets* buckets) |
- : last_failure_count(0), rtt_estimate(rtt_estimate_param) { |
- rtt_histogram.reset(new base::SampleVector(buckets)); |
- // Seed histogram with 2 samples at |rtt_estimate| timeout. |
- rtt_histogram->Accumulate( |
- static_cast<base::HistogramBase::Sample>(rtt_estimate.InMilliseconds()), |
- 2); |
- } |
- |
- // Count of consecutive failures after last success. |
- int last_failure_count; |
- |
- // Last time when server returned failure or timeout. |
- base::Time last_failure; |
- // Last time when server returned success. |
- base::Time last_success; |
- |
- // Estimated RTT using moving average. |
- base::TimeDelta rtt_estimate; |
- // Estimated error in the above. |
- base::TimeDelta rtt_deviation; |
- |
- // A histogram of observed RTT . |
- scoped_ptr<base::SampleVector> rtt_histogram; |
- |
- DISALLOW_COPY_AND_ASSIGN(ServerStats); |
-}; |
- |
-// static |
-base::LazyInstance<DnsSession::RttBuckets>::Leaky DnsSession::rtt_buckets_ = |
- LAZY_INSTANCE_INITIALIZER; |
- |
-DnsSession::RttBuckets::RttBuckets() : base::BucketRanges(kRTTBucketCount + 1) { |
- base::Histogram::InitializeBucketRanges(1, 5000, this); |
-} |
- |
-DnsSession::SocketLease::SocketLease(scoped_refptr<DnsSession> session, |
- unsigned server_index, |
- scoped_ptr<DatagramClientSocket> socket) |
- : session_(session), server_index_(server_index), socket_(socket.Pass()) {} |
- |
-DnsSession::SocketLease::~SocketLease() { |
- session_->FreeSocket(server_index_, socket_.Pass()); |
-} |
- |
-DnsSession::DnsSession(const DnsConfig& config, |
- scoped_ptr<DnsSocketPool> socket_pool, |
- const RandIntCallback& rand_int_callback, |
- NetLog* net_log) |
- : config_(config), |
- socket_pool_(socket_pool.Pass()), |
- rand_callback_(base::Bind(rand_int_callback, 0, kuint16max)), |
- net_log_(net_log), |
- server_index_(0) { |
- socket_pool_->Initialize(&config_.nameservers, net_log); |
- UMA_HISTOGRAM_CUSTOM_COUNTS( |
- "AsyncDNS.ServerCount", config_.nameservers.size(), 0, 10, 11); |
- for (size_t i = 0; i < config_.nameservers.size(); ++i) { |
- server_stats_.push_back(new ServerStats(config_.timeout, |
- rtt_buckets_.Pointer())); |
- } |
-} |
- |
-DnsSession::~DnsSession() { |
- RecordServerStats(); |
-} |
- |
-uint16 DnsSession::NextQueryId() const { |
- return static_cast<uint16>(rand_callback_.Run()); |
-} |
- |
-unsigned DnsSession::NextFirstServerIndex() { |
- unsigned index = NextGoodServerIndex(server_index_); |
- if (config_.rotate) |
- server_index_ = (server_index_ + 1) % config_.nameservers.size(); |
- return index; |
-} |
- |
-unsigned DnsSession::NextGoodServerIndex(unsigned server_index) { |
- unsigned index = server_index; |
- base::Time oldest_server_failure(base::Time::Now()); |
- unsigned oldest_server_failure_index = 0; |
- |
- UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ServerIsGood", |
- server_stats_[server_index]->last_failure.is_null()); |
- |
- do { |
- base::Time cur_server_failure = server_stats_[index]->last_failure; |
- // If number of failures on this server doesn't exceed number of allowed |
- // attempts, return its index. |
- if (server_stats_[server_index]->last_failure_count < config_.attempts) { |
- return index; |
- } |
- // Track oldest failed server. |
- if (cur_server_failure < oldest_server_failure) { |
- oldest_server_failure = cur_server_failure; |
- oldest_server_failure_index = index; |
- } |
- index = (index + 1) % config_.nameservers.size(); |
- } while (index != server_index); |
- |
- // If we are here it means that there are no successful servers, so we have |
- // to use one that has failed oldest. |
- return oldest_server_failure_index; |
-} |
- |
-void DnsSession::RecordServerFailure(unsigned server_index) { |
- UMA_HISTOGRAM_CUSTOM_COUNTS( |
- "AsyncDNS.ServerFailureIndex", server_index, 0, 10, 11); |
- ++(server_stats_[server_index]->last_failure_count); |
- server_stats_[server_index]->last_failure = base::Time::Now(); |
-} |
- |
-void DnsSession::RecordServerSuccess(unsigned server_index) { |
- if (server_stats_[server_index]->last_success.is_null()) { |
- UMA_HISTOGRAM_COUNTS_100("AsyncDNS.ServerFailuresAfterNetworkChange", |
- server_stats_[server_index]->last_failure_count); |
- } else { |
- UMA_HISTOGRAM_COUNTS_100("AsyncDNS.ServerFailuresBeforeSuccess", |
- server_stats_[server_index]->last_failure_count); |
- } |
- server_stats_[server_index]->last_failure_count = 0; |
- server_stats_[server_index]->last_failure = base::Time(); |
- server_stats_[server_index]->last_success = base::Time::Now(); |
-} |
- |
-void DnsSession::RecordRTT(unsigned server_index, base::TimeDelta rtt) { |
- DCHECK_LT(server_index, server_stats_.size()); |
- |
- // For measurement, assume it is the first attempt (no backoff). |
- base::TimeDelta timeout_jacobson = NextTimeoutFromJacobson(server_index, 0); |
- base::TimeDelta timeout_histogram = NextTimeoutFromHistogram(server_index, 0); |
- UMA_HISTOGRAM_TIMES("AsyncDNS.TimeoutErrorJacobson", rtt - timeout_jacobson); |
- UMA_HISTOGRAM_TIMES("AsyncDNS.TimeoutErrorHistogram", |
- rtt - timeout_histogram); |
- UMA_HISTOGRAM_TIMES("AsyncDNS.TimeoutErrorJacobsonUnder", |
- timeout_jacobson - rtt); |
- UMA_HISTOGRAM_TIMES("AsyncDNS.TimeoutErrorHistogramUnder", |
- timeout_histogram - rtt); |
- |
- // Jacobson/Karels algorithm for TCP. |
- // Using parameters: alpha = 1/8, delta = 1/4, beta = 4 |
- base::TimeDelta& estimate = server_stats_[server_index]->rtt_estimate; |
- base::TimeDelta& deviation = server_stats_[server_index]->rtt_deviation; |
- base::TimeDelta current_error = rtt - estimate; |
- estimate += current_error / 8; // * alpha |
- base::TimeDelta abs_error = base::TimeDelta::FromInternalValue( |
- std::abs(current_error.ToInternalValue())); |
- deviation += (abs_error - deviation) / 4; // * delta |
- |
- // Histogram-based method. |
- server_stats_[server_index]->rtt_histogram->Accumulate( |
- static_cast<base::HistogramBase::Sample>(rtt.InMilliseconds()), 1); |
-} |
- |
-void DnsSession::RecordLostPacket(unsigned server_index, int attempt) { |
- base::TimeDelta timeout_jacobson = |
- NextTimeoutFromJacobson(server_index, attempt); |
- base::TimeDelta timeout_histogram = |
- NextTimeoutFromHistogram(server_index, attempt); |
- UMA_HISTOGRAM_TIMES("AsyncDNS.TimeoutSpentJacobson", timeout_jacobson); |
- UMA_HISTOGRAM_TIMES("AsyncDNS.TimeoutSpentHistogram", timeout_histogram); |
-} |
- |
-void DnsSession::RecordServerStats() { |
- for (size_t index = 0; index < server_stats_.size(); ++index) { |
- if (server_stats_[index]->last_failure_count) { |
- if (server_stats_[index]->last_success.is_null()) { |
- UMA_HISTOGRAM_COUNTS("AsyncDNS.ServerFailuresWithoutSuccess", |
- server_stats_[index]->last_failure_count); |
- } else { |
- UMA_HISTOGRAM_COUNTS("AsyncDNS.ServerFailuresAfterSuccess", |
- server_stats_[index]->last_failure_count); |
- } |
- } |
- } |
-} |
- |
- |
-base::TimeDelta DnsSession::NextTimeout(unsigned server_index, int attempt) { |
- // Respect config timeout if it exceeds |kMaxTimeoutMs|. |
- if (config_.timeout.InMilliseconds() >= kMaxTimeoutMs) |
- return config_.timeout; |
- return NextTimeoutFromHistogram(server_index, attempt); |
-} |
- |
-// Allocate a socket, already connected to the server address. |
-scoped_ptr<DnsSession::SocketLease> DnsSession::AllocateSocket( |
- unsigned server_index, const NetLog::Source& source) { |
- scoped_ptr<DatagramClientSocket> socket; |
- |
- socket = socket_pool_->AllocateSocket(server_index); |
- if (!socket.get()) |
- return scoped_ptr<SocketLease>(); |
- |
- socket->NetLog().BeginEvent(NetLog::TYPE_SOCKET_IN_USE, |
- source.ToEventParametersCallback()); |
- |
- SocketLease* lease = new SocketLease(this, server_index, socket.Pass()); |
- return scoped_ptr<SocketLease>(lease); |
-} |
- |
-scoped_ptr<StreamSocket> DnsSession::CreateTCPSocket( |
- unsigned server_index, const NetLog::Source& source) { |
- return socket_pool_->CreateTCPSocket(server_index, source); |
-} |
- |
-// Release a socket. |
-void DnsSession::FreeSocket(unsigned server_index, |
- scoped_ptr<DatagramClientSocket> socket) { |
- DCHECK(socket.get()); |
- |
- socket->NetLog().EndEvent(NetLog::TYPE_SOCKET_IN_USE); |
- |
- socket_pool_->FreeSocket(server_index, socket.Pass()); |
-} |
- |
-base::TimeDelta DnsSession::NextTimeoutFromJacobson(unsigned server_index, |
- int attempt) { |
- DCHECK_LT(server_index, server_stats_.size()); |
- |
- base::TimeDelta timeout = server_stats_[server_index]->rtt_estimate + |
- 4 * server_stats_[server_index]->rtt_deviation; |
- |
- timeout = std::max(timeout, base::TimeDelta::FromMilliseconds(kMinTimeoutMs)); |
- |
- // The timeout doubles every full round. |
- unsigned num_backoffs = attempt / config_.nameservers.size(); |
- |
- return std::min(timeout * (1 << num_backoffs), |
- base::TimeDelta::FromMilliseconds(kMaxTimeoutMs)); |
-} |
- |
-base::TimeDelta DnsSession::NextTimeoutFromHistogram(unsigned server_index, |
- int attempt) { |
- DCHECK_LT(server_index, server_stats_.size()); |
- |
- static_assert(std::numeric_limits<base::HistogramBase::Count>::is_signed, |
- "histogram base count assumed to be signed"); |
- |
- // Use fixed percentile of observed samples. |
- const base::SampleVector& samples = |
- *server_stats_[server_index]->rtt_histogram; |
- |
- base::HistogramBase::Count total = samples.TotalCount(); |
- base::HistogramBase::Count remaining_count = kRTOPercentile * total / 100; |
- size_t index = 0; |
- while (remaining_count > 0 && index < rtt_buckets_.Get().size()) { |
- remaining_count -= samples.GetCountAtIndex(index); |
- ++index; |
- } |
- |
- base::TimeDelta timeout = |
- base::TimeDelta::FromMilliseconds(rtt_buckets_.Get().range(index)); |
- |
- timeout = std::max(timeout, base::TimeDelta::FromMilliseconds(kMinTimeoutMs)); |
- |
- // The timeout still doubles every full round. |
- unsigned num_backoffs = attempt / config_.nameservers.size(); |
- |
- return std::min(timeout * (1 << num_backoffs), |
- base::TimeDelta::FromMilliseconds(kMaxTimeoutMs)); |
-} |
- |
-} // namespace net |