// Copyright (c) 2013 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/simple/simple_backend_impl.h"

#include <algorithm>
#include <cstdlib>
#include <functional>

#if defined(OS_POSIX)
#include <sys/resource.h>
#endif

#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/single_thread_task_runner.h"
#include "base/sys_info.h"
#include "base/task_runner_util.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/cache_util.h"
#include "net/disk_cache/simple/simple_entry_format.h"
#include "net/disk_cache/simple/simple_entry_impl.h"
#include "net/disk_cache/simple/simple_histogram_macros.h"
#include "net/disk_cache/simple/simple_index.h"
#include "net/disk_cache/simple/simple_index_file.h"
#include "net/disk_cache/simple/simple_synchronous_entry.h"
#include "net/disk_cache/simple/simple_util.h"
#include "net/disk_cache/simple/simple_version_upgrade.h"

using base::Callback;
using base::Closure;
using base::FilePath;
using base::SequencedWorkerPool;
using base::Time;
using base::DirectoryExists;
using base::CreateDirectory;

namespace disk_cache {

namespace {

// Maximum number of concurrent worker pool threads, which also is the limit
// on concurrent IO (as we use one thread per IO request).
const int kDefaultMaxWorkerThreads = 50;

const char kThreadNamePrefix[] = "SimpleCache";

// Maximum fraction of the cache that one entry can consume.
const int kMaxFileRatio = 8;

// A global sequenced worker pool to use for launching all tasks.
SequencedWorkerPool* g_sequenced_worker_pool = NULL;

void MaybeCreateSequencedWorkerPool() {
  if (!g_sequenced_worker_pool) {
    int max_worker_threads = kDefaultMaxWorkerThreads;

    const std::string thread_count_field_trial =
        base::FieldTrialList::FindFullName("SimpleCacheMaxThreads");
    if (!thread_count_field_trial.empty()) {
      max_worker_threads =
          std::max(1, std::atoi(thread_count_field_trial.c_str()));
    }

    g_sequenced_worker_pool = new SequencedWorkerPool(max_worker_threads,
                                                      kThreadNamePrefix);
    g_sequenced_worker_pool->AddRef();  // Leak it.
  }
}

bool g_fd_limit_histogram_has_been_populated = false;

void MaybeHistogramFdLimit(net::CacheType cache_type) {
  if (g_fd_limit_histogram_has_been_populated)
    return;

  // Used in histograms; add new entries at end.
  enum FdLimitStatus {
    FD_LIMIT_STATUS_UNSUPPORTED = 0,
    FD_LIMIT_STATUS_FAILED      = 1,
    FD_LIMIT_STATUS_SUCCEEDED   = 2,
    FD_LIMIT_STATUS_MAX         = 3
  };
  FdLimitStatus fd_limit_status = FD_LIMIT_STATUS_UNSUPPORTED;
  int soft_fd_limit = 0;
  int hard_fd_limit = 0;

#if defined(OS_POSIX)
  struct rlimit nofile;
  if (!getrlimit(RLIMIT_NOFILE, &nofile)) {
    soft_fd_limit = nofile.rlim_cur;
    hard_fd_limit = nofile.rlim_max;
    fd_limit_status = FD_LIMIT_STATUS_SUCCEEDED;
  } else {
    fd_limit_status = FD_LIMIT_STATUS_FAILED;
  }
#endif

  SIMPLE_CACHE_UMA(ENUMERATION,
                   "FileDescriptorLimitStatus", cache_type,
                   fd_limit_status, FD_LIMIT_STATUS_MAX);
  if (fd_limit_status == FD_LIMIT_STATUS_SUCCEEDED) {
    SIMPLE_CACHE_UMA(SPARSE_SLOWLY,
                     "FileDescriptorLimitSoft", cache_type, soft_fd_limit);
    SIMPLE_CACHE_UMA(SPARSE_SLOWLY,
                     "FileDescriptorLimitHard", cache_type, hard_fd_limit);
  }

  g_fd_limit_histogram_has_been_populated = true;
}

// Detects if the files in the cache directory match the current disk cache
// backend type and version. If the directory contains no cache, occupies it
// with the fresh structure.
bool FileStructureConsistent(const base::FilePath& path) {
  if (!base::PathExists(path) && !base::CreateDirectory(path)) {
    LOG(ERROR) << "Failed to create directory: " << path.LossyDisplayName();
    return false;
  }
  return disk_cache::UpgradeSimpleCacheOnDisk(path);
}

// A context used by a BarrierCompletionCallback to track state.
struct BarrierContext {
  BarrierContext(int expected)
      : expected(expected),
        count(0),
        had_error(false) {}

