// Copyright (c) 2011 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,
                     base::TimeDelta success_entry_ttl,
                     base::TimeDelta failure_entry_ttl)
    : max_entries_(max_entries),
      success_entry_ttl_(success_entry_ttl),
      failure_entry_ttl_(failure_entry_ttl) {
}

HostCache::~HostCache() {
}

const HostCache::Entry* HostCache::Lookup(const Key& key,
                                          base::TimeTicks now) const {
  DCHECK(CalledOnValidThread());
  if (caching_is_disabled())
    return NULL;

  EntryMap::const_iterator it = entries_.find(key);
  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 Key& key,
                                 int error,
                                 const AddressList& addrlist,
                                 base::TimeTicks now) {
  DCHECK(CalledOnValidThread());
  if (caching_is_disabled())
    return NULL;

  base::TimeTicks expiration = now +
      (error == OK ? success_entry_ttl_ : failure_entry_ttl_);

  scoped_refptr<Entry>& entry = entries_[key];
  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();
  }
}

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 max_entries_;
}

base::TimeDelta HostCache::success_entry_ttl() const {
  DCHECK(CalledOnValidThread());
  return success_entry_ttl_;
}

base::TimeDelta HostCache::failure_entry_ttl() const {
  DCHECK(CalledOnValidThread());
  return failure_entry_ttl_;
}

// Note that this map may contain expired entries.
const HostCache::EntryMap& HostCache::entries() const {
  DCHECK(CalledOnValidThread());
  return entries_;
}

// static
bool HostCache::CanUseEntry(const Entry* entry, const base::TimeTicks now) {
  return entry->expiration > now;
}

// static
HostCache* HostCache::CreateDefaultCache() {
  static const size_t kMaxHostCacheEntries = 100;

  HostCache* cache = new HostCache(
      kMaxHostCacheEntries,
      base::TimeDelta::FromMinutes(1),
      base::TimeDelta::FromSeconds(0));  // Disable caching of failed DNS.

  return cache;
}

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
