// 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.

#ifndef NET_BASE_EXPIRING_CACHE_H_
#define NET_BASE_EXPIRING_CACHE_H_

#include <map>
#include <utility>

#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/time.h"

namespace net {

template <typename KeyType,
          typename ValueType,
          typename ExpirationType>
class NoopEvictionHandler {
 public:
  void Handle(const KeyType& /* key */,
              const ValueType& /* value */,
              const ExpirationType& /* expiration */,
              const ExpirationType& /* now */,
              bool /* onGet */) const {}
};

// Cache implementation where all entries have an explicit expiration policy. As
// new items are added, expired items will be removed first.
// The template types have the following requirements:
//  KeyType must be LessThanComparable, Assignable, and CopyConstructible.
//  ValueType must be CopyConstructible and Assignable.
//  ExpirationType must be CopyConstructible and Assignable.
//  ExpirationCompare is a function class that takes two arguments of the
//    type ExpirationType and returns a bool. If |comp| is an instance of
//    ExpirationCompare, then the expression |comp(current, expiration)| shall
//    return true iff |current| is still valid within |expiration|.
//
// A simple use of this class may use base::TimeTicks, which provides a
// monotonically increasing clock, for the expiration type. Because it's always
// increasing, std::less<> can be used, which will simply ensure that |now| is
// sorted before |expiration|:
//
//   ExpiringCache<std::string, std::string, base::TimeTicks,
//                 std::less<base::TimeTicks> > cache(0);
//   // Add a value that expires in 5 minutes
//   cache.Put("key1", "value1", base::TimeTicks::Now(),
//             base::TimeTicks::Now() + base::TimeDelta::FromMinutes(5));
//   // Add another value that expires in 10 minutes.
//   cache.Put("key2", "value2", base::TimeTicks::Now(),
//             base::TimeTicks::Now() + base::TimeDelta::FromMinutes(10));
//
// Alternatively, there may be some more complex expiration criteria, at which
// point a custom functor may be used:
//
//   struct ComplexExpirationFunctor {
//     bool operator()(const ComplexExpiration& now,
//                     const ComplexExpiration& expiration) const;
//   };
//   ExpiringCache<std::string, std::string, ComplexExpiration,
//                 ComplexExpirationFunctor> cache(15);
//   // Add a value that expires once the 'sprocket' has 'cog'-ified.
//   cache.Put("key1", "value1", ComplexExpiration("sprocket"),
//             ComplexExpiration("cog"));
template <typename KeyType,
          typename ValueType,
          typename ExpirationType,
          typename ExpirationCompare,
          typename EvictionHandler = NoopEvictionHandler<KeyType,
                                                         ValueType,
                                                         ExpirationType> >
class ExpiringCache {
 private:
  // Intentionally violate the C++ Style Guide so that EntryMap is known to be
  // a dependent type. Without this, Clang's two-phase lookup complains when
  // using EntryMap::const_iterator, while GCC and MSVC happily resolve the
  // typename.

  // Tuple to represent the value and when it expires.
  typedef std::pair<ValueType, ExpirationType> Entry;
  typedef std::map<KeyType, Entry> EntryMap;

 public:
  typedef KeyType key_type;
  typedef ValueType value_type;
  typedef ExpirationType expiration_type;

  // This class provides a read-only iterator over items in the ExpiringCache
  class Iterator {
   public:
    explicit Iterator(const ExpiringCache& cache)
        : cache_(cache),
          it_(cache_.entries_.begin()) {
    }
    ~Iterator() {}

    bool HasNext() const { return it_ != cache_.entries_.end(); }
    void Advance() { ++it_; }

    const KeyType& key() const { return it_->first; }
    const ValueType& value() const { return it_->second.first; }
    const ExpirationType& expiration() const { return it_->second.second; }

   private:
    const ExpiringCache& cache_;

    // Use a second layer of type indirection, as both EntryMap and
    // EntryMap::const_iterator are dependent types.
    typedef typename ExpiringCache::EntryMap EntryMap;
    typename EntryMap::const_iterator it_;
  };


  // Constructs an ExpiringCache that stores up to |max_entries|.
  explicit ExpiringCache(size_t max_entries) : max_entries_(max_entries) {}
  ~ExpiringCache() {}

  // Returns the value matching |key|, which must be valid at the time |now|.
  // Returns NULL if the item is not found or has expired. If the item has
  // expired, it is immediately removed from the cache.
  // Note: The returned pointer remains owned by the ExpiringCache and is
  // invalidated by a call to a non-const method.
  const ValueType* Get(const KeyType& key, const ExpirationType& now) {
    typename EntryMap::iterator it = entries_.find(key);
    if (it == entries_.end())
      return NULL;

    // Immediately remove expired entries.
    if (!expiration_comp_(now, it->second.second)) {
      Evict(it, now, true);
      return NULL;
    }

    return &it->second.first;
  }

  // Updates or replaces the value associated with |key|.
  void Put(const KeyType& key,
           const ValueType& value,
           const ExpirationType& now,
           const ExpirationType& expiration) {
    typename EntryMap::iterator it = entries_.find(key);
    if (it == entries_.end()) {
      // Compact the cache if it grew beyond the limit.
      if (entries_.size() == max_entries_ )
        Compact(now);

      // No existing entry. Creating a new one.
      entries_.insert(std::make_pair(key, Entry(value, expiration)));
    } else {
      // Update an existing cache entry.
      it->second.first = value;
      it->second.second = expiration;
    }
  }

  // Empties the cache.
  void Clear() {
    entries_.clear();
  }

  // Returns the number of entries in the cache.
  size_t size() const { return entries_.size(); }

  // Returns the maximum number of entries in the cache.
  size_t max_entries() const { return max_entries_; }

  bool empty() const { return entries_.empty(); }

 private:
  FRIEND_TEST_ALL_PREFIXES(ExpiringCacheTest, Compact);
  FRIEND_TEST_ALL_PREFIXES(ExpiringCacheTest, CustomFunctor);

  // Prunes entries from the cache to bring it below |max_entries()|.
  void Compact(const ExpirationType& now) {
    // Clear out expired entries.
    typename EntryMap::iterator it;
    for (it = entries_.begin(); it != entries_.end(); ) {
      if (!expiration_comp_(now, it->second.second)) {
        Evict(it++, now, false);
      } else {
        ++it;
      }
    }

    if (entries_.size() < max_entries_)
      return;

    // If the cache is still too full, start deleting items 'randomly'.
    for (it = entries_.begin();
         it != entries_.end() && entries_.size() >= max_entries_;) {
      Evict(it++, now, false);
    }
  }

  void Evict(typename EntryMap::iterator it,
             const ExpirationType& now,
             bool on_get) {
    eviction_handler_.Handle(it->first, it->second.first, it->second.second,
                             now, on_get);
    entries_.erase(it);
  }

  // Bound on total size of the cache.
  size_t max_entries_;

  EntryMap entries_;
  ExpirationCompare expiration_comp_;
  EvictionHandler eviction_handler_;

  DISALLOW_COPY_AND_ASSIGN(ExpiringCache);
};

}  // namespace net

#endif  // NET_BASE_EXPIRING_CACHE_H_
