// 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 "base/callback_helpers.h"
#include "base/task/thread_pool.h"

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

#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/lazy_instance.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/task_runner_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/memory_usage_estimator.h"
#include "base/trace_event/process_memory_dump.h"
#include "build/build_config.h"
#include "net/base/net_errors.h"
#include "net/base/prioritized_task_runner.h"
#include "net/disk_cache/backend_cleanup_tracker.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_file_tracker.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::FilePath;
using base::Time;
using base::DirectoryExists;
using base::CreateDirectory;

namespace disk_cache {

namespace {

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

// Native code entries can be large. Rather than increasing the overall cache
// size, allow an individual entry to occupy up to half of the cache.
const int kMaxNativeCodeFileRatio = 2;

// Overrides the above.
const int64_t kMinFileSizeLimit = 5 * 1024 * 1024;

// Global context of all the files we have open --- this permits some to be
// closed on demand if too many FDs are being used, to avoid running out.
base::LazyInstance<SimpleFileTracker>::Leaky g_simple_file_tracker =
    LAZY_INSTANCE_INITIALIZER;

// 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.
SimpleCacheConsistencyResult FileStructureConsistent(
    const base::FilePath& path) {
  if (!base::PathExists(path) && !base::CreateDirectory(path)) {
    LOG(ERROR) << "Failed to create directory: " << path.LossyDisplayName();
    return SimpleCacheConsistencyResult::kCreateDirectoryFailed;
  }
  return disk_cache::UpgradeSimpleCacheOnDisk(path);
}

// A context used by a BarrierCompletionCallback to track state.
struct BarrierContext {
  explicit BarrierContext(net::CompletionOnceCallback final_callback,
                          int expected)
      : final_callback_(std::move(final_callback)),
        expected(expected),
        count(0),
        had_error(false) {}