  const int expected;
  int count;
  bool had_error;
};

void BarrierCompletionCallbackImpl(
    BarrierContext* context,
    const net::CompletionCallback& final_callback,
    int result) {
  DCHECK_GT(context->expected, context->count);
  if (context->had_error)
    return;
  if (result != net::OK) {
    context->had_error = true;
    final_callback.Run(result);
    return;
  }
  ++context->count;
  if (context->count == context->expected)
    final_callback.Run(net::OK);
}

// A barrier completion callback is a net::CompletionCallback that waits for
// |count| successful results before invoking |final_callback|. In the case of
// an error, the first error is passed to |final_callback| and all others
// are ignored.
net::CompletionCallback MakeBarrierCompletionCallback(
    int count,
    const net::CompletionCallback& final_callback) {
  BarrierContext* context = new BarrierContext(count);
  return base::Bind(&BarrierCompletionCallbackImpl,
                    base::Owned(context), final_callback);
}

// A short bindable thunk that ensures a completion callback is always called
// after running an operation asynchronously.
void RunOperationAndCallback(
    const Callback<int(const net::CompletionCallback&)>& operation,
    const net::CompletionCallback& operation_callback) {
  const int operation_result = operation.Run(operation_callback);
  if (operation_result != net::ERR_IO_PENDING)
    operation_callback.Run(operation_result);
}

void RecordIndexLoad(net::CacheType cache_type,
                     base::TimeTicks constructed_since,
                     int result) {
  const base::TimeDelta creation_to_index = base::TimeTicks::Now() -
                                            constructed_since;
  if (result == net::OK) {
    SIMPLE_CACHE_UMA(TIMES, "CreationToIndex", cache_type, creation_to_index);
  } else {
    SIMPLE_CACHE_UMA(TIMES,
                     "CreationToIndexFail", cache_type, creation_to_index);
  }
}

}  // namespace

class SimpleBackendImpl::ActiveEntryProxy
    : public SimpleEntryImpl::ActiveEntryProxy {
 public:
  ~ActiveEntryProxy() override {
    if (backend_) {
      DCHECK_EQ(1U, backend_->active_entries_.count(entry_hash_));
      backend_->active_entries_.erase(entry_hash_);
    }
  }

  static scoped_ptr<SimpleEntryImpl::ActiveEntryProxy> Create(
      int64 entry_hash,
      SimpleBackendImpl* backend) {
    scoped_ptr<SimpleEntryImpl::ActiveEntryProxy>
        proxy(new ActiveEntryProxy(entry_hash, backend));
    return proxy.Pass();
  }

 private:
  ActiveEntryProxy(uint64 entry_hash,
                   SimpleBackendImpl* backend)
      : entry_hash_(entry_hash),
        backend_(backend->AsWeakPtr()) {}

  uint64 entry_hash_;
  base::WeakPtr<SimpleBackendImpl> backend_;
};

SimpleBackendImpl::SimpleBackendImpl(
    const FilePath& path,
    int max_bytes,
    net::CacheType cache_type,
    const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread,
    net::NetLog* net_log)
    : path_(path),
      cache_type_(cache_type),
      cache_thread_(cache_thread),
      orig_max_size_(max_bytes),
      entry_operations_mode_(cache_type == net::DISK_CACHE ?
                                 SimpleEntryImpl::OPTIMISTIC_OPERATIONS :
                                 SimpleEntryImpl::NON_OPTIMISTIC_OPERATIONS),
      net_log_(net_log) {
  MaybeHistogramFdLimit(cache_type_);
}

SimpleBackendImpl::~SimpleBackendImpl() {
  index_->WriteToDisk();
}

int SimpleBackendImpl::Init(const CompletionCallback& completion_callback) {
  MaybeCreateSequencedWorkerPool();

  worker_pool_ = g_sequenced_worker_pool->GetTaskRunnerWithShutdownBehavior(
      SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);

  index_.reset(new SimpleIndex(
      base::ThreadTaskRunnerHandle::Get(),
      this,
      cache_type_,
      make_scoped_ptr(new SimpleIndexFile(
          cache_thread_, worker_pool_.get(), cache_type_, path_))));
  index_->ExecuteWhenReady(
      base::Bind(&RecordIndexLoad, cache_type_, base::TimeTicks::Now()));

  PostTaskAndReplyWithResult(
      cache_thread_.get(),
      FROM_HERE,
      base::Bind(
          &SimpleBackendImpl::InitCacheStructureOnDisk, path_, orig_max_size_),
      base::Bind(&SimpleBackendImpl::InitializeIndex,
                 AsWeakPtr(),
                 completion_callback));
  return net::ERR_IO_PENDING;
}

bool SimpleBackendImpl::SetMaxSize(int max_bytes) {
  orig_max_size_ = max_bytes;
  return index_->SetMaxSize(max_bytes);
}

int SimpleBackendImpl::GetMaxFileSize() const {
  return index_->max_size() / kMaxFileRatio;
}

void SimpleBackendImpl::OnDoomStart(uint64 entry_hash) {
  DCHECK_EQ(0u, entries_pending_doom_.count(entry_hash));
  entries_pending_doom_.insert(
      std::make_pair(entry_hash, std::vector<Closure>()));
}

void SimpleBackendImpl::OnDoomComplete(uint64 entry_hash) {
  DCHECK_EQ(1u, entries_pending_doom_.count(entry_hash));
  base::hash_map<uint64, std::vector<Closure> >::iterator it =
      entries_pending_doom_.find(entry_hash);
  std::vector<Closure> to_run_closures;
  to_run_closures.swap(it->second);
  entries_pending_doom_.erase(it);

  std::for_each(to_run_closures.begin(), to_run_closures.end(),
                std::mem_fun_ref(&Closure::Run));
}

void SimpleBackendImpl::DoomEntries(std::vector<uint64>* entry_hashes,
                                    const net::CompletionCallback& callback) {
  scoped_ptr<std::vector<uint64> >
      mass_doom_entry_hashes(new std::vector<uint64>());
  mass_doom_entry_hashes->swap(*entry_hashes);

  std::vector<uint64> to_doom_individually_hashes;

  // For each of the entry hashes, there are two cases:
  // 1. The entry is either open or pending doom, and so it should be doomed
  //    individually to avoid flakes.
  // 2. The entry is not in use at all, so we can call
  //    SimpleSynchronousEntry::DoomEntrySet and delete the files en masse.
  for (int i = mass_doom_entry_hashes->size() - 1; i >= 0; --i) {
    const uint64 entry_hash = (*mass_doom_entry_hashes)[i];
    DCHECK(active_entries_.count(entry_hash) == 0 ||
           entries_pending_doom_.count(entry_hash) == 0);
    if (!active_entries_.count(entry_hash) &&
        !entries_pending_doom_.count(entry_hash)) {
      continue;
    }

    to_doom_individually_hashes.push_back(entry_hash);

    (*mass_doom_entry_hashes)[i] = mass_doom_entry_hashes->back();
    mass_doom_entry_hashes->resize(mass_doom_entry_hashes->size() - 1);
  }

  net::CompletionCallback barrier_callback =
      MakeBarrierCompletionCallback(to_doom_individually_hashes.size() + 1,
                                    callback);
  for (std::vector<uint64>::const_iterator
           it = to_doom_individually_hashes.begin(),
           end = to_doom_individually_hashes.end(); it != end; ++it) {
    const int doom_result = DoomEntryFromHash(*it, barrier_callback);
    DCHECK_EQ(net::ERR_IO_PENDING, doom_result);
    index_->Remove(*it);
  }

  for (std::vector<uint64>::const_iterator it = mass_doom_entry_hashes->begin(),
                                           end = mass_doom_entry_hashes->end();
       it != end; ++it) {
    index_->Remove(*it);
    OnDoomStart(*it);
  }

  // Taking this pointer here avoids undefined behaviour from calling
  // base::Passed before mass_doom_entry_hashes.get().
  std::vector<uint64>* mass_doom_entry_hashes_ptr =
      mass_doom_entry_hashes.get();
  PostTaskAndReplyWithResult(worker_pool_.get(),
                             FROM_HERE,
                             base::Bind(&SimpleSynchronousEntry::DoomEntrySet,
                                        mass_doom_entry_hashes_ptr,
                                        path_),
                             base::Bind(&SimpleBackendImpl::DoomEntriesComplete,
                                        AsWeakPtr(),
                                        base::Passed(&mass_doom_entry_hashes),
                                        barrier_callback));
}

net::CacheType SimpleBackendImpl::GetCacheType() const {
  return net::DISK_CACHE;
}

int32 SimpleBackendImpl::GetEntryCount() const {
  // TODO(pasko): Use directory file count when index is not ready.
  return index_->GetEntryCount();
}

int SimpleBackendImpl::OpenEntry(const std::string& key,
                                 Entry** entry,
                                 const CompletionCallback& callback) {
  const uint64 entry_hash = simple_util::GetEntryHashKey(key);

  // TODO(gavinp): Factor out this (not quite completely) repetitive code
  // block from OpenEntry/CreateEntry/DoomEntry.
  base::hash_map<uint64, std::vector<Closure> >::iterator it =
      entries_pending_doom_.find(entry_hash);
  if (it != entries_pending_doom_.end()) {
    Callback<int(const net::CompletionCallback&)> operation =
        base::Bind(&SimpleBackendImpl::OpenEntry,
                   base::Unretained(this), key, entry);
    it->second.push_back(base::Bind(&RunOperationAndCallback,
                                    operation, callback));
    return net::ERR_IO_PENDING;
  }
  scoped_refptr<SimpleEntryImpl> simple_entry =
      CreateOrFindActiveEntry(entry_hash, key);
  CompletionCallback backend_callback =
      base::Bind(&SimpleBackendImpl::OnEntryOpenedFromKey,
                 AsWeakPtr(),
                 key,
                 entry,
                 simple_entry,
                 callback);
  return simple_entry->OpenEntry(entry, backend_callback);
}

int SimpleBackendImpl::CreateEntry(const std::string& key,
                                   Entry** entry,
                                   const CompletionCallback& callback) {
  DCHECK_LT(0u, key.size());
  const uint64 entry_hash = simple_util::GetEntryHashKey(key);

  base::hash_map<uint64, std::vector<Closure> >::iterator it =
      entries_pending_doom_.find(entry_hash);
  if (it != entries_pending_doom_.end()) {
    Callback<int(const net::CompletionCallback&)> operation =
        base::Bind(&SimpleBackendImpl::CreateEntry,
                   base::Unretained(this), key, entry);
    it->second.push_back(base::Bind(&RunOperationAndCallback,
                                    operation, callback));
    return net::ERR_IO_PENDING;
  }
  scoped_refptr<SimpleEntryImpl> simple_entry =
      CreateOrFindActiveEntry(entry_hash, key);
  return simple_entry->CreateEntry(entry, callback);
}

int SimpleBackendImpl::DoomEntry(const std::string& key,
                                 const net::CompletionCallback& callback) {
  const uint64 entry_hash = simple_util::GetEntryHashKey(key);

  base::hash_map<uint64, std::vector<Closure> >::iterator it =
      entries_pending_doom_.find(entry_hash);
  if (it != entries_pending_doom_.end()) {
    Callback<int(const net::CompletionCallback&)> operation =
        base::Bind(&SimpleBackendImpl::DoomEntry, base::Unretained(this), key);
    it->second.push_back(base::Bind(&RunOperationAndCallback,
                                    operation, callback));
    return net::ERR_IO_PENDING;
  }
  scoped_refptr<SimpleEntryImpl> simple_entry =
      CreateOrFindActiveEntry(entry_hash, key);
  return simple_entry->DoomEntry(callback);
}

int SimpleBackendImpl::DoomAllEntries(const CompletionCallback& callback) {
  return DoomEntriesBetween(Time(), Time(), callback);
}

void SimpleBackendImpl::IndexReadyForDoom(Time initial_time,
                                          Time end_time,
                                          const CompletionCallback& callback,
                                          int result) {
  if (result != net::OK) {
    callback.Run(result);
    return;
  }
  scoped_ptr<std::vector<uint64> > removed_key_hashes(
      index_->GetEntriesBetween(initial_time, end_time).release());
  DoomEntries(removed_key_hashes.get(), callback);
}

int SimpleBackendImpl::DoomEntriesBetween(
    const Time initial_time,
    const Time end_time,
    const CompletionCallback& callback) {
  return index_->ExecuteWhenReady(
      base::Bind(&SimpleBackendImpl::IndexReadyForDoom, AsWeakPtr(),
                 initial_time, end_time, callback));
}

int SimpleBackendImpl::DoomEntriesSince(
    const Time initial_time,
    const CompletionCallback& callback) {
  return DoomEntriesBetween(initial_time, Time(), callback);
}

class SimpleBackendImpl::SimpleIterator final : public Iterator {
 public:
  explicit SimpleIterator(base::WeakPtr<SimpleBackendImpl> backend)
      : backend_(backend),
        weak_factory_(this) {
  }

