1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/dns/host_cache.h"
6
7#include "base/logging.h"
8#include "base/metrics/field_trial.h"
9#include "base/metrics/histogram.h"
10#include "base/strings/string_number_conversions.h"
11#include "net/base/net_errors.h"
12
13namespace net {
14
15//-----------------------------------------------------------------------------
16
17HostCache::Entry::Entry(int error, const AddressList& addrlist,
18                        base::TimeDelta ttl)
19    : error(error),
20      addrlist(addrlist),
21      ttl(ttl) {
22  DCHECK(ttl >= base::TimeDelta());
23}
24
25HostCache::Entry::Entry(int error, const AddressList& addrlist)
26    : error(error),
27      addrlist(addrlist),
28      ttl(base::TimeDelta::FromSeconds(-1)) {
29}
30
31HostCache::Entry::~Entry() {
32}
33
34//-----------------------------------------------------------------------------
35
36HostCache::HostCache(size_t max_entries)
37    : entries_(max_entries) {
38}
39
40HostCache::~HostCache() {
41}
42
43const HostCache::Entry* HostCache::Lookup(const Key& key,
44                                          base::TimeTicks now) {
45  DCHECK(CalledOnValidThread());
46  if (caching_is_disabled())
47    return NULL;
48
49  return entries_.Get(key, now);
50}
51
52void HostCache::Set(const Key& key,
53                    const Entry& entry,
54                    base::TimeTicks now,
55                    base::TimeDelta ttl) {
56  DCHECK(CalledOnValidThread());
57  if (caching_is_disabled())
58    return;
59
60  entries_.Put(key, entry, now, now + ttl);
61}
62
63void HostCache::clear() {
64  DCHECK(CalledOnValidThread());
65  entries_.Clear();
66}
67
68size_t HostCache::size() const {
69  DCHECK(CalledOnValidThread());
70  return entries_.size();
71}
72
73size_t HostCache::max_entries() const {
74  DCHECK(CalledOnValidThread());
75  return entries_.max_entries();
76}
77
78// Note that this map may contain expired entries.
79const HostCache::EntryMap& HostCache::entries() const {
80  DCHECK(CalledOnValidThread());
81  return entries_;
82}
83
84// static
85scoped_ptr<HostCache> HostCache::CreateDefaultCache() {
86  // Cache capacity is determined by the field trial.
87#if defined(ENABLE_BUILT_IN_DNS)
88  const size_t kDefaultMaxEntries = 1000;
89#else
90  const size_t kDefaultMaxEntries = 100;
91#endif
92  const size_t kSaneMaxEntries = 1 << 20;
93  size_t max_entries = 0;
94  base::StringToSizeT(base::FieldTrialList::FindFullName("HostCacheSize"),
95                      &max_entries);
96  if ((max_entries == 0) || (max_entries > kSaneMaxEntries))
97    max_entries = kDefaultMaxEntries;
98  return make_scoped_ptr(new HostCache(max_entries));
99}
100
101void HostCache::EvictionHandler::Handle(
102    const Key& key,
103    const Entry& entry,
104    const base::TimeTicks& expiration,
105    const base::TimeTicks& now,
106    bool on_get) const {
107  if (on_get) {
108    DCHECK(now >= expiration);
109    UMA_HISTOGRAM_CUSTOM_TIMES("DNS.CacheExpiredOnGet", now - expiration,
110        base::TimeDelta::FromSeconds(1), base::TimeDelta::FromDays(1), 100);
111    return;
112  }
113  if (expiration > now) {
114    UMA_HISTOGRAM_CUSTOM_TIMES("DNS.CacheEvicted", expiration - now,
115        base::TimeDelta::FromSeconds(1), base::TimeDelta::FromDays(1), 100);
116  } else {
117    UMA_HISTOGRAM_CUSTOM_TIMES("DNS.CacheExpired", now - expiration,
118        base::TimeDelta::FromSeconds(1), base::TimeDelta::FromDays(1), 100);
119  }
120}
121
122}  // namespace net
123