  net::CompletionOnceCallback final_callback_;
  const int expected;
  int count;
  bool had_error;
};

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

// A barrier completion callback is a repeatable callback 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.
base::RepeatingCallback<void(int)> MakeBarrierCompletionCallback(
    int count,
    net::CompletionOnceCallback final_callback) {
  BarrierContext* context =
      new BarrierContext(std::move(final_callback), count);
  return base::BindRepeating(&BarrierCompletionCallbackImpl,
                             base::Owned(context));
}

// A short bindable thunk that ensures a completion callback is always called
// after running an operation asynchronously. Checks for backend liveness first.
void RunOperationAndCallback(
    base::WeakPtr<SimpleBackendImpl> backend,
    base::OnceCallback<net::Error(net::CompletionOnceCallback)> operation,
    net::CompletionOnceCallback operation_callback) {
  if (!backend)
    return;

  base::RepeatingCallback<void(int)> copyable_callback;
  if (operation_callback)
    copyable_callback =
        base::AdaptCallbackForRepeating(std::move(operation_callback));
  const int operation_result = std::move(operation).Run(copyable_callback);
  if (operation_result != net::ERR_IO_PENDING && copyable_callback)
    copyable_callback.Run(operation_result);
}

// Same but for things that work with EntryResult.
void RunEntryResultOperationAndCallback(
    base::WeakPtr<SimpleBackendImpl> backend,
    base::OnceCallback<EntryResult(EntryResultCallback)> operation,
    EntryResultCallback operation_callback) {
  if (!backend)
    return;

  base::RepeatingCallback<void(EntryResult)> copyable_callback;
  if (operation_callback)
    copyable_callback =
        base::AdaptCallbackForRepeating(std::move(operation_callback));
  EntryResult operation_result = std::move(operation).Run(copyable_callback);
  if (operation_result.net_error() != net::ERR_IO_PENDING && copyable_callback)
    copyable_callback.Run(std::move(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

const base::Feature SimpleBackendImpl::kPrioritizedSimpleCacheTasks{
    "PrioritizedSimpleCacheTasks", base::FEATURE_ENABLED_BY_DEFAULT};

// Static function which is called by base::trace_event::EstimateMemoryUsage()
// to estimate the memory of SimpleEntryImpl* type.
// This needs to be in disk_cache namespace.
size_t EstimateMemoryUsage(const SimpleEntryImpl* const& entry_impl) {
  return sizeof(SimpleEntryImpl) + entry_impl->EstimateMemoryUsage();
}

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 std::unique_ptr<SimpleEntryImpl::ActiveEntryProxy> Create(
      int64_t entry_hash,
      SimpleBackendImpl* backend) {
    std::unique_ptr<SimpleEntryImpl::ActiveEntryProxy> proxy(
        new ActiveEntryProxy(entry_hash, backend));
    return proxy;
  }

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

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

SimpleBackendImpl::SimpleBackendImpl(
    const FilePath& path,
    scoped_refptr<BackendCleanupTracker> cleanup_tracker,
    SimpleFileTracker* file_tracker,
    int64_t max_bytes,
    net::CacheType cache_type,
    net::NetLog* net_log)
    : Backend(cache_type),
      cleanup_tracker_(std::move(cleanup_tracker)),
      file_tracker_(file_tracker ? file_tracker
                                 : g_simple_file_tracker.Pointer()),
      path_(path),
      cache_runner_(base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
           base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
      orig_max_size_(max_bytes),
      entry_operations_mode_((cache_type == net::DISK_CACHE ||
                              cache_type == net::GENERATED_BYTE_CODE_CACHE ||
                              cache_type == net::GENERATED_NATIVE_CODE_CACHE)
                                 ? SimpleEntryImpl::OPTIMISTIC_OPERATIONS
                                 : SimpleEntryImpl::NON_OPTIMISTIC_OPERATIONS),
      post_doom_waiting_(
          base::MakeRefCounted<SimplePostDoomWaiterTable>(cache_type)),
      net_log_(net_log) {
  // Treat negative passed-in sizes same as SetMaxSize would here and in other
  // backends, as default (if first call).
  if (orig_max_size_ < 0)
    orig_max_size_ = 0;
}

SimpleBackendImpl::~SimpleBackendImpl() {
  // Write the index out if there is a pending write from a
  // previous operation.
  if (index_->HasPendingWrite())
    index_->WriteToDisk(SimpleIndex::INDEX_WRITE_REASON_SHUTDOWN);
}

void SimpleBackendImpl::SetTaskRunnerForTesting(
    scoped_refptr<base::SequencedTaskRunner> task_runner) {
  prioritized_task_runner_ =
      base::MakeRefCounted<net::PrioritizedTaskRunner>(std::move(task_runner));
}

net::Error SimpleBackendImpl::Init(CompletionOnceCallback completion_callback) {
  auto worker_pool = base::ThreadPool::CreateTaskRunner(
      {base::MayBlock(), base::WithBaseSyncPrimitives(),
       base::TaskPriority::USER_BLOCKING,
       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});

  prioritized_task_runner_ =
      base::MakeRefCounted<net::PrioritizedTaskRunner>(worker_pool);

  index_ = std::make_unique<SimpleIndex>(
      base::SequencedTaskRunnerHandle::Get(), cleanup_tracker_.get(), this,
      GetCacheType(),
      std::make_unique<SimpleIndexFile>(cache_runner_, worker_pool.get(),
                                        GetCacheType(), path_));
  index_->ExecuteWhenReady(
      base::BindOnce(&RecordIndexLoad, GetCacheType(), base::TimeTicks::Now()));

  PostTaskAndReplyWithResult(
      cache_runner_.get(), FROM_HERE,
      base::BindOnce(&SimpleBackendImpl::InitCacheStructureOnDisk, path_,
                     orig_max_size_, GetCacheType()),
      base::BindOnce(&SimpleBackendImpl::InitializeIndex, AsWeakPtr(),
                     std::move(completion_callback)));
  return net::ERR_IO_PENDING;
}

bool SimpleBackendImpl::SetMaxSize(int64_t max_bytes) {
  if (max_bytes < 0)
    return false;
  orig_max_size_ = max_bytes;
  index_->SetMaxSize(max_bytes);
  return true;
}

int64_t SimpleBackendImpl::MaxFileSize() const {
  uint64_t file_size_ratio = GetCacheType() == net::GENERATED_NATIVE_CODE_CACHE
                                 ? kMaxNativeCodeFileRatio
                                 : kMaxFileRatio;
  return std::max(
      base::saturated_cast<int64_t>(index_->max_size() / file_size_ratio),
      kMinFileSizeLimit);
}

scoped_refptr<SimplePostDoomWaiterTable> SimpleBackendImpl::OnDoomStart(
    uint64_t entry_hash) {
  post_doom_waiting_->OnDoomStart(entry_hash);
  return post_doom_waiting_;
}

void SimpleBackendImpl::DoomEntries(std::vector<uint64_t>* entry_hashes,
                                    net::CompletionOnceCallback callback) {
  std::unique_ptr<std::vector<uint64_t>> mass_doom_entry_hashes(
      new std::vector<uint64_t>());
  mass_doom_entry_hashes->swap(*entry_hashes);

  std::vector<uint64_t> to_doom_individually_hashes;

  // For each of the entry hashes, there are two cases:
  // 1. There are corresponding entries in active set, pending doom, or both
  //    sets, and so the hash should be doomed individually to avoid flakes.
  // 2. The hash is not in active use at all, so we can call
  //    SimpleSynchronousEntry::DeleteEntrySetFiles and delete the files en
  //    masse.
  for (int i = mass_doom_entry_hashes->size() - 1; i >= 0; --i) {
    const uint64_t entry_hash = (*mass_doom_entry_hashes)[i];
    if (!active_entries_.count(entry_hash) &&
        !post_doom_waiting_->Has(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);
  }

  base::RepeatingCallback<void(int)> barrier_callback =
      MakeBarrierCompletionCallback(to_doom_individually_hashes.size() + 1,
                                    std::move(callback));
  for (std::vector<uint64_t>::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_t>::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
  // std::move() before mass_doom_entry_hashes.get().
  std::vector<uint64_t>* mass_doom_entry_hashes_ptr =
      mass_doom_entry_hashes.get();

  PostTaskAndReplyWithResult(
      prioritized_task_runner_->task_runner(), FROM_HERE,
      base::BindOnce(&SimpleSynchronousEntry::DeleteEntrySetFiles,
                     mass_doom_entry_hashes_ptr, path_),
      base::BindOnce(&SimpleBackendImpl::DoomEntriesComplete, AsWeakPtr(),
                     std::move(mass_doom_entry_hashes), barrier_callback));
}

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

EntryResult SimpleBackendImpl::OpenEntry(const std::string& key,
                                         net::RequestPriority request_priority,
                                         EntryResultCallback callback) {
  const uint64_t entry_hash = simple_util::GetEntryHashKey(key);

  std::vector<SimplePostDoomWaiter>* post_doom = nullptr;
  scoped_refptr<SimpleEntryImpl> simple_entry = CreateOrFindActiveOrDoomedEntry(
      entry_hash, key, request_priority, &post_doom);
  if (!simple_entry) {
    if (post_doom->empty() &&
        entry_operations_mode_ == SimpleEntryImpl::OPTIMISTIC_OPERATIONS) {
      // The entry is doomed, and no other backend operations are queued for the
      // entry, thus the open must fail and it's safe to return synchronously.
      net::NetLogWithSource log_for_entry(net::NetLogWithSource::Make(
          net_log_, net::NetLogSourceType::DISK_CACHE_ENTRY));
      log_for_entry.AddEvent(
          net::NetLogEventType::SIMPLE_CACHE_ENTRY_OPEN_CALL);
      log_for_entry.AddEventWithNetErrorCode(
          net::NetLogEventType::SIMPLE_CACHE_ENTRY_OPEN_END, net::ERR_FAILED);
      return EntryResult::MakeError(net::ERR_FAILED);
    }

    base::OnceCallback<EntryResult(EntryResultCallback)> operation =
        base::BindOnce(&SimpleBackendImpl::OpenEntry, base::Unretained(this),
                       key, request_priority);
    post_doom->emplace_back(base::BindOnce(&RunEntryResultOperationAndCallback,
                                           AsWeakPtr(), std::move(operation),
                                           std::move(callback)));
    return EntryResult::MakeError(net::ERR_IO_PENDING);
  }
  return simple_entry->OpenEntry(std::move(callback));
}

EntryResult SimpleBackendImpl::CreateEntry(
    const std::string& key,
    net::RequestPriority request_priority,
    EntryResultCallback callback) {
  DCHECK_LT(0u, key.size());
  const uint64_t entry_hash = simple_util::GetEntryHashKey(key);

  std::vector<SimplePostDoomWaiter>* post_doom = nullptr;
  scoped_refptr<SimpleEntryImpl> simple_entry = CreateOrFindActiveOrDoomedEntry(
      entry_hash, key, request_priority, &post_doom);

  // If couldn't grab an entry object due to pending doom, see if circumstances
  // are right for an optimistic create.
  if (!simple_entry) {
    simple_entry = MaybeOptimisticCreateForPostDoom(
        entry_hash, key, request_priority, post_doom);
  }

  // If that doesn't work either, retry this once doom is done.
  if (!simple_entry) {
    base::OnceCallback<EntryResult(EntryResultCallback)> operation =
        base::BindOnce(&SimpleBackendImpl::CreateEntry, base::Unretained(this),
                       key, request_priority);
    post_doom->emplace_back(base::BindOnce(&RunEntryResultOperationAndCallback,
                                           AsWeakPtr(), std::move(operation),
                                           std::move(callback)));
    return EntryResult::MakeError(net::ERR_IO_PENDING);
  }

  return simple_entry->CreateEntry(std::move(callback));
}

EntryResult SimpleBackendImpl::OpenOrCreateEntry(
    const std::string& key,
    net::RequestPriority request_priority,
    EntryResultCallback callback) {
  DCHECK_LT(0u, key.size());
  const uint64_t entry_hash = simple_util::GetEntryHashKey(key);

  std::vector<SimplePostDoomWaiter>* post_doom = nullptr;
  scoped_refptr<SimpleEntryImpl> simple_entry = CreateOrFindActiveOrDoomedEntry(
      entry_hash, key, request_priority, &post_doom);

  // If couldn't grab an entry object due to pending doom, see if circumstances
  // are right for an optimistic create.
  if (!simple_entry) {
    simple_entry = MaybeOptimisticCreateForPostDoom(
        entry_hash, key, request_priority, post_doom);
    if (simple_entry) {
      return simple_entry->CreateEntry(std::move(callback));
    } else {
      // If that doesn't work either, retry this once doom is done.
      base::OnceCallback<EntryResult(EntryResultCallback)> operation =
          base::BindOnce(&SimpleBackendImpl::OpenOrCreateEntry,
                         base::Unretained(this), key, request_priority);
      post_doom->emplace_back(
          base::BindOnce(&RunEntryResultOperationAndCallback, AsWeakPtr(),
                         std::move(operation), std::move(callback)));
      return EntryResult::MakeError(net::ERR_IO_PENDING);
    }
  }

  return simple_entry->OpenOrCreateEntry(std::move(callback));
}

scoped_refptr<SimpleEntryImpl>
SimpleBackendImpl::MaybeOptimisticCreateForPostDoom(
    uint64_t entry_hash,
    const std::string& key,
    net::RequestPriority request_priority,
    std::vector<SimplePostDoomWaiter>* post_doom) {
  scoped_refptr<SimpleEntryImpl> simple_entry;
  // We would like to optimistically have create go ahead, for benefit of
  // HTTP cache use. This can only be sanely done if we are the only op
  // serialized after doom's completion.
  if (post_doom->empty() &&
      entry_operations_mode_ == SimpleEntryImpl::OPTIMISTIC_OPERATIONS) {
    simple_entry = new SimpleEntryImpl(
        GetCacheType(), path_, cleanup_tracker_.get(), entry_hash,
        entry_operations_mode_, this, file_tracker_, net_log_,
        GetNewEntryPriority(request_priority));
    simple_entry->SetKey(key);
    simple_entry->SetActiveEntryProxy(
        ActiveEntryProxy::Create(entry_hash, this));
    simple_entry->SetCreatePendingDoom();
    std::pair<EntryMap::iterator, bool> insert_result = active_entries_.insert(
        EntryMap::value_type(entry_hash, simple_entry.get()));
    post_doom->emplace_back(base::BindOnce(
        &SimpleEntryImpl::NotifyDoomBeforeCreateComplete, simple_entry));
    DCHECK(insert_result.second);
  }

  return simple_entry;
}

net::Error SimpleBackendImpl::DoomEntry(const std::string& key,
                                        net::RequestPriority priority,
                                        CompletionOnceCallback callback) {
  const uint64_t entry_hash = simple_util::GetEntryHashKey(key);

  std::vector<SimplePostDoomWaiter>* post_doom = nullptr;
  scoped_refptr<SimpleEntryImpl> simple_entry =
      CreateOrFindActiveOrDoomedEntry(entry_hash, key, priority, &post_doom);
  if (!simple_entry) {
    // At first glance, it appears exceedingly silly to queue up a doom
    // when we get here because the files corresponding to our key are being
    // deleted... but it's possible that one of the things in post_doom is a
    // create for our key, in which case we still have work to do.
    base::OnceCallback<net::Error(CompletionOnceCallback)> operation =
        base::BindOnce(&SimpleBackendImpl::DoomEntry, base::Unretained(this),
                       key, priority);
    post_doom->emplace_back(base::BindOnce(&RunOperationAndCallback,
                                           AsWeakPtr(), std::move(operation),
                                           std::move(callback)));
    return net::ERR_IO_PENDING;
  }

  return simple_entry->DoomEntry(std::move(callback));
}

net::Error SimpleBackendImpl::DoomAllEntries(CompletionOnceCallback callback) {
  return DoomEntriesBetween(Time(), Time(), std::move(callback));
}

net::Error SimpleBackendImpl::DoomEntriesBetween(
    const Time initial_time,
    const Time end_time,
    CompletionOnceCallback callback) {
  index_->ExecuteWhenReady(base::BindOnce(&SimpleBackendImpl::IndexReadyForDoom,
                                          AsWeakPtr(), initial_time, end_time,
                                          std::move(callback)));
  return net::ERR_IO_PENDING;
}

net::Error SimpleBackendImpl::DoomEntriesSince(
    const Time initial_time,
    CompletionOnceCallback callback) {
  return DoomEntriesBetween(initial_time, Time(), std::move(callback));
}

int64_t SimpleBackendImpl::CalculateSizeOfAllEntries(
    Int64CompletionOnceCallback callback) {
  index_->ExecuteWhenReady(
      base::BindOnce(&SimpleBackendImpl::IndexReadyForSizeCalculation,
                     AsWeakPtr(), std::move(callback)));
  return net::ERR_IO_PENDING;
}

int64_t SimpleBackendImpl::CalculateSizeOfEntriesBetween(
    base::Time initial_time,
    base::Time end_time,
    Int64CompletionOnceCallback callback) {
  index_->ExecuteWhenReady(
      base::BindOnce(&SimpleBackendImpl::IndexReadyForSizeBetweenCalculation,
                     AsWeakPtr(), initial_time, end_time, std::move(callback)));
  return net::ERR_IO_PENDING;
}

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

  // From Backend::Iterator:
  EntryResult OpenNextEntry(EntryResultCallback callback) override {
    if (!backend_)
      return EntryResult::MakeError(net::ERR_FAILED);
    CompletionOnceCallback open_next_entry_impl =
        base::BindOnce(&SimpleIterator::OpenNextEntryImpl,
                       weak_factory_.GetWeakPtr(), std::move(callback));
    backend_->index_->ExecuteWhenReady(std::move(open_next_entry_impl));
    return EntryResult::MakeError(net::ERR_IO_PENDING);
  }

  void OpenNextEntryImpl(EntryResultCallback callback,
                         int index_initialization_error_code) {
    if (!backend_) {
      std::move(callback).Run(EntryResult::MakeError(net::ERR_FAILED));
      return;
    }
    if (index_initialization_error_code != net::OK) {
      std::move(callback).Run(EntryResult::MakeError(
          static_cast<net::Error>(index_initialization_error_code)));
      return;
    }
    if (!hashes_to_enumerate_)
      hashes_to_enumerate_ = backend_->index()->GetAllHashes();

    auto copyable_callback =
        base::AdaptCallbackForRepeating(std::move(callback));

    while (!hashes_to_enumerate_->empty()) {
      uint64_t entry_hash = hashes_to_enumerate_->back();
      hashes_to_enumerate_->pop_back();
      if (backend_->index()->Has(entry_hash)) {
        EntryResultCallback continue_iteration =
            base::BindOnce(&SimpleIterator::CheckIterationReturnValue,
                           weak_factory_.GetWeakPtr(), copyable_callback);
        EntryResult open_result = backend_->OpenEntryFromHash(
            entry_hash, std::move(continue_iteration));
        if (open_result.net_error() == net::ERR_IO_PENDING)
          return;
        if (open_result.net_error() != net::ERR_FAILED) {
          copyable_callback.Run(std::move(open_result));
          return;
        }
      }
    }
    copyable_callback.Run(EntryResult::MakeError(net::ERR_FAILED));
  }

  void CheckIterationReturnValue(EntryResultCallback callback,
                                 EntryResult result) {
    if (result.net_error() == net::ERR_FAILED) {
      OpenNextEntry(std::move(callback));
      return;
    }
    std::move(callback).Run(std::move(result));
  }

 private:
  base::WeakPtr<SimpleBackendImpl> backend_;
  std::unique_ptr<std::vector<uint64_t>> hashes_to_enumerate_;
  base::WeakPtrFactory<SimpleIterator> weak_factory_{this};
};

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

void SimpleBackendImpl::GetStats(base::StringPairs* 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));
}

size_t SimpleBackendImpl::DumpMemoryStats(
    base::trace_event::ProcessMemoryDump* pmd,
    const std::string& parent_absolute_name) const {
  base::trace_event::MemoryAllocatorDump* dump =
      pmd->CreateAllocatorDump(parent_absolute_name + "/simple_backend");

  size_t size = base::trace_event::EstimateMemoryUsage(index_) +
                base::trace_event::EstimateMemoryUsage(active_entries_);
  // TODO(xunjieli): crbug.com/669108. Track |post_doom_waiting_| once
  // base::OnceClosure is supported in memory_usage_estimator.h.
  dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
                  base::trace_event::MemoryAllocatorDump::kUnitsBytes, size);
  return size;
}

uint8_t SimpleBackendImpl::GetEntryInMemoryData(const std::string& key) {
  const uint64_t entry_hash = simple_util::GetEntryHashKey(key);
  return index_->GetEntryInMemoryData(entry_hash);
}

void SimpleBackendImpl::SetEntryInMemoryData(const std::string& key,
                                             uint8_t data) {
  const uint64_t entry_hash = simple_util::GetEntryHashKey(key);
  index_->SetEntryInMemoryData(entry_hash, data);
}

void SimpleBackendImpl::InitializeIndex(CompletionOnceCallback callback,
                                        const DiskStatResult& result) {
  if (result.net_error == net::OK) {
    index_->SetMaxSize(result.max_size);
#if defined(OS_ANDROID)
    if (app_status_listener_)
      index_->set_app_status_listener(app_status_listener_);
#endif
    index_->Initialize(result.cache_dir_mtime);
  }
  std::move(callback).Run(result.net_error);
}

void SimpleBackendImpl::IndexReadyForDoom(Time initial_time,
                                          Time end_time,
                                          CompletionOnceCallback callback,
                                          int result) {
  if (result != net::OK) {
    std::move(callback).Run(result);
    return;
  }
  std::unique_ptr<std::vector<uint64_t>> removed_key_hashes(
      index_->GetEntriesBetween(initial_time, end_time).release());
  DoomEntries(removed_key_hashes.get(), std::move(callback));
}

void SimpleBackendImpl::IndexReadyForSizeCalculation(
    Int64CompletionOnceCallback callback,
    int result) {
  int64_t rv = result == net::OK ? index_->GetCacheSize() : result;
  std::move(callback).Run(rv);
}

void SimpleBackendImpl::IndexReadyForSizeBetweenCalculation(
    base::Time initial_time,
    base::Time end_time,
    Int64CompletionOnceCallback callback,
    int result) {
  int64_t rv = result == net::OK
                   ? index_->GetCacheSizeBetween(initial_time, end_time)
                   : result;
  std::move(callback).Run(rv);
}

// static
SimpleBackendImpl::DiskStatResult SimpleBackendImpl::InitCacheStructureOnDisk(
    const base::FilePath& path,
    uint64_t suggested_max_size,
    net::CacheType cache_type) {
  DiskStatResult result;
  result.max_size = suggested_max_size;
  result.net_error = net::OK;
  SimpleCacheConsistencyResult consistency = FileStructureConsistent(path);
  SIMPLE_CACHE_UMA(ENUMERATION, "ConsistencyResult", cache_type, consistency);

  // If the cache structure is inconsistent make a single attempt at
  // recovering it.  Previously there were bugs that could cause a partially
  // written fake index file to be left in an otherwise empty cache.  In
  // that case we can delete the index files and start over.  Also, some
  // consistency failures may leave an empty directory directly and we can
  // retry those cases as well.
  if (consistency != SimpleCacheConsistencyResult::kOK) {
    bool deleted_files = disk_cache::DeleteIndexFilesIfCacheIsEmpty(path);
    SIMPLE_CACHE_UMA(BOOLEAN, "DidDeleteIndexFilesAfterFailedConsistency",
                     cache_type, deleted_files);
    if (base::IsDirectoryEmpty(path)) {
      SimpleCacheConsistencyResult orig_consistency = consistency;
      consistency = FileStructureConsistent(path);
      SIMPLE_CACHE_UMA(ENUMERATION, "RetryConsistencyResult", cache_type,
                       consistency);
      if (consistency == SimpleCacheConsistencyResult::kOK) {
        SIMPLE_CACHE_UMA(ENUMERATION,
                         "OriginalConsistencyResultBeforeSuccessfulRetry",
                         cache_type, orig_consistency);
      }
    }
    if (deleted_files) {
      SIMPLE_CACHE_UMA(ENUMERATION, "ConsistencyResultAfterIndexFilesDeleted",
                       cache_type, consistency);
    }
  }

  if (consistency != SimpleCacheConsistencyResult::kOK) {
    LOG(ERROR) << "Simple Cache Backend: wrong file structure on disk: "
               << static_cast<int>(consistency)
               << " path: " << path.LossyDisplayName();
    result.net_error = net::ERR_FAILED;
  } else {
    bool mtime_result =
        disk_cache::simple_util::GetMTime(path, &result.cache_dir_mtime);
    if (!mtime_result) {
      // Something deleted the directory between when we set it up and the
      // mstat; this is not uncommon on some test fixtures which erase their
      // tempdir while some worker threads may still be running.
      LOG(ERROR) << "Simple Cache Backend: cache directory inaccessible right "
                    "after creation; path: "
                 << path.LossyDisplayName();
      result.net_error = net::ERR_FAILED;
    } else if (!result.max_size) {
      int64_t available = base::SysInfo::AmountOfFreeDiskSpace(path);
      result.max_size = disk_cache::PreferredCacheSize(available, cache_type);
      DCHECK(result.max_size);
    }
  }
  return result;
}

scoped_refptr<SimpleEntryImpl>
SimpleBackendImpl::CreateOrFindActiveOrDoomedEntry(
    const uint64_t entry_hash,
    const std::string& key,
    net::RequestPriority request_priority,
    std::vector<SimplePostDoomWaiter>** post_doom) {
  DCHECK_EQ(entry_hash, simple_util::GetEntryHashKey(key));

  // If there is a doom pending, we would want to serialize after it.
  *post_doom = post_doom_waiting_->Find(entry_hash);
  if (*post_doom)
    return nullptr;

  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(
        GetCacheType(), path_, cleanup_tracker_.get(), entry_hash,
        entry_operations_mode_, this, file_tracker_, net_log_,
        GetNewEntryPriority(request_priority));
    entry->SetKey(key);
    entry->SetActiveEntryProxy(ActiveEntryProxy::Create(entry_hash, this));
  }
  // TODO(jkarlin): In case of recycling a half-closed entry, we might want to
  // update its priority.
  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));
    DCHECK(post_doom_waiting_->Has(entry_hash));
    // Re-run ourselves to handle the now-pending doom.
    return CreateOrFindActiveOrDoomedEntry(entry_hash, key, request_priority,
                                           post_doom);
  }
  return base::WrapRefCounted(it->second);
}