  // From Backend::Iterator:
  int OpenNextEntry(Entry** next_entry,
                    const CompletionCallback& callback) override {
    CompletionCallback open_next_entry_impl =
        base::Bind(&SimpleIterator::OpenNextEntryImpl,
                   weak_factory_.GetWeakPtr(), next_entry, callback);
    return backend_->index_->ExecuteWhenReady(open_next_entry_impl);
  }

  void OpenNextEntryImpl(Entry** next_entry,
                         const CompletionCallback& callback,
                         int index_initialization_error_code) {
    if (!backend_) {
      callback.Run(net::ERR_FAILED);
      return;
    }
    if (index_initialization_error_code != net::OK) {
      callback.Run(index_initialization_error_code);
      return;
    }
    if (!hashes_to_enumerate_)
      hashes_to_enumerate_ = backend_->index()->GetAllHashes().Pass();

    while (!hashes_to_enumerate_->empty()) {
      uint64 entry_hash = hashes_to_enumerate_->back();
      hashes_to_enumerate_->pop_back();
      if (backend_->index()->Has(entry_hash)) {
        *next_entry = NULL;
        CompletionCallback continue_iteration = base::Bind(
            &SimpleIterator::CheckIterationReturnValue,
            weak_factory_.GetWeakPtr(),
            next_entry,
            callback);
        int error_code_open = backend_->OpenEntryFromHash(entry_hash,
                                                          next_entry,
                                                          continue_iteration);
        if (error_code_open == net::ERR_IO_PENDING)
          return;
        if (error_code_open != net::ERR_FAILED) {
          callback.Run(error_code_open);
          return;
        }
      }
    }
    callback.Run(net::ERR_FAILED);
  }

