12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/disk_cache/simple/simple_backend_impl.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <algorithm> 87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <cstdlib> 968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <functional> 107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#if defined(OS_POSIX) 12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <sys/resource.h> 13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif 14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/location.h" 197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/metrics/field_trial.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/metrics/histogram.h" 21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/metrics/sparse_histogram.h" 227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/single_thread_task_runner.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/sys_info.h" 24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/task_runner_util.h" 2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/thread_task_runner_handle.h" 267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h" 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/disk_cache/cache_util.h" 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/disk_cache/simple/simple_entry_format.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/disk_cache/simple/simple_entry_impl.h" 3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "net/disk_cache/simple/simple_histogram_macros.h" 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/disk_cache/simple/simple_index.h" 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/disk_cache/simple/simple_index_file.h" 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/disk_cache/simple/simple_synchronous_entry.h" 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/disk_cache/simple/simple_util.h" 37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/disk_cache/simple/simple_version_upgrade.h" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using base::Callback; 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::Closure; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::FilePath; 427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)using base::SequencedWorkerPool; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::Time; 447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::DirectoryExists; 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using base::CreateDirectory; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace disk_cache { 4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Maximum number of concurrent worker pool threads, which also is the limit 527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// on concurrent IO (as we use one thread per IO request). 537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const int kDefaultMaxWorkerThreads = 50; 547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst char kThreadNamePrefix[] = "SimpleCache"; 567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Maximum fraction of the cache that one entry can consume. 58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const int kMaxFileRatio = 8; 59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// A global sequenced worker pool to use for launching all tasks. 617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SequencedWorkerPool* g_sequenced_worker_pool = NULL; 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void MaybeCreateSequencedWorkerPool() { 647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!g_sequenced_worker_pool) { 657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int max_worker_threads = kDefaultMaxWorkerThreads; 667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const std::string thread_count_field_trial = 687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::FieldTrialList::FindFullName("SimpleCacheMaxThreads"); 697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!thread_count_field_trial.empty()) { 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) max_worker_threads = 717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) std::max(1, std::atoi(thread_count_field_trial.c_str())); 727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) g_sequenced_worker_pool = new SequencedWorkerPool(max_worker_threads, 757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kThreadNamePrefix); 767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) g_sequenced_worker_pool->AddRef(); // Leak it. 777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool g_fd_limit_histogram_has_been_populated = false; 81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void MaybeHistogramFdLimit(net::CacheType cache_type) { 83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (g_fd_limit_histogram_has_been_populated) 84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Used in histograms; add new entries at end. 87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) enum FdLimitStatus { 88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FD_LIMIT_STATUS_UNSUPPORTED = 0, 89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FD_LIMIT_STATUS_FAILED = 1, 90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FD_LIMIT_STATUS_SUCCEEDED = 2, 91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FD_LIMIT_STATUS_MAX = 3 92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) }; 93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FdLimitStatus fd_limit_status = FD_LIMIT_STATUS_UNSUPPORTED; 94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int soft_fd_limit = 0; 95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int hard_fd_limit = 0; 96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#if defined(OS_POSIX) 98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) struct rlimit nofile; 99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!getrlimit(RLIMIT_NOFILE, &nofile)) { 100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) soft_fd_limit = nofile.rlim_cur; 101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) hard_fd_limit = nofile.rlim_max; 102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) fd_limit_status = FD_LIMIT_STATUS_SUCCEEDED; 103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) fd_limit_status = FD_LIMIT_STATUS_FAILED; 105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif 107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SIMPLE_CACHE_UMA(ENUMERATION, 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) "FileDescriptorLimitStatus", cache_type, 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) fd_limit_status, FD_LIMIT_STATUS_MAX); 111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (fd_limit_status == FD_LIMIT_STATUS_SUCCEEDED) { 11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SIMPLE_CACHE_UMA(SPARSE_SLOWLY, 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) "FileDescriptorLimitSoft", cache_type, soft_fd_limit); 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SIMPLE_CACHE_UMA(SPARSE_SLOWLY, 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) "FileDescriptorLimitHard", cache_type, hard_fd_limit); 116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) g_fd_limit_histogram_has_been_populated = true; 119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Detects if the files in the cache directory match the current disk cache 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// backend type and version. If the directory contains no cache, occupies it 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// with the fresh structure. 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool FileStructureConsistent(const base::FilePath& path) { 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::PathExists(path) && !base::CreateDirectory(path)) { 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Failed to create directory: " << path.LossyDisplayName(); 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return disk_cache::UpgradeSimpleCacheOnDisk(path); 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// A context used by a BarrierCompletionCallback to track state. 13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)struct BarrierContext { 13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) BarrierContext(int expected) 13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) : expected(expected), 13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) count(0), 13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) had_error(false) {} 13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const int expected; 14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int count; 14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool had_error; 14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}; 14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void BarrierCompletionCallbackImpl( 14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) BarrierContext* context, 14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const net::CompletionCallback& final_callback, 14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int result) { 14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK_GT(context->expected, context->count); 14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (context->had_error) 15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return; 15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (result != net::OK) { 15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) context->had_error = true; 15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) final_callback.Run(result); 15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return; 15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ++context->count; 15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (context->count == context->expected) 15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) final_callback.Run(net::OK); 15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// A barrier completion callback is a net::CompletionCallback that waits for 16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// |count| successful results before invoking |final_callback|. In the case of 16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// an error, the first error is passed to |final_callback| and all others 16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// are ignored. 16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)net::CompletionCallback MakeBarrierCompletionCallback( 16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int count, 16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const net::CompletionCallback& final_callback) { 16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) BarrierContext* context = new BarrierContext(count); 16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return base::Bind(&BarrierCompletionCallbackImpl, 17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Owned(context), final_callback); 171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// A short bindable thunk that ensures a completion callback is always called 17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// after running an operation asynchronously. 17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void RunOperationAndCallback( 17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const Callback<int(const net::CompletionCallback&)>& operation, 17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const net::CompletionCallback& operation_callback) { 17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const int operation_result = operation.Run(operation_callback); 17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (operation_result != net::ERR_IO_PENDING) 18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) operation_callback.Run(operation_result); 18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void RecordIndexLoad(net::CacheType cache_type, 18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::TimeTicks constructed_since, 18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int result) { 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::TimeDelta creation_to_index = base::TimeTicks::Now() - 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) constructed_since; 18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (result == net::OK) { 18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SIMPLE_CACHE_UMA(TIMES, "CreationToIndex", cache_type, creation_to_index); 19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SIMPLE_CACHE_UMA(TIMES, 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) "CreationToIndexFail", cache_type, creation_to_index); 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass SimpleBackendImpl::ActiveEntryProxy 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : public SimpleEntryImpl::ActiveEntryProxy { 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ~ActiveEntryProxy() { 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (backend_) { 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(1U, backend_->active_entries_.count(entry_hash_)); 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci backend_->active_entries_.erase(entry_hash_); 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static scoped_ptr<SimpleEntryImpl::ActiveEntryProxy> Create( 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int64 entry_hash, 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SimpleBackendImpl* backend) { 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<SimpleEntryImpl::ActiveEntryProxy> 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci proxy(new ActiveEntryProxy(entry_hash, backend)); 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return proxy.Pass(); 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ActiveEntryProxy(uint64 entry_hash, 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SimpleBackendImpl* backend) 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : entry_hash_(entry_hash), 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci backend_(backend->AsWeakPtr()) {} 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint64 entry_hash_; 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtr<SimpleBackendImpl> backend_; 2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)SimpleBackendImpl::SimpleBackendImpl( 22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const FilePath& path, 22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int max_bytes, 22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) net::CacheType cache_type, 23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread, 23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) net::NetLog* net_log) 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : path_(path), 23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) cache_type_(cache_type), 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cache_thread_(cache_thread), 2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch orig_max_size_(max_bytes), 23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) entry_operations_mode_(cache_type == net::DISK_CACHE ? 23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SimpleEntryImpl::OPTIMISTIC_OPERATIONS : 23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SimpleEntryImpl::NON_OPTIMISTIC_OPERATIONS), 2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch net_log_(net_log) { 24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) MaybeHistogramFdLimit(cache_type_); 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SimpleBackendImpl::~SimpleBackendImpl() { 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) index_->WriteToDisk(); 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int SimpleBackendImpl::Init(const CompletionCallback& completion_callback) { 2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) MaybeCreateSequencedWorkerPool(); 2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) worker_pool_ = g_sequenced_worker_pool->GetTaskRunnerWithShutdownBehavior( 2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); 2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) index_.reset(new SimpleIndex( 25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::ThreadTaskRunnerHandle::Get(), 25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) this, 25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cache_type_, 25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) make_scoped_ptr(new SimpleIndexFile( 25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cache_thread_, worker_pool_.get(), cache_type_, path_)))); 25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) index_->ExecuteWhenReady( 26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&RecordIndexLoad, cache_type_, base::TimeTicks::Now())); 2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 262a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostTaskAndReplyWithResult( 2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cache_thread_.get(), 264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FROM_HERE, 26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind( 26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &SimpleBackendImpl::InitCacheStructureOnDisk, path_, orig_max_size_), 26703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&SimpleBackendImpl::InitializeIndex, 26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) AsWeakPtr(), 269a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) completion_callback)); 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return net::ERR_IO_PENDING; 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool SimpleBackendImpl::SetMaxSize(int max_bytes) { 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) orig_max_size_ = max_bytes; 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return index_->SetMaxSize(max_bytes); 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)int SimpleBackendImpl::GetMaxFileSize() const { 279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return index_->max_size() / kMaxFileRatio; 280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void SimpleBackendImpl::OnDoomStart(uint64 entry_hash) { 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(0u, entries_pending_doom_.count(entry_hash)); 28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) entries_pending_doom_.insert( 28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::make_pair(entry_hash, std::vector<Closure>())); 28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void SimpleBackendImpl::OnDoomComplete(uint64 entry_hash) { 2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(1u, entries_pending_doom_.count(entry_hash)); 29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::hash_map<uint64, std::vector<Closure> >::iterator it = 29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) entries_pending_doom_.find(entry_hash); 29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::vector<Closure> to_run_closures; 29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) to_run_closures.swap(it->second); 29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) entries_pending_doom_.erase(it); 29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::for_each(to_run_closures.begin(), to_run_closures.end(), 29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::mem_fun_ref(&Closure::Run)); 29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SimpleBackendImpl::DoomEntries(std::vector<uint64>* entry_hashes, 30168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const net::CompletionCallback& callback) { 30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<std::vector<uint64> > 30368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) mass_doom_entry_hashes(new std::vector<uint64>()); 30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) mass_doom_entry_hashes->swap(*entry_hashes); 30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 30668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::vector<uint64> to_doom_individually_hashes; 30768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // For each of the entry hashes, there are two cases: 30968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // 1. The entry is either open or pending doom, and so it should be doomed 31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // individually to avoid flakes. 31168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // 2. The entry is not in use at all, so we can call 31268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // SimpleSynchronousEntry::DoomEntrySet and delete the files en masse. 31368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (int i = mass_doom_entry_hashes->size() - 1; i >= 0; --i) { 31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const uint64 entry_hash = (*mass_doom_entry_hashes)[i]; 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(active_entries_.count(entry_hash) == 0 || 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci entries_pending_doom_.count(entry_hash) == 0); 31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!active_entries_.count(entry_hash) && 31868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) !entries_pending_doom_.count(entry_hash)) { 31968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) continue; 32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 32168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 32268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) to_doom_individually_hashes.push_back(entry_hash); 32368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 32468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) (*mass_doom_entry_hashes)[i] = mass_doom_entry_hashes->back(); 32568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) mass_doom_entry_hashes->resize(mass_doom_entry_hashes->size() - 1); 32668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) net::CompletionCallback barrier_callback = 32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) MakeBarrierCompletionCallback(to_doom_individually_hashes.size() + 1, 33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) callback); 33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (std::vector<uint64>::const_iterator 33268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) it = to_doom_individually_hashes.begin(), 33368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) end = to_doom_individually_hashes.end(); it != end; ++it) { 33468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const int doom_result = DoomEntryFromHash(*it, barrier_callback); 3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(net::ERR_IO_PENDING, doom_result); 33668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) index_->Remove(*it); 33768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 33868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 33968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (std::vector<uint64>::const_iterator it = mass_doom_entry_hashes->begin(), 34068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) end = mass_doom_entry_hashes->end(); 34168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) it != end; ++it) { 34268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) index_->Remove(*it); 34368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) OnDoomStart(*it); 34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 34668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Taking this pointer here avoids undefined behaviour from calling 34768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // base::Passed before mass_doom_entry_hashes.get(). 34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::vector<uint64>* mass_doom_entry_hashes_ptr = 34968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) mass_doom_entry_hashes.get(); 3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PostTaskAndReplyWithResult(worker_pool_.get(), 3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&SimpleSynchronousEntry::DoomEntrySet, 3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mass_doom_entry_hashes_ptr, 3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci path_), 3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&SimpleBackendImpl::DoomEntriesComplete, 3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AsWeakPtr(), 3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Passed(&mass_doom_entry_hashes), 3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci barrier_callback)); 35968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 36068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)net::CacheType SimpleBackendImpl::GetCacheType() const { 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return net::DISK_CACHE; 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 SimpleBackendImpl::GetEntryCount() const { 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(pasko): Use directory file count when index is not ready. 367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return index_->GetEntryCount(); 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SimpleBackendImpl::OpenEntry(const std::string& key, 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Entry** entry, 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback) { 37358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const uint64 entry_hash = simple_util::GetEntryHashKey(key); 37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 37558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // TODO(gavinp): Factor out this (not quite completely) repetitive code 37658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // block from OpenEntry/CreateEntry/DoomEntry. 37758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::hash_map<uint64, std::vector<Closure> >::iterator it = 37858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) entries_pending_doom_.find(entry_hash); 37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (it != entries_pending_doom_.end()) { 38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Callback<int(const net::CompletionCallback&)> operation = 38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&SimpleBackendImpl::OpenEntry, 38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Unretained(this), key, entry); 38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) it->second.push_back(base::Bind(&RunOperationAndCallback, 38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) operation, callback)); 38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return net::ERR_IO_PENDING; 38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_refptr<SimpleEntryImpl> simple_entry = 38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CreateOrFindActiveEntry(entry_hash, key); 389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CompletionCallback backend_callback = 390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&SimpleBackendImpl::OnEntryOpenedFromKey, 391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AsWeakPtr(), 392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch key, 393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch entry, 394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch simple_entry, 395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch callback); 396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return simple_entry->OpenEntry(entry, backend_callback); 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SimpleBackendImpl::CreateEntry(const std::string& key, 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Entry** entry, 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback) { 40258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK_LT(0u, key.size()); 40358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const uint64 entry_hash = simple_util::GetEntryHashKey(key); 40458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 40558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::hash_map<uint64, std::vector<Closure> >::iterator it = 40658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) entries_pending_doom_.find(entry_hash); 40758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (it != entries_pending_doom_.end()) { 40858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Callback<int(const net::CompletionCallback&)> operation = 40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&SimpleBackendImpl::CreateEntry, 41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Unretained(this), key, entry); 41158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) it->second.push_back(base::Bind(&RunOperationAndCallback, 41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) operation, callback)); 41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return net::ERR_IO_PENDING; 41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_refptr<SimpleEntryImpl> simple_entry = 41658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CreateOrFindActiveEntry(entry_hash, key); 417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return simple_entry->CreateEntry(entry, callback); 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SimpleBackendImpl::DoomEntry(const std::string& key, 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::CompletionCallback& callback) { 42258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const uint64 entry_hash = simple_util::GetEntryHashKey(key); 42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 42458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::hash_map<uint64, std::vector<Closure> >::iterator it = 42558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) entries_pending_doom_.find(entry_hash); 42658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (it != entries_pending_doom_.end()) { 42758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Callback<int(const net::CompletionCallback&)> operation = 42858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&SimpleBackendImpl::DoomEntry, base::Unretained(this), key); 42958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) it->second.push_back(base::Bind(&RunOperationAndCallback, 43058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) operation, callback)); 43158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return net::ERR_IO_PENDING; 43258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 43358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_refptr<SimpleEntryImpl> simple_entry = 43458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CreateOrFindActiveEntry(entry_hash, key); 43568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return simple_entry->DoomEntry(callback); 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SimpleBackendImpl::DoomAllEntries(const CompletionCallback& callback) { 439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DoomEntriesBetween(Time(), Time(), callback); 440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SimpleBackendImpl::IndexReadyForDoom(Time initial_time, 443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Time end_time, 444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CompletionCallback& callback, 445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int result) { 446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result != net::OK) { 447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback.Run(result); 448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<std::vector<uint64> > removed_key_hashes( 45168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) index_->GetEntriesBetween(initial_time, end_time).release()); 45268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DoomEntries(removed_key_hashes.get(), callback); 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SimpleBackendImpl::DoomEntriesBetween( 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Time initial_time, 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Time end_time, 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback) { 459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return index_->ExecuteWhenReady( 460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&SimpleBackendImpl::IndexReadyForDoom, AsWeakPtr(), 461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) initial_time, end_time, callback)); 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SimpleBackendImpl::DoomEntriesSince( 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Time initial_time, 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback) { 467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DoomEntriesBetween(initial_time, Time(), callback); 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass SimpleBackendImpl::SimpleIterator FINAL : public Iterator { 4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci explicit SimpleIterator(base::WeakPtr<SimpleBackendImpl> backend) 4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : backend_(backend), 4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_(this) { 4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // From Backend::Iterator: 4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual int OpenNextEntry(Entry** next_entry, 4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const CompletionCallback& callback) OVERRIDE { 4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CompletionCallback open_next_entry_impl = 4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&SimpleIterator::OpenNextEntryImpl, 4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_.GetWeakPtr(), next_entry, callback); 4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return backend_->index_->ExecuteWhenReady(open_next_entry_impl); 4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void OpenNextEntryImpl(Entry** next_entry, 4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const CompletionCallback& callback, 4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int index_initialization_error_code) { 4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!backend_) { 4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(net::ERR_FAILED); 4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (index_initialization_error_code != net::OK) { 4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(index_initialization_error_code); 4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!hashes_to_enumerate_) 4981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci hashes_to_enumerate_ = backend_->index()->GetAllHashes().Pass(); 4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci while (!hashes_to_enumerate_->empty()) { 5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint64 entry_hash = hashes_to_enumerate_->back(); 5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci hashes_to_enumerate_->pop_back(); 5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (backend_->index()->Has(entry_hash)) { 5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *next_entry = NULL; 5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CompletionCallback continue_iteration = base::Bind( 5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &SimpleIterator::CheckIterationReturnValue, 5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_.GetWeakPtr(), 5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci next_entry, 5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback); 5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int error_code_open = backend_->OpenEntryFromHash(entry_hash, 5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci next_entry, 5121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci continue_iteration); 5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (error_code_open == net::ERR_IO_PENDING) 5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (error_code_open != net::ERR_FAILED) { 5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(error_code_open); 5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(net::ERR_FAILED); 5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void CheckIterationReturnValue(Entry** entry, 5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const CompletionCallback& callback, 5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int error_code) { 5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (error_code == net::ERR_FAILED) { 5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OpenNextEntry(entry, callback); 5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(error_code); 5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtr<SimpleBackendImpl> backend_; 5361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<std::vector<uint64> > hashes_to_enumerate_; 5371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtrFactory<SimpleIterator> weak_factory_; 5381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 5391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<Backend::Iterator> SimpleBackendImpl::CreateIterator() { 5411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return scoped_ptr<Iterator>(new SimpleIterator(AsWeakPtr())); 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SimpleBackendImpl::GetStats( 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<std::pair<std::string, std::string> >* stats) { 546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::pair<std::string, std::string> item; 547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) item.first = "Cache type"; 548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) item.second = "Simple Cache"; 549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) stats->push_back(item); 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SimpleBackendImpl::OnExternalCacheHit(const std::string& key) { 5533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) index_->UseIfExists(simple_util::GetEntryHashKey(key)); 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 556a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void SimpleBackendImpl::InitializeIndex(const CompletionCallback& callback, 557a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const DiskStatResult& result) { 558a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (result.net_error == net::OK) { 559a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) index_->SetMaxSize(result.max_size); 560a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) index_->Initialize(result.cache_dir_mtime); 561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 562a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) callback.Run(result.net_error); 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 565a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)SimpleBackendImpl::DiskStatResult SimpleBackendImpl::InitCacheStructureOnDisk( 566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& path, 567a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) uint64 suggested_max_size) { 568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DiskStatResult result; 569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result.max_size = suggested_max_size; 570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result.net_error = net::OK; 571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!FileStructureConsistent(path)) { 572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Simple Cache Backend: wrong file structure on disk: " 573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << path.LossyDisplayName(); 574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result.net_error = net::ERR_FAILED; 575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 57658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool mtime_result = 57758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) disk_cache::simple_util::GetMTime(path, &result.cache_dir_mtime); 57858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(mtime_result); 579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!result.max_size) { 580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int64 available = base::SysInfo::AmountOfFreeDiskSpace(path); 581f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) result.max_size = disk_cache::PreferredCacheSize(available); 582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 583a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(result.max_size); 584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return result; 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_refptr<SimpleEntryImpl> SimpleBackendImpl::CreateOrFindActiveEntry( 58958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const uint64 entry_hash, 590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& key) { 59158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK_EQ(entry_hash, simple_util::GetEntryHashKey(key)); 592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::pair<EntryMap::iterator, bool> insert_result = 5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci active_entries_.insert(EntryMap::value_type(entry_hash, NULL)); 594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EntryMap::iterator& it = insert_result.first; 5951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const bool did_insert = insert_result.second; 5961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (did_insert) { 5971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SimpleEntryImpl* entry = it->second = 5981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new SimpleEntryImpl(cache_type_, path_, entry_hash, 5991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci entry_operations_mode_,this, net_log_); 6002385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch entry->SetKey(key); 6011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci entry->SetActiveEntryProxy(ActiveEntryProxy::Create(entry_hash, this)); 602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(it->second); 604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // It's possible, but unlikely, that we have an entry hash collision with a 605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // currently active entry. 606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (key != it->second->key()) { 607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) it->second->Doom(); 608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(0U, active_entries_.count(entry_hash)); 60958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return CreateOrFindActiveEntry(entry_hash, key); 610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 6111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return make_scoped_refptr(it->second); 6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 61468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int SimpleBackendImpl::OpenEntryFromHash(uint64 entry_hash, 615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Entry** entry, 616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const CompletionCallback& callback) { 61768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::hash_map<uint64, std::vector<Closure> >::iterator it = 61868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entries_pending_doom_.find(entry_hash); 61968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (it != entries_pending_doom_.end()) { 62068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Callback<int(const net::CompletionCallback&)> operation = 62168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&SimpleBackendImpl::OpenEntryFromHash, 62268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Unretained(this), entry_hash, entry); 62368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) it->second.push_back(base::Bind(&RunOperationAndCallback, 62468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) operation, callback)); 62568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return net::ERR_IO_PENDING; 62668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 62768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 62868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) EntryMap::iterator has_active = active_entries_.find(entry_hash); 62968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (has_active != active_entries_.end()) { 630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return OpenEntry(has_active->second->key(), entry, callback); 63168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 63358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_refptr<SimpleEntryImpl> simple_entry = new SimpleEntryImpl( 63468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) cache_type_, path_, entry_hash, entry_operations_mode_, this, net_log_); 635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CompletionCallback backend_callback = 636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&SimpleBackendImpl::OnEntryOpenedFromHash, 63768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) AsWeakPtr(), entry_hash, entry, simple_entry, callback); 638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return simple_entry->OpenEntry(entry, backend_callback); 639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 64168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int SimpleBackendImpl::DoomEntryFromHash(uint64 entry_hash, 64268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const CompletionCallback& callback) { 64368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Entry** entry = new Entry*(); 64468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<Entry*> scoped_entry(entry); 64568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::hash_map<uint64, std::vector<Closure> >::iterator pending_it = 64768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entries_pending_doom_.find(entry_hash); 6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pending_it != entries_pending_doom_.end()) { 64968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Callback<int(const net::CompletionCallback&)> operation = 65068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&SimpleBackendImpl::DoomEntryFromHash, 65168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Unretained(this), entry_hash); 6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pending_it->second.push_back(base::Bind(&RunOperationAndCallback, 65368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) operation, callback)); 65468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return net::ERR_IO_PENDING; 65568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 65668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 65768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) EntryMap::iterator active_it = active_entries_.find(entry_hash); 65868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (active_it != active_entries_.end()) 65968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return active_it->second->DoomEntry(callback); 66068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 66168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // There's no pending dooms, nor any open entry. We can make a trivial 66268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // call to DoomEntries() to delete this entry. 66368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::vector<uint64> entry_hash_vector; 66468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entry_hash_vector.push_back(entry_hash); 66568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DoomEntries(&entry_hash_vector, callback); 66668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return net::ERR_IO_PENDING; 66768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 66868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SimpleBackendImpl::OnEntryOpenedFromHash( 670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint64 hash, 671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Entry** entry, 6721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<SimpleEntryImpl>& simple_entry, 673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const CompletionCallback& callback, 674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int error_code) { 675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (error_code != net::OK) { 67658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) callback.Run(error_code); 677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(*entry); 680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::pair<EntryMap::iterator, bool> insert_result = 6811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci active_entries_.insert(EntryMap::value_type(hash, simple_entry.get())); 682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EntryMap::iterator& it = insert_result.first; 683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const bool did_insert = insert_result.second; 684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (did_insert) { 6851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // There was no active entry corresponding to this hash. We've already put 6861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the entry opened from hash in the |active_entries_|. We now provide the 6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // proxy object to the entry. 6881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it->second->SetActiveEntryProxy(ActiveEntryProxy::Create(hash, this)); 6891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(net::OK); 690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 6911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The entry was made active while we waiting for the open from hash to 6921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // finish. The entry created from hash needs to be closed, and the one 6931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // in |active_entries_| can be returned to the caller. 694eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch simple_entry->Close(); 695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it->second->OpenEntry(entry, callback); 696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SimpleBackendImpl::OnEntryOpenedFromKey( 700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string key, 701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Entry** entry, 7021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<SimpleEntryImpl>& simple_entry, 703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const CompletionCallback& callback, 704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int error_code) { 705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int final_code = error_code; 706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (final_code == net::OK) { 7077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool key_matches = key.compare(simple_entry->key()) == 0; 7087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!key_matches) { 7097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(clamy): Add a unit test to check this code path. 710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DLOG(WARNING) << "Key mismatch on open."; 711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch simple_entry->Doom(); 712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch simple_entry->Close(); 713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch final_code = net::ERR_FAILED; 714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_EQ(simple_entry->entry_hash(), simple_util::GetEntryHashKey(key)); 716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 71758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SIMPLE_CACHE_UMA(BOOLEAN, "KeyMatchedOnOpen", cache_type_, key_matches); 718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 71958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) callback.Run(final_code); 720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 72268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SimpleBackendImpl::DoomEntriesComplete( 72368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<std::vector<uint64> > entry_hashes, 72468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const net::CompletionCallback& callback, 72568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int result) { 72668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::for_each( 72768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entry_hashes->begin(), entry_hashes->end(), 72868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::bind1st(std::mem_fun(&SimpleBackendImpl::OnDoomComplete), 72968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this)); 73068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) callback.Run(result); 73168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 73268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 73358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void SimpleBackendImpl::FlushWorkerPoolForTesting() { 73458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (g_sequenced_worker_pool) 73558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) g_sequenced_worker_pool->FlushForTesting(); 736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace disk_cache 739