EntryResult SimpleBackendImpl::OpenEntryFromHash(uint64_t entry_hash,
                                                 EntryResultCallback callback) {
  std::vector<SimplePostDoomWaiter>* post_doom =
      post_doom_waiting_->Find(entry_hash);
  if (post_doom) {
    base::OnceCallback<EntryResult(EntryResultCallback)> operation =
        base::BindOnce(&SimpleBackendImpl::OpenEntryFromHash,
                       base::Unretained(this), entry_hash);
    // TODO(https://crbug.com/1019682) The cancellation behavior looks wrong.
    post_doom->emplace_back(base::BindOnce(&RunEntryResultOperationAndCallback,
                                           AsWeakPtr(), std::move(operation),
                                           std::move(callback)));
    return EntryResult::MakeError(net::ERR_IO_PENDING);
  }

  auto has_active = active_entries_.find(entry_hash);
  if (has_active != active_entries_.end()) {
    return OpenEntry(has_active->second->key(), net::HIGHEST,
                     std::move(callback));
  }

  scoped_refptr<SimpleEntryImpl> simple_entry = new SimpleEntryImpl(
      GetCacheType(), path_, cleanup_tracker_.get(), entry_hash,
      entry_operations_mode_, this, file_tracker_, net_log_,
      GetNewEntryPriority(net::HIGHEST));
  EntryResultCallback backend_callback =
      base::BindOnce(&SimpleBackendImpl::OnEntryOpenedFromHash, AsWeakPtr(),
                     entry_hash, simple_entry, std::move(callback));
  return simple_entry->OpenEntry(std::move(backend_callback));
}

