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

#include "net/disk_cache/mem_backend_impl.h"

#include "base/logging.h"
#include "base/sys_info.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/cache_util.h"
#include "net/disk_cache/mem_entry_impl.h"

using base::Time;

namespace {

const int kDefaultCacheSize = 10 * 1024 * 1024;
const int kCleanUpMargin = 1024 * 1024;

int LowWaterAdjust(int high_water) {
  if (high_water < kCleanUpMargin)
    return 0;

  return high_water - kCleanUpMargin;
}

}  // namespace

namespace disk_cache {

MemBackendImpl::MemBackendImpl(net::NetLog* net_log)
    : max_size_(0), current_size_(0), net_log_(net_log) {}

MemBackendImpl::~MemBackendImpl() {
  EntryMap::iterator it = entries_.begin();
  while (it != entries_.end()) {
    it->second->Doom();
    it = entries_.begin();
  }
  DCHECK(!current_size_);
}

// Static.
Backend* MemBackendImpl::CreateBackend(int max_bytes, net::NetLog* net_log) {
  MemBackendImpl* cache = new MemBackendImpl(net_log);
  cache->SetMaxSize(max_bytes);
  if (cache->Init())
    return cache;

  delete cache;
  LOG(ERROR) << "Unable to create cache";
  return NULL;
}

bool MemBackendImpl::Init() {
  if (max_size_)
    return true;

  int64 total_memory = base::SysInfo::AmountOfPhysicalMemory();

  if (total_memory <= 0) {
    max_size_ = kDefaultCacheSize;
    return true;
  }

  // We want to use up to 2% of the computer's memory, with a limit of 50 MB,
  // reached on systemd with more than 2.5 GB of RAM.
  total_memory = total_memory * 2 / 100;
  if (total_memory > kDefaultCacheSize * 5)
    max_size_ = kDefaultCacheSize * 5;
  else
    max_size_ = static_cast<int32>(total_memory);

  return true;
}

bool MemBackendImpl::SetMaxSize(int max_bytes) {
  COMPILE_ASSERT(sizeof(max_bytes) == sizeof(max_size_), unsupported_int_model);
  if (max_bytes < 0)
    return false;

  // Zero size means use the default.
  if (!max_bytes)
    return true;

  max_size_ = max_bytes;
  return true;
}

void MemBackendImpl::InternalDoomEntry(MemEntryImpl* entry) {
  // Only parent entries can be passed into this method.
  DCHECK(entry->type() == MemEntryImpl::kParentEntry);

  rankings_.Remove(entry);
  EntryMap::iterator it = entries_.find(entry->GetKey());
  if (it != entries_.end())
    entries_.erase(it);
  else
    NOTREACHED();

  entry->InternalDoom();
}

void MemBackendImpl::UpdateRank(MemEntryImpl* node) {
  rankings_.UpdateRank(node);
}

void MemBackendImpl::ModifyStorageSize(int32 old_size, int32 new_size) {
  if (old_size >= new_size)
    SubstractStorageSize(old_size - new_size);
  else
    AddStorageSize(new_size - old_size);
}

int MemBackendImpl::MaxFileSize() const {
  return max_size_ / 8;
}

void MemBackendImpl::InsertIntoRankingList(MemEntryImpl* entry) {
  rankings_.Insert(entry);
}

void MemBackendImpl::RemoveFromRankingList(MemEntryImpl* entry) {
  rankings_.Remove(entry);
}

net::CacheType MemBackendImpl::GetCacheType() const {
  return net::MEMORY_CACHE;
}

int32 MemBackendImpl::GetEntryCount() const {
  return static_cast<int32>(entries_.size());
}

int MemBackendImpl::OpenEntry(const std::string& key, Entry** entry,
                              const CompletionCallback& callback) {
  if (OpenEntry(key, entry))
    return net::OK;

  return net::ERR_FAILED;
}

int MemBackendImpl::CreateEntry(const std::string& key, Entry** entry,
                                const CompletionCallback& callback) {
  if (CreateEntry(key, entry))
    return net::OK;

  return net::ERR_FAILED;
}

int MemBackendImpl::DoomEntry(const std::string& key,
                              const CompletionCallback& callback) {
  if (DoomEntry(key))
    return net::OK;

  return net::ERR_FAILED;
}

int MemBackendImpl::DoomAllEntries(const CompletionCallback& callback) {
  if (DoomAllEntries())
    return net::OK;

  return net::ERR_FAILED;
}

int MemBackendImpl::DoomEntriesBetween(const base::Time initial_time,
                                       const base::Time end_time,
                                       const CompletionCallback& callback) {
  if (DoomEntriesBetween(initial_time, end_time))
    return net::OK;

  return net::ERR_FAILED;
}

int MemBackendImpl::DoomEntriesSince(const base::Time initial_time,
                                     const CompletionCallback& callback) {
  if (DoomEntriesSince(initial_time))
    return net::OK;

  return net::ERR_FAILED;
}

int MemBackendImpl::OpenNextEntry(void** iter, Entry** next_entry,
                                  const CompletionCallback& callback) {
  if (OpenNextEntry(iter, next_entry))
    return net::OK;

  return net::ERR_FAILED;
}

void MemBackendImpl::EndEnumeration(void** iter) {
  *iter = NULL;
}

void MemBackendImpl::OnExternalCacheHit(const std::string& key) {
  EntryMap::iterator it = entries_.find(key);
  if (it != entries_.end()) {
    UpdateRank(it->second);
  }
}

bool MemBackendImpl::OpenEntry(const std::string& key, Entry** entry) {
  EntryMap::iterator it = entries_.find(key);
  if (it == entries_.end())
    return false;

  it->second->Open();

  *entry = it->second;
  return true;
}

bool MemBackendImpl::CreateEntry(const std::string& key, Entry** entry) {
  EntryMap::iterator it = entries_.find(key);
  if (it != entries_.end())
    return false;

  MemEntryImpl* cache_entry = new MemEntryImpl(this);
  if (!cache_entry->CreateEntry(key, net_log_)) {
    delete entry;
    return false;
  }

  rankings_.Insert(cache_entry);
  entries_[key] = cache_entry;

  *entry = cache_entry;
  return true;
}

bool MemBackendImpl::DoomEntry(const std::string& key) {
  Entry* entry;
  if (!OpenEntry(key, &entry))
    return false;

  entry->Doom();
  entry->Close();
  return true;
}

bool MemBackendImpl::DoomAllEntries() {
  TrimCache(true);
  return true;
}

bool MemBackendImpl::DoomEntriesBetween(const Time initial_time,
                                        const Time end_time) {
  if (end_time.is_null())
    return DoomEntriesSince(initial_time);

  DCHECK(end_time >= initial_time);

  MemEntryImpl* next = rankings_.GetNext(NULL);

  // rankings_ is ordered by last used, this will descend through the cache
  // and start dooming items before the end_time, and will stop once it reaches
  // an item used before the initial time.
  while (next) {
    MemEntryImpl* node = next;
    next = rankings_.GetNext(next);

    if (node->GetLastUsed() < initial_time)
      break;

    if (node->GetLastUsed() < end_time)
      node->Doom();
  }

  return true;
}

bool MemBackendImpl::DoomEntriesSince(const Time initial_time) {
  for (;;) {
    // Get the entry in the front.
    Entry* entry = rankings_.GetNext(NULL);

    // Break the loop when there are no more entries or the entry is too old.
    if (!entry || entry->GetLastUsed() < initial_time)
      return true;
    entry->Doom();
  }
}

bool MemBackendImpl::OpenNextEntry(void** iter, Entry** next_entry) {
  MemEntryImpl* current = reinterpret_cast<MemEntryImpl*>(*iter);
  MemEntryImpl* node = rankings_.GetNext(current);
  // We should never return a child entry so iterate until we hit a parent
  // entry.
  while (node && node->type() != MemEntryImpl::kParentEntry) {
    node = rankings_.GetNext(node);
  }
  *next_entry = node;
  *iter = node;

  if (node)
    node->Open();

  return NULL != node;
}

void MemBackendImpl::TrimCache(bool empty) {
  MemEntryImpl* next = rankings_.GetPrev(NULL);
  if (!next)
    return;

  int target_size = empty ? 0 : LowWaterAdjust(max_size_);
  while (current_size_ > target_size && next) {
    MemEntryImpl* node = next;
    next = rankings_.GetPrev(next);
    if (!node->InUse() || empty) {
      node->Doom();
    }
  }

  return;
}

void MemBackendImpl::AddStorageSize(int32 bytes) {
  current_size_ += bytes;
  DCHECK_GE(current_size_, 0);

  if (current_size_ > max_size_)
    TrimCache(false);
}

void MemBackendImpl::SubstractStorageSize(int32 bytes) {
  current_size_ -= bytes;
  DCHECK_GE(current_size_, 0);
}

}  // namespace disk_cache
