1 // Copyright (c) 2009 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/base/host_cache.h" 6 7 #include "base/logging.h" 8 #include "net/base/net_errors.h" 9 10 namespace net { 11 12 //----------------------------------------------------------------------------- 13 14 HostCache::Entry::Entry(int error, 15 const AddressList& addrlist, 16 base::TimeTicks expiration) 17 : error(error), addrlist(addrlist), expiration(expiration) { 18 } 19 20 HostCache::Entry::~Entry() { 21 } 22 23 //----------------------------------------------------------------------------- 24 25 HostCache::HostCache(size_t max_entries, 26 base::TimeDelta success_entry_ttl, 27 base::TimeDelta failure_entry_ttl) 28 : max_entries_(max_entries), 29 success_entry_ttl_(success_entry_ttl), 30 failure_entry_ttl_(failure_entry_ttl) { 31 } 32 33 HostCache::~HostCache() { 34 } 35 36 const HostCache::Entry* HostCache::Lookup(const Key& key, 37 base::TimeTicks now) const { 38 DCHECK(CalledOnValidThread()); 39 if (caching_is_disabled()) 40 return NULL; 41 42 EntryMap::const_iterator it = entries_.find(key); 43 if (it == entries_.end()) 44 return NULL; // Not found. 45 46 Entry* entry = it->second.get(); 47 if (CanUseEntry(entry, now)) 48 return entry; 49 50 return NULL; 51 } 52 53 HostCache::Entry* HostCache::Set(const Key& key, 54 int error, 55 const AddressList& addrlist, 56 base::TimeTicks now) { 57 DCHECK(CalledOnValidThread()); 58 if (caching_is_disabled()) 59 return NULL; 60 61 base::TimeTicks expiration = now + 62 (error == OK ? success_entry_ttl_ : failure_entry_ttl_); 63 64 scoped_refptr<Entry>& entry = entries_[key]; 65 if (!entry) { 66 // Entry didn't exist, creating one now. 67 Entry* ptr = new Entry(error, addrlist, expiration); 68 entry = ptr; 69 70 // Compact the cache if we grew it beyond limit -- exclude |entry| from 71 // being pruned though! 72 if (entries_.size() > max_entries_) 73 Compact(now, ptr); 74 return ptr; 75 } else { 76 // Update an existing cache entry. 77 entry->error = error; 78 entry->addrlist = addrlist; 79 entry->expiration = expiration; 80 return entry.get(); 81 } 82 } 83 84 void HostCache::clear() { 85 DCHECK(CalledOnValidThread()); 86 entries_.clear(); 87 } 88 89 size_t HostCache::size() const { 90 DCHECK(CalledOnValidThread()); 91 return entries_.size(); 92 } 93 94 size_t HostCache::max_entries() const { 95 DCHECK(CalledOnValidThread()); 96 return max_entries_; 97 } 98 99 base::TimeDelta HostCache::success_entry_ttl() const { 100 DCHECK(CalledOnValidThread()); 101 return success_entry_ttl_; 102 } 103 104 base::TimeDelta HostCache::failure_entry_ttl() const { 105 DCHECK(CalledOnValidThread()); 106 return failure_entry_ttl_; 107 } 108 109 // Note that this map may contain expired entries. 110 const HostCache::EntryMap& HostCache::entries() const { 111 DCHECK(CalledOnValidThread()); 112 return entries_; 113 } 114 115 // static 116 bool HostCache::CanUseEntry(const Entry* entry, const base::TimeTicks now) { 117 return entry->expiration > now; 118 } 119 120 void HostCache::Compact(base::TimeTicks now, const Entry* pinned_entry) { 121 // Clear out expired entries. 122 for (EntryMap::iterator it = entries_.begin(); it != entries_.end(); ) { 123 Entry* entry = (it->second).get(); 124 if (entry != pinned_entry && !CanUseEntry(entry, now)) { 125 entries_.erase(it++); 126 } else { 127 ++it; 128 } 129 } 130 131 if (entries_.size() <= max_entries_) 132 return; 133 134 // If we still have too many entries, start removing unexpired entries 135 // at random. 136 // TODO(eroman): this eviction policy could be better (access count FIFO 137 // or whatever). 138 for (EntryMap::iterator it = entries_.begin(); 139 it != entries_.end() && entries_.size() > max_entries_; ) { 140 Entry* entry = (it->second).get(); 141 if (entry != pinned_entry) { 142 entries_.erase(it++); 143 } else { 144 ++it; 145 } 146 } 147 148 if (entries_.size() > max_entries_) 149 DLOG(WARNING) << "Still above max entries limit"; 150 } 151 152 } // namespace net 153