  void CheckIterationReturnValue(Entry** entry,
                                 const CompletionCallback& callback,
                                 int error_code) {
    if (error_code == net::ERR_FAILED) {
      OpenNextEntry(entry, callback);
      return;
    }
    callback.Run(error_code);
  }

 private:
  base::WeakPtr<SimpleBackendImpl> backend_;
  scoped_ptr<std::vector<uint64> > hashes_to_enumerate_;
  base::WeakPtrFactory<SimpleIterator> weak_factory_;
};

scoped_ptr<Backend::Iterator> SimpleBackendImpl::CreateIterator() {
  return scoped_ptr<Iterator>(new SimpleIterator(AsWeakPtr()));
}

void SimpleBackendImpl::GetStats(
    std::vector<std::pair<std::string, std::string> >* stats) {
  std::pair<std::string, std::string> item;
  item.first = "Cache type";
  item.second = "Simple Cache";
  stats->push_back(item);
}

void SimpleBackendImpl::OnExternalCacheHit(const std::string& key) {
  index_->UseIfExists(simple_util::GetEntryHashKey(key));
}

void SimpleBackendImpl::InitializeIndex(const CompletionCallback& callback,
                                        const DiskStatResult& result) {
  if (result.net_error == net::OK) {
    index_->SetMaxSize(result.max_size);
    index_->Initialize(result.cache_dir_mtime);
  }
  callback.Run(result.net_error);
}

SimpleBackendImpl::DiskStatResult SimpleBackendImpl::InitCacheStructureOnDisk(
    const base::FilePath& path,
    uint64 suggested_max_size) {
  DiskStatResult result;
  result.max_size = suggested_max_size;
  result.net_error = net::OK;
  if (!FileStructureConsistent(path)) {
    LOG(ERROR) << "Simple Cache Backend: wrong file structure on disk: "
               << path.LossyDisplayName();
    result.net_error = net::ERR_FAILED;
  } else {
    bool mtime_result =
        disk_cache::simple_util::GetMTime(path, &result.cache_dir_mtime);
    DCHECK(mtime_result);
    if (!result.max_size) {
      int64 available = base::SysInfo::AmountOfFreeDiskSpace(path);
      result.max_size = disk_cache::PreferredCacheSize(available);
    }
    DCHECK(result.max_size);
  }
  return result;
}

scoped_refptr<SimpleEntryImpl> SimpleBackendImpl::CreateOrFindActiveEntry(
    const uint64 entry_hash,
    const std::string& key) {
  DCHECK_EQ(entry_hash, simple_util::GetEntryHashKey(key));
  std::pair<EntryMap::iterator, bool> insert_result =
      active_entries_.insert(EntryMap::value_type(entry_hash, NULL));
  EntryMap::iterator& it = insert_result.first;
  const bool did_insert = insert_result.second;
  if (did_insert) {
    SimpleEntryImpl* entry = it->second =
        new SimpleEntryImpl(cache_type_, path_, entry_hash,
                            entry_operations_mode_,this, net_log_);
    entry->SetKey(key);
    entry->SetActiveEntryProxy(ActiveEntryProxy::Create(entry_hash, this));
  }
  DCHECK(it->second);
  // It's possible, but unlikely, that we have an entry hash collision with a
  // currently active entry.
  if (key != it->second->key()) {
    it->second->Doom();
    DCHECK_EQ(0U, active_entries_.count(entry_hash));
    return CreateOrFindActiveEntry(entry_hash, key);
  }
  return make_scoped_refptr(it->second);
}

int SimpleBackendImpl::OpenEntryFromHash(uint64 entry_hash,
                                         Entry** entry,
                                         const CompletionCallback& callback) {
  base::hash_map<uint64, std::vector<Closure> >::iterator it =
      entries_pending_doom_.find(entry_hash);
  if (it != entries_pending_doom_.end()) {
    Callback<int(const net::CompletionCallback&)> operation =
        base::Bind(&SimpleBackendImpl::OpenEntryFromHash,
                   base::Unretained(this), entry_hash, entry);
    it->second.push_back(base::Bind(&RunOperationAndCallback,
                                    operation, callback));
    return net::ERR_IO_PENDING;
  }

  EntryMap::iterator has_active = active_entries_.find(entry_hash);
  if (has_active != active_entries_.end()) {
    return OpenEntry(has_active->second->key(), entry, callback);
  }

  scoped_refptr<SimpleEntryImpl> simple_entry = new SimpleEntryImpl(
      cache_type_, path_, entry_hash, entry_operations_mode_, this, net_log_);
  CompletionCallback backend_callback =
      base::Bind(&SimpleBackendImpl::OnEntryOpenedFromHash,
                 AsWeakPtr(), entry_hash, entry, simple_entry, callback);
  return simple_entry->OpenEntry(entry, backend_callback);
}

int SimpleBackendImpl::DoomEntryFromHash(uint64 entry_hash,
                                         const CompletionCallback& callback) {
  Entry** entry = new Entry*();
  scoped_ptr<Entry*> scoped_entry(entry);

  base::hash_map<uint64, std::vector<Closure> >::iterator pending_it =
      entries_pending_doom_.find(entry_hash);
  if (pending_it != entries_pending_doom_.end()) {
    Callback<int(const net::CompletionCallback&)> operation =
        base::Bind(&SimpleBackendImpl::DoomEntryFromHash,
                   base::Unretained(this), entry_hash);
    pending_it->second.push_back(base::Bind(&RunOperationAndCallback,
                                    operation, callback));
    return net::ERR_IO_PENDING;
  }

  EntryMap::iterator active_it = active_entries_.find(entry_hash);
  if (active_it != active_entries_.end())
    return active_it->second->DoomEntry(callback);

  // There's no pending dooms, nor any open entry. We can make a trivial
  // call to DoomEntries() to delete this entry.
  std::vector<uint64> entry_hash_vector;
  entry_hash_vector.push_back(entry_hash);
  DoomEntries(&entry_hash_vector, callback);
  return net::ERR_IO_PENDING;
}

void SimpleBackendImpl::OnEntryOpenedFromHash(
    uint64 hash,
    Entry** entry,
    const scoped_refptr<SimpleEntryImpl>& simple_entry,
    const CompletionCallback& callback,
    int error_code) {
  if (error_code != net::OK) {
    callback.Run(error_code);
    return;
  }
  DCHECK(*entry);
  std::pair<EntryMap::iterator, bool> insert_result =
      active_entries_.insert(EntryMap::value_type(hash, simple_entry.get()));
  EntryMap::iterator& it = insert_result.first;
  const bool did_insert = insert_result.second;
  if (did_insert) {
    // There was no active entry corresponding to this hash. We've already put
    // the entry opened from hash in the |active_entries_|. We now provide the
    // proxy object to the entry.
    it->second->SetActiveEntryProxy(ActiveEntryProxy::Create(hash, this));
    callback.Run(net::OK);
  } else {
    // The entry was made active while we waiting for the open from hash to
    // finish. The entry created from hash needs to be closed, and the one
    // in |active_entries_| can be returned to the caller.
    simple_entry->Close();
    it->second->OpenEntry(entry, callback);
  }
}

void SimpleBackendImpl::OnEntryOpenedFromKey(
    const std::string key,
    Entry** entry,
    const scoped_refptr<SimpleEntryImpl>& simple_entry,
    const CompletionCallback& callback,
    int error_code) {
  int final_code = error_code;
  if (final_code == net::OK) {
    bool key_matches = key.compare(simple_entry->key()) == 0;
    if (!key_matches) {
      // TODO(clamy): Add a unit test to check this code path.
      DLOG(WARNING) << "Key mismatch on open.";
      simple_entry->Doom();
      simple_entry->Close();
      final_code = net::ERR_FAILED;
    } else {
      DCHECK_EQ(simple_entry->entry_hash(), simple_util::GetEntryHashKey(key));
    }
    SIMPLE_CACHE_UMA(BOOLEAN, "KeyMatchedOnOpen", cache_type_, key_matches);
  }
  callback.Run(final_code);
}

void SimpleBackendImpl::DoomEntriesComplete(
    scoped_ptr<std::vector<uint64> > entry_hashes,
    const net::CompletionCallback& callback,
    int result) {
  std::for_each(
      entry_hashes->begin(), entry_hashes->end(),
      std::bind1st(std::mem_fun(&SimpleBackendImpl::OnDoomComplete),
                   this));
  callback.Run(result);
}

void SimpleBackendImpl::FlushWorkerPoolForTesting() {
  if (g_sequenced_worker_pool)
    g_sequenced_worker_pool->FlushForTesting();
}

}  // namespace disk_cache
