|  | // 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/host_cache.h" | 
|  |  | 
|  | #include "base/logging.h" | 
|  | #include "base/metrics/field_trial.h" | 
|  | #include "base/metrics/histogram.h" | 
|  | #include "base/strings/string_number_conversions.h" | 
|  | #include "net/base/net_errors.h" | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | //----------------------------------------------------------------------------- | 
|  |  | 
|  | HostCache::Entry::Entry(int error, const AddressList& addrlist, | 
|  | base::TimeDelta ttl) | 
|  | : error(error), | 
|  | addrlist(addrlist), | 
|  | ttl(ttl) { | 
|  | DCHECK(ttl >= base::TimeDelta()); | 
|  | } | 
|  |  | 
|  | HostCache::Entry::Entry(int error, const AddressList& addrlist) | 
|  | : error(error), | 
|  | addrlist(addrlist), | 
|  | ttl(base::TimeDelta::FromSeconds(-1)) { | 
|  | } | 
|  |  | 
|  | HostCache::Entry::~Entry() { | 
|  | } | 
|  |  | 
|  | //----------------------------------------------------------------------------- | 
|  |  | 
|  | HostCache::HostCache(size_t max_entries) | 
|  | : entries_(max_entries) { | 
|  | } | 
|  |  | 
|  | HostCache::~HostCache() { | 
|  | } | 
|  |  | 
|  | const HostCache::Entry* HostCache::Lookup(const Key& key, | 
|  | base::TimeTicks now) { | 
|  | DCHECK(CalledOnValidThread()); | 
|  | if (caching_is_disabled()) | 
|  | return NULL; | 
|  |  | 
|  | return entries_.Get(key, now); | 
|  | } | 
|  |  | 
|  | void HostCache::Set(const Key& key, | 
|  | const Entry& entry, | 
|  | base::TimeTicks now, | 
|  | base::TimeDelta ttl) { | 
|  | DCHECK(CalledOnValidThread()); | 
|  | if (caching_is_disabled()) | 
|  | return; | 
|  |  | 
|  | entries_.Put(key, entry, now, now + ttl); | 
|  | } | 
|  |  | 
|  | void HostCache::clear() { | 
|  | DCHECK(CalledOnValidThread()); | 
|  | entries_.Clear(); | 
|  | } | 
|  |  | 
|  | size_t HostCache::size() const { | 
|  | DCHECK(CalledOnValidThread()); | 
|  | return entries_.size(); | 
|  | } | 
|  |  | 
|  | size_t HostCache::max_entries() const { | 
|  | DCHECK(CalledOnValidThread()); | 
|  | return entries_.max_entries(); | 
|  | } | 
|  |  | 
|  | // Note that this map may contain expired entries. | 
|  | const HostCache::EntryMap& HostCache::entries() const { | 
|  | DCHECK(CalledOnValidThread()); | 
|  | return entries_; | 
|  | } | 
|  |  | 
|  | // static | 
|  | scoped_ptr<HostCache> HostCache::CreateDefaultCache() { | 
|  | // Cache capacity is determined by the field trial. | 
|  | #if defined(ENABLE_BUILT_IN_DNS) | 
|  | const size_t kDefaultMaxEntries = 1000; | 
|  | #else | 
|  | const size_t kDefaultMaxEntries = 100; | 
|  | #endif | 
|  | const size_t kSaneMaxEntries = 1 << 20; | 
|  | size_t max_entries = 0; | 
|  | base::StringToSizeT(base::FieldTrialList::FindFullName("HostCacheSize"), | 
|  | &max_entries); | 
|  | if ((max_entries == 0) || (max_entries > kSaneMaxEntries)) | 
|  | max_entries = kDefaultMaxEntries; | 
|  | return make_scoped_ptr(new HostCache(max_entries)); | 
|  | } | 
|  |  | 
|  | void HostCache::EvictionHandler::Handle( | 
|  | const Key& key, | 
|  | const Entry& entry, | 
|  | const base::TimeTicks& expiration, | 
|  | const base::TimeTicks& now, | 
|  | bool on_get) const { | 
|  | if (on_get) { | 
|  | DCHECK(now >= expiration); | 
|  | UMA_HISTOGRAM_CUSTOM_TIMES("DNS.CacheExpiredOnGet", now - expiration, | 
|  | base::TimeDelta::FromSeconds(1), base::TimeDelta::FromDays(1), 100); | 
|  | return; | 
|  | } | 
|  | if (expiration > now) { | 
|  | UMA_HISTOGRAM_CUSTOM_TIMES("DNS.CacheEvicted", expiration - now, | 
|  | base::TimeDelta::FromSeconds(1), base::TimeDelta::FromDays(1), 100); | 
|  | } else { | 
|  | UMA_HISTOGRAM_CUSTOM_TIMES("DNS.CacheExpired", now - expiration, | 
|  | base::TimeDelta::FromSeconds(1), base::TimeDelta::FromDays(1), 100); | 
|  | } | 
|  | } | 
|  |  | 
|  | }  // namespace net |