net::Error SimpleBackendImpl::DoomEntryFromHash(
    uint64_t entry_hash,
    CompletionOnceCallback callback) {
  Entry** entry = new Entry*();
  std::unique_ptr<Entry*> scoped_entry(entry);

  std::vector<SimplePostDoomWaiter>* post_doom =
      post_doom_waiting_->Find(entry_hash);
  if (post_doom) {
    base::OnceCallback<net::Error(CompletionOnceCallback)> operation =
        base::BindOnce(&SimpleBackendImpl::DoomEntryFromHash,
                       base::Unretained(this), entry_hash);
    post_doom->emplace_back(base::BindOnce(&RunOperationAndCallback,
                                           AsWeakPtr(), std::move(operation),
                                           std::move(callback)));
    return net::ERR_IO_PENDING;
  }

  auto active_it = active_entries_.find(entry_hash);
  if (active_it != active_entries_.end())
    return active_it->second->DoomEntry(std::move(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_t> entry_hash_vector;
  entry_hash_vector.push_back(entry_hash);
  DoomEntries(&entry_hash_vector, std::move(callback));
  return net::ERR_IO_PENDING;
}

void SimpleBackendImpl::OnEntryOpenedFromHash(
    uint64_t hash,
    const scoped_refptr<SimpleEntryImpl>& simple_entry,
    EntryResultCallback callback,
    EntryResult result) {
  if (result.net_error() != net::OK) {
    std::move(callback).Run(std::move(result));
    return;
  }

  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));
    std::move(callback).Run(std::move(result));
  } 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.
    Entry* entry_from_result = result.ReleaseEntry();
    DCHECK_EQ(entry_from_result, simple_entry.get());
    simple_entry->Close();
    EntryResult reopen_result = it->second->OpenEntry(std::move(callback));
    DCHECK_EQ(reopen_result.net_error(), net::ERR_IO_PENDING);
  }
}

void SimpleBackendImpl::DoomEntriesComplete(
    std::unique_ptr<std::vector<uint64_t>> entry_hashes,
    CompletionOnceCallback callback,
    int result) {
  for (const uint64_t& entry_hash : *entry_hashes)
    post_doom_waiting_->OnDoomComplete(entry_hash);
  std::move(callback).Run(result);
}

// static
void SimpleBackendImpl::FlushWorkerPoolForTesting() {
  // TODO(morlovich): Remove this, move everything over to disk_cache:: use.
  base::ThreadPoolInstance::Get()->FlushForTesting();
}

uint32_t SimpleBackendImpl::GetNewEntryPriority(
    net::RequestPriority request_priority) {
  if (base::FeatureList::IsEnabled(kPrioritizedSimpleCacheTasks)) {
    // Lower priority is better, so give high network priority the least bump.
    return ((net::RequestPriority::MAXIMUM_PRIORITY - request_priority) *
            10000) +
           entry_count_++;
  }

  return 0;
}

}  // namespace disk_cache
