summaryrefslogtreecommitdiffstats
path: root/net/base/host_cache.cc
diff options
context:
space:
mode:
authorericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-12 00:49:38 +0000
committerericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-12 00:49:38 +0000
commit8a00f00ab5d68ffcc998fd04d2ca343af7cdf190 (patch)
treefd464ba49db4271c76c1cf8f769a22120ad631af /net/base/host_cache.cc
parent77ae132c1bfdd986228b6f1c0d8c63baa441afdf (diff)
downloadchromium_src-8a00f00ab5d68ffcc998fd04d2ca343af7cdf190.zip
chromium_src-8a00f00ab5d68ffcc998fd04d2ca343af7cdf190.tar.gz
chromium_src-8a00f00ab5d68ffcc998fd04d2ca343af7cdf190.tar.bz2
* Avoid doing concurrent DNS resolves of the same hostname in HostResolver.
* Add a 1 minute cache for host resolves. * Refactor HostResolver to handle multiple requests. * Make HostResolver a dependency of URLRequestContext. operate the HostResolver in async mode for proxy resolver (bridging to IO thread). TEST=unittests BUG=13163 Review URL: http://codereview.chromium.org/118100 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18236 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/host_cache.cc')
-rw-r--r--net/base/host_cache.cc115
1 files changed, 115 insertions, 0 deletions
diff --git a/net/base/host_cache.cc b/net/base/host_cache.cc
new file mode 100644
index 0000000..53af5b4
--- /dev/null
+++ b/net/base/host_cache.cc
@@ -0,0 +1,115 @@
+// Copyright (c) 2009 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/base/host_cache.h"
+
+#include "base/logging.h"
+#include "net/base/net_errors.h"
+
+namespace net {
+
+//-----------------------------------------------------------------------------
+
+HostCache::Entry::Entry(int error,
+ const AddressList& addrlist,
+ base::TimeTicks expiration)
+ : error(error), addrlist(addrlist), expiration(expiration) {
+}
+
+HostCache::Entry::~Entry() {
+}
+
+//-----------------------------------------------------------------------------
+
+HostCache::HostCache(size_t max_entries, size_t cache_duration_ms)
+ : max_entries_(max_entries), cache_duration_ms_(cache_duration_ms) {
+}
+
+HostCache::~HostCache() {
+}
+
+const HostCache::Entry* HostCache::Lookup(const std::string& hostname,
+ base::TimeTicks now) const {
+ if (caching_is_disabled())
+ return NULL;
+
+ EntryMap::const_iterator it = entries_.find(hostname);
+ if (it == entries_.end())
+ return NULL; // Not found.
+
+ Entry* entry = it->second.get();
+ if (CanUseEntry(entry, now))
+ return entry;
+
+ return NULL;
+}
+
+HostCache::Entry* HostCache::Set(const std::string& hostname,
+ int error,
+ const AddressList addrlist,
+ base::TimeTicks now) {
+ if (caching_is_disabled())
+ return NULL;
+
+ base::TimeTicks expiration = now +
+ base::TimeDelta::FromMilliseconds(cache_duration_ms_);
+
+ scoped_refptr<Entry>& entry = entries_[hostname];
+ if (!entry) {
+ // Entry didn't exist, creating one now.
+ Entry* ptr = new Entry(error, addrlist, expiration);
+ entry = ptr;
+
+ // Compact the cache if we grew it beyond limit -- exclude |entry| from
+ // being pruned though!
+ if (entries_.size() > max_entries_)
+ Compact(now, ptr);
+ return ptr;
+ } else {
+ // Update an existing cache entry.
+ entry->error = error;
+ entry->addrlist = addrlist;
+ entry->expiration = expiration;
+ return entry.get();
+ }
+}
+
+// static
+bool HostCache::CanUseEntry(const Entry* entry, const base::TimeTicks now) {
+ return entry->error == OK && entry->expiration > now;
+}
+
+void HostCache::Compact(base::TimeTicks now, const Entry* pinned_entry) {
+ // Clear out expired entries.
+ for (EntryMap::iterator it = entries_.begin(); it != entries_.end(); ) {
+ Entry* entry = (it->second).get();
+ if (entry != pinned_entry && !CanUseEntry(entry, now)) {
+ entries_.erase(it++);
+ } else {
+ ++it;
+ }
+ }
+
+ if (entries_.size() <= max_entries_)
+ return;
+
+ // If we still have too many entries, start removing unexpired entries
+ // at random.
+ // TODO(eroman): this eviction policy could be better (access count FIFO
+ // or whatever).
+ for (EntryMap::iterator it = entries_.begin();
+ it != entries_.end() && entries_.size() > max_entries_; ) {
+ Entry* entry = (it->second).get();
+ if (entry != pinned_entry) {
+ entries_.erase(it++);
+ } else {
+ ++it;
+ }
+ }
+
+ if (entries_.size() > max_entries_)
+ DLOG(WARNING) << "Still above max entries limit";
+}
+
+} // namespace net