summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrvargas@chromium.org <rvargas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-30 17:49:48 +0000
committerrvargas@chromium.org <rvargas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-30 17:49:48 +0000
commitb851da9d3d378df04225d39ea44502742c73c20f (patch)
tree75926f3dd54b06e16f8fd97a856aed89ab3e8817 /net
parent6042bccc5aa73335796043eb35a5f2a76f3addf1 (diff)
downloadchromium_src-b851da9d3d378df04225d39ea44502742c73c20f.zip
chromium_src-b851da9d3d378df04225d39ea44502742c73c20f.tar.gz
chromium_src-b851da9d3d378df04225d39ea44502742c73c20f.tar.bz2
Http cache: disable the infinite cache simulation and perform cleanup of local data.
BUG=147383 TEST=none Review URL: https://chromiumcodereview.appspot.com/13000003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191528 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/http/http_cache.cc21
-rw-r--r--net/http/http_cache.h7
-rw-r--r--net/http/http_cache_transaction.cc29
-rw-r--r--net/http/http_cache_transaction.h4
-rw-r--r--net/http/infinite_cache.cc1189
-rw-r--r--net/http/infinite_cache.h121
-rw-r--r--net/http/infinite_cache_unittest.cc276
-rw-r--r--net/net.gyp3
8 files changed, 16 insertions, 1634 deletions
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index ab9a0bb..a2a9dfc 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -15,6 +15,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
+#include "base/file_util.h"
#include "base/format_macros.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
@@ -25,6 +26,7 @@
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
+#include "base/threading/worker_pool.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -38,6 +40,15 @@
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
+namespace {
+
+// Adaptor to delete a file on a worker thread.
+void DeletePath(base::FilePath path) {
+ file_util::Delete(path, false);
+}
+
+} // namespace
+
namespace net {
HttpCache::DefaultBackend::DefaultBackend(CacheType type,
@@ -356,7 +367,7 @@ void HttpCache::WriteMetadata(const GURL& url,
}
HttpCache::Transaction* trans =
- new HttpCache::Transaction(priority, this, NULL, NULL);
+ new HttpCache::Transaction(priority, this, NULL);
MetadataWriter* writer = new MetadataWriter(trans);
// The writer will self destruct when done.
@@ -394,8 +405,7 @@ void HttpCache::OnExternalCacheHit(const GURL& url,
void HttpCache::InitializeInfiniteCache(const base::FilePath& path) {
if (base::FieldTrialList::FindFullName("InfiniteCache") != "Yes")
return;
- // To be enabled after everything is fully wired.
- infinite_cache_.Init(path);
+ base::WorkerPool::PostTask(FROM_HERE, base::Bind(&DeletePath, path), true);
}
int HttpCache::CreateTransaction(RequestPriority priority,
@@ -407,10 +417,7 @@ int HttpCache::CreateTransaction(RequestPriority priority,
CreateBackend(NULL, net::CompletionCallback());
}
- InfiniteCacheTransaction* infinite_cache_transaction =
- infinite_cache_.CreateInfiniteCacheTransaction();
- trans->reset(new HttpCache::Transaction(priority, this, delegate,
- infinite_cache_transaction));
+ trans->reset(new HttpCache::Transaction(priority, this, delegate));
return OK;
}
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index 92dbee1..9e6b73c 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -33,7 +33,6 @@
#include "net/base/request_priority.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
-#include "net/http/infinite_cache.h"
class GURL;
@@ -188,9 +187,6 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
// Initializes the Infinite Cache, if selected by the field trial.
void InitializeInfiniteCache(const base::FilePath& path);
- // Returns a pointer to the Infinite Cache.
- InfiniteCache* infinite_cache() { return &infinite_cache_; }
-
// HttpTransactionFactory implementation:
virtual int CreateTransaction(RequestPriority priority,
scoped_ptr<HttpTransaction>* trans,
@@ -217,7 +213,6 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
class Transaction;
class WorkItem;
friend class Transaction;
- friend class InfiniteCache;
struct PendingOp; // Info for an entry under construction.
typedef std::list<Transaction*> TransactionList;
@@ -399,8 +394,6 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
scoped_ptr<PlaybackCacheMap> playback_cache_map_;
- InfiniteCache infinite_cache_;
-
DISALLOW_COPY_AND_ASSIGN(HttpCache);
};
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 5ecdb47..fce6bac 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -129,8 +129,7 @@ static bool HeaderMatches(const HttpRequestHeaders& headers,
HttpCache::Transaction::Transaction(
RequestPriority priority,
HttpCache* cache,
- HttpTransactionDelegate* transaction_delegate,
- InfiniteCacheTransaction* infinite_cache_transaction)
+ HttpTransactionDelegate* transaction_delegate)
: next_state_(STATE_NONE),
request_(NULL),
priority_(priority),
@@ -138,7 +137,6 @@ HttpCache::Transaction::Transaction(
entry_(NULL),
new_entry_(NULL),
network_trans_(NULL),
- infinite_cache_transaction_(infinite_cache_transaction),
new_response_(NULL),
mode_(NONE),
target_state_(STATE_NONE),
@@ -236,9 +234,6 @@ bool HttpCache::Transaction::AddTruncatedFlag() {
if (done_reading_)
return true;
- if (infinite_cache_transaction_.get())
- infinite_cache_transaction_->OnTruncatedResponse();
-
truncated_ = true;
target_state_ = STATE_NONE;
next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
@@ -274,20 +269,6 @@ int HttpCache::Transaction::Start(const HttpRequestInfo* request,
return ERR_UNEXPECTED;
SetRequest(net_log, request);
- if (infinite_cache_transaction_.get()) {
- if ((effective_load_flags_ & LOAD_BYPASS_CACHE) ||
- (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) ||
- (effective_load_flags_ & LOAD_DISABLE_CACHE) ||
- (effective_load_flags_ & LOAD_VALIDATE_CACHE) ||
- (effective_load_flags_ & LOAD_PREFERRING_CACHE) ||
- partial_.get()) {
- if (effective_load_flags_ & LOAD_PREFERRING_CACHE)
- infinite_cache_transaction_->OnBackForwardNavigation();
- infinite_cache_transaction_.reset();
- } else {
- infinite_cache_transaction_->OnRequestStart(request);
- }
- }
// We have to wait until the backend is initialized so we start the SM.
next_state_ = STATE_GET_BACKEND;
@@ -862,8 +843,6 @@ int HttpCache::Transaction::DoSendRequestComplete(int result) {
int HttpCache::Transaction::DoSuccessfulSendRequest() {
DCHECK(!new_response_);
const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
- if (infinite_cache_transaction_.get())
- infinite_cache_transaction_->OnResponseReceived(new_response);
if (new_response->headers->response_code() == 401 ||
new_response->headers->response_code() == 407) {
@@ -947,9 +926,6 @@ int HttpCache::Transaction::DoNetworkReadComplete(int result) {
if (!cache_)
return ERR_UNEXPECTED;
- if (infinite_cache_transaction_.get())
- infinite_cache_transaction_->OnDataRead(read_buf_->data(), result);
-
// If there is an error or we aren't saving the data, we are done; just wait
// until the destructor runs to see if we can keep the data.
if (mode_ == NONE || result < 0)
@@ -1508,9 +1484,6 @@ int HttpCache::Transaction::DoCacheReadData() {
DCHECK(entry_);
next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
- if (infinite_cache_transaction_.get())
- infinite_cache_transaction_->OnServedFromCache(&response_);
-
if (net_log_.IsLoggingAllEvents())
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA);
ReportCacheActionStart();
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index e5365c4..a5ddfcd 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -60,8 +60,7 @@ class HttpCache::Transaction : public HttpTransaction {
Transaction(RequestPriority priority,
HttpCache* cache,
- HttpTransactionDelegate* transaction_delegate,
- InfiniteCacheTransaction* infinite_cache_transaction);
+ HttpTransactionDelegate* transaction_delegate);
virtual ~Transaction();
Mode mode() const { return mode_; }
@@ -399,7 +398,6 @@ class HttpCache::Transaction : public HttpTransaction {
HttpCache::ActiveEntry* entry_;
HttpCache::ActiveEntry* new_entry_;
scoped_ptr<HttpTransaction> network_trans_;
- scoped_ptr<InfiniteCacheTransaction> infinite_cache_transaction_;
CompletionCallback callback_; // Consumer's callback.
HttpResponseInfo response_;
HttpResponseInfo auth_response_;
diff --git a/net/http/infinite_cache.cc b/net/http/infinite_cache.cc
deleted file mode 100644
index f8a710b..0000000
--- a/net/http/infinite_cache.cc
+++ /dev/null
@@ -1,1189 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/http/infinite_cache.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/compiler_specific.h"
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/hash.h"
-#include "base/hash_tables.h"
-#include "base/location.h"
-#include "base/memory/ref_counted.h"
-#include "base/metrics/histogram.h"
-#include "base/pickle.h"
-#include "base/platform_file.h"
-#include "base/rand_util.h"
-#include "base/sha1.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "base/time.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_cache_transaction.h"
-#include "net/http/http_request_info.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_response_info.h"
-#include "net/http/http_util.h"
-#include "third_party/zlib/zlib.h"
-
-using base::PlatformFile;
-using base::Time;
-using base::TimeDelta;
-
-namespace {
-
-// Flags to use with a particular resource.
-enum Flags {
- NO_CACHE = 1 << 0,
- NO_STORE = 1 << 1,
- EXPIRED = 1 << 2,
- TRUNCATED = 1 << 3,
- RESUMABLE = 1 << 4,
- REVALIDATEABLE = 1 << 5,
- DOOM_METHOD = 1 << 6,
- CACHED = 1 << 7,
- GA_JS_HTTP = 1 << 8,
- GA_JS_HTTPS = 1 << 9,
-};
-
-const char kGaJsHttpUrl[] = "http://www.google-analytics.com/ga.js";
-const char kGaJsHttpsUrl[] = "https://ssl.google-analytics.com/ga.js";
-
-const int kKeySizeBytes = 20;
-COMPILE_ASSERT(base::kSHA1Length == static_cast<unsigned>(kKeySizeBytes),
- invalid_key_length);
-struct Key {
- char value[kKeySizeBytes];
-};
-
-// The actual data that we store for every resource.
-struct Details {
- int32 expiration;
- int32 last_access;
- uint16 flags;
- uint8 use_count;
- uint8 update_count;
- uint32 vary_hash;
- int32 headers_size;
- int32 response_size;
- uint32 headers_hash;
- uint32 response_hash;
-};
-const size_t kRecordSize = sizeof(Key) + sizeof(Details);
-
-// Some constants related to the database file.
-uint32 kMagicSignature = 0x1f00cace;
-uint32 kCurrentVersion = 0x10002;
-
-// Basic limits for the experiment.
-int kMaxNumEntries = 500 * 1000;
-int kMaxTrackingSize = 40 * 1024 * 1024;
-
-// Settings that control how we generate histograms.
-int kTimerMinutes = 5;
-int kReportSizeStep = 100 * 1024 * 1024;
-
-// Buffer to read and write the file.
-const size_t kBufferSize = 1024 * 1024;
-const size_t kMaxRecordsToRead = kBufferSize / kRecordSize;
-COMPILE_ASSERT(kRecordSize * kMaxRecordsToRead < kBufferSize, wrong_buffer);
-
-// Functor for operator <.
-struct Key_less {
- bool operator()(const Key& left, const Key& right) const {
- // left < right.
- return (memcmp(left.value, right.value, kKeySizeBytes) < 0);
- }
-};
-
-// Functor for operator ==.
-struct Key_eq {
- bool operator()(const Key& left, const Key& right) const {
- return (memcmp(left.value, right.value, kKeySizeBytes) == 0);
- }
-};
-
-// Simple adaptor for the sha1 interface.
-void CryptoHash(std::string source, Key* destination) {
- base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(source.data()),
- source.size(),
- reinterpret_cast<unsigned char*>(destination->value));
-}
-
-// Simple adaptor for base::ReadPlatformFile.
-bool ReadPlatformFile(PlatformFile file, size_t offset,
- void* buffer, size_t buffer_len) {
- DCHECK_LE(offset, static_cast<size_t>(kuint32max));
- int bytes = base::ReadPlatformFile(file, static_cast<int64>(offset),
- reinterpret_cast<char*>(buffer),
- static_cast<int>(buffer_len));
- return (bytes == static_cast<int>(buffer_len));
-}
-
-// Simple adaptor for base::WritePlatformFile.
-bool WritePlatformFile(PlatformFile file, size_t offset,
- const void* buffer, size_t buffer_len) {
- DCHECK_LE(offset, static_cast<size_t>(kuint32max));
- int bytes = base::WritePlatformFile(file, static_cast<int64>(offset),
- reinterpret_cast<const char*>(buffer),
- static_cast<int>(buffer_len));
- return (bytes == static_cast<int>(buffer_len));
-}
-
-// 1 second resolution, +- 68 years from the baseline.
-int32 TimeToInt(Time time) {
- int64 seconds = (time - Time::UnixEpoch()).InSeconds();
- if (seconds > kint32max)
- seconds = kint32max;
- if (seconds < kint32min)
- seconds = kint32min;
- return static_cast<int32>(seconds);
-}
-
-Time IntToTime(int32 time) {
- return Time::UnixEpoch() + TimeDelta::FromSeconds(time);
-}
-
-int32 GetExpiration(const net::HttpResponseInfo* response) {
- TimeDelta freshness =
- response->headers->GetFreshnessLifetime(response->response_time);
-
- // Avoid overflow when adding to current time.
- if (freshness.InDays() > 365 * 10)
- freshness = TimeDelta::FromDays(365 * 10);
- return TimeToInt(response->response_time + freshness);
-}
-
-uint32 GetCacheability(const net::HttpResponseInfo* response) {
- uint32 cacheability = 0;
- const net::HttpResponseHeaders* headers = response->headers;
- if (headers->HasHeaderValue("cache-control", "no-cache") ||
- headers->HasHeaderValue("pragma", "no-cache") ||
- headers->HasHeaderValue("vary", "*")) {
- cacheability |= NO_CACHE;
- }
-
- if (headers->HasHeaderValue("cache-control", "no-store"))
- cacheability |= NO_STORE;
-
- TimeDelta max_age;
- if (headers->GetMaxAgeValue(&max_age) && max_age.InSeconds() <= 0)
- cacheability |= NO_CACHE;
-
- return cacheability;
-}
-
-uint32 GetRevalidationFlags(const net::HttpResponseInfo* response) {
- uint32 revalidation = 0;
- std::string etag;
- response->headers->EnumerateHeader(NULL, "etag", &etag);
-
- std::string last_modified;
- response->headers->EnumerateHeader(NULL, "last-modified", &last_modified);
-
- if (!etag.empty() || !last_modified.empty())
- revalidation = REVALIDATEABLE;
-
- if (response->headers->HasStrongValidators())
- revalidation = RESUMABLE;
-
- return revalidation;
-}
-
-
-uint32 GetVaryHash(const net::HttpResponseInfo* response) {
- if (!response->vary_data.is_valid())
- return 0;
-
- uint32 hash = adler32(0, Z_NULL, 0);
- Pickle pickle;
- response->vary_data.Persist(&pickle);
- return adler32(hash, reinterpret_cast<const Bytef*>(pickle.data()),
- pickle.size());
-}
-
-// Adaptor for PostTaskAndReply.
-void OnComplete(const net::CompletionCallback& callback, int* result) {
- callback.Run(*result);
-}
-
-#define CACHE_COUNT_HISTOGRAM(name, count) \
- UMA_HISTOGRAM_CUSTOM_COUNTS(name, count, 0, kuint8max, 25)
-
-} // namespace
-
-namespace BASE_HASH_NAMESPACE {
-#if defined(COMPILER_MSVC)
-inline size_t hash_value(const Key& key) {
- return base::Hash(key.value, kKeySizeBytes);
-}
-#elif defined(COMPILER_GCC)
-template <>
-struct hash<Key> {
- size_t operator()(const Key& key) const {
- return base::Hash(key.value, kKeySizeBytes);
- }
-};
-#endif
-
-} // BASE_HASH_NAMESPACE
-
-namespace net {
-
-struct InfiniteCacheTransaction::ResourceData {
- ResourceData() {
- memset(this, 0, sizeof(*this));
- }
-
- Key key;
- Details details;
-};
-
-InfiniteCacheTransaction::InfiniteCacheTransaction(InfiniteCache* cache)
- : cache_(cache->AsWeakPtr()) {
-}
-
-InfiniteCacheTransaction::~InfiniteCacheTransaction() {
- Finish();
-}
-
-void InfiniteCacheTransaction::OnRequestStart(const HttpRequestInfo* request) {
- if (!cache_)
- return;
-
- std::string method = request->method;
- resource_data_.reset(new ResourceData);
- if (method == "POST" || method == "DELETE" || method == "PUT") {
- resource_data_->details.flags |= DOOM_METHOD;
- } else if (method != "GET") {
- cache_.reset();
- return;
- }
- const std::string cache_key = cache_->GenerateKey(request);
- if (cache_key == kGaJsHttpUrl) {
- resource_data_->details.flags |= GA_JS_HTTP;
- } else if (cache_key == kGaJsHttpsUrl) {
- resource_data_->details.flags |= GA_JS_HTTPS;
- }
-
- CryptoHash(cache_key, &resource_data_->key);
-}
-
-void InfiniteCacheTransaction::OnBackForwardNavigation() {
- if (!cache_)
- return;
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.BackForwardNavigation", true);
-}
-
-void InfiniteCacheTransaction::OnResponseReceived(
- const HttpResponseInfo* response) {
- if (!cache_)
- return;
-
- Details& details = resource_data_->details;
-
- // Store the old flag values that we want to preserve.
- const uint32 kPreserveFlagsBitMask = (GA_JS_HTTP | GA_JS_HTTPS | DOOM_METHOD);
- uint32 old_flag_values = details.flags & kPreserveFlagsBitMask;
-
- details.expiration = GetExpiration(response);
- details.last_access = TimeToInt(response->request_time);
- details.flags = GetCacheability(response);
- details.vary_hash = GetVaryHash(response);
- details.response_hash = adler32(0, Z_NULL, 0); // Init the hash.
-
- if (!details.flags &&
- TimeToInt(response->response_time) == details.expiration) {
- details.flags = EXPIRED;
- }
-
- // Restore the old flag values we wanted to preserve.
- details.flags |= old_flag_values;
-
- details.flags |= GetRevalidationFlags(response);
-
- Pickle pickle;
- response->Persist(&pickle, true, false); // Skip transient headers.
- details.headers_size = pickle.size();
- details.headers_hash = adler32(0, Z_NULL, 0);
- details.headers_hash = adler32(details.headers_hash,
- reinterpret_cast<const Bytef*>(pickle.data()),
- pickle.size());
-}
-
-void InfiniteCacheTransaction::OnDataRead(const char* data, int data_len) {
- if (!cache_)
- return;
-
- if (!data_len)
- return Finish();
-
- if (data_len < 0)
- return OnTruncatedResponse();
-
- resource_data_->details.response_size += data_len;
-
- resource_data_->details.response_hash =
- adler32(resource_data_->details.response_hash,
- reinterpret_cast<const Bytef*>(data), data_len);
-}
-
-void InfiniteCacheTransaction::OnTruncatedResponse() {
- if (!cache_)
- return;
-
- resource_data_->details.flags |= TRUNCATED;
-}
-
-void InfiniteCacheTransaction::OnServedFromCache(
- const HttpResponseInfo* response) {
- if (!cache_)
- return;
-
- resource_data_->details.flags |= CACHED;
- if (!resource_data_->details.last_access) {
- OnResponseReceived(response);
- // For cached responses, the request time is the last revalidation time.
- resource_data_->details.last_access = TimeToInt(Time::Now());
- }
-}
-
-void InfiniteCacheTransaction::Finish() {
- if (!cache_ || !resource_data_.get())
- return;
-
- if (!resource_data_->details.headers_size)
- return;
-
- cache_->ProcessResource(resource_data_.Pass());
- cache_.reset();
-}
-
-// ----------------------------------------------------------------------------
-
-// This is the object that performs the bulk of the work.
-// InfiniteCacheTransaction posts the transaction data to the InfiniteCache, and
-// the InfiniteCache basically just forward requests to the Worker for actual
-// processing.
-// The Worker lives on a worker thread (basically a dedicated worker pool with
-// only one thread), and flushes data to disk once every five minutes, when it
-// is notified by the InfiniteCache.
-// In general, there are no callbacks on completion of tasks, and the Worker can
-// be as behind as it has to when processing requests.
-class InfiniteCache::Worker : public base::RefCountedThreadSafe<Worker> {
- public:
- Worker() : init_(false), flushed_(false) {}
-
- // Construction and destruction helpers.
- void Init(const base::FilePath& path);
- void Cleanup();
-
- // Deletes all tracked data.
- void DeleteData(int* result);
-
- // Deletes requests between |initial_time| and |end_time|.
- void DeleteDataBetween(base::Time initial_time,
- base::Time end_time,
- int* result);
-
- // Performs the actual processing of a new transaction. Takes ownership of
- // the transaction |data|.
- void Process(scoped_ptr<InfiniteCacheTransaction::ResourceData> data);
-
- // Test helpers.
- void Query(int* result);
- void Flush(int* result);
-
- // Timer notification.
- void OnTimer();
-
- private:
- friend class base::RefCountedThreadSafe<Worker>;
-#if defined(COMPILER_MSVC)
- typedef BASE_HASH_NAMESPACE::hash_map<
- Key, Details, BASE_HASH_NAMESPACE::hash_compare<Key, Key_less> > KeyMap;
-#elif defined(COMPILER_GCC)
- typedef BASE_HASH_NAMESPACE::hash_map<
- Key, Details, BASE_HASH_NAMESPACE::hash<Key>, Key_eq> KeyMap;
-#endif
-
- // Header for the data file. The file starts with the header, followed by
- // all the records, and a data hash at the end (just of the records, not the
- // header). Note that the header has a dedicated hash.
- struct Header {
- uint32 magic;
- uint32 version;
- int32 num_entries;
- int32 generation;
- uint64 creation_time;
- uint64 update_time;
- int64 total_size;
- int64 size_last_report;
- int32 use_minutes;
- int32 num_hits;
- int32 num_bad_hits;
- int32 num_requests;
- int32 disabled;
- uint32 header_hash;
- };
-
- ~Worker() {}
-
- // Methods to load and store data on disk.
- void LoadData();
- void StoreData();
- void InitializeData();
- bool ReadData(PlatformFile file);
- bool WriteData(PlatformFile file);
- bool ReadAndVerifyHeader(PlatformFile file);
-
- // Book-keeping methods.
- void Add(const Details& details);
- void Remove(const Details& details);
- void UpdateSize(int old_size, int new_size);
-
- // Bulk of report generation methods.
- void RecordHit(const Details& old, Details* details);
- void RecordUpdate(const Details& old, Details* details);
- void RecordComparison(bool infinite_used_or_validated,
- bool http_used_or_validated) const;
- void GenerateHistograms();
-
- // Cache logic methods.
- bool CanReuse(const Details& old, const Details& current);
- bool DataChanged(const Details& old, const Details& current);
- bool HeadersChanged(const Details& old, const Details& current);
-
- KeyMap map_;
- bool init_;
- bool flushed_;
- scoped_ptr<Header> header_;
- base::FilePath path_;
-
- DISALLOW_COPY_AND_ASSIGN(Worker);
-};
-
-void InfiniteCache::Worker::Init(const base::FilePath& path) {
- path_ = path;
- LoadData();
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.NewSession", true);
-}
-
-void InfiniteCache::Worker::Cleanup() {
- if (init_)
- StoreData();
-
- map_.clear();
-}
-
-void InfiniteCache::Worker::DeleteData(int* result) {
- if (!init_)
- return;
-
- map_.clear();
- InitializeData();
- file_util::Delete(path_, false);
- *result = OK;
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.DeleteAll", true);
-}
-
-void InfiniteCache::Worker::DeleteDataBetween(base::Time initial_time,
- base::Time end_time,
- int* result) {
- if (!init_)
- return;
-
- for (KeyMap::iterator i = map_.begin(); i != map_.end();) {
- Time last_access = IntToTime(i->second.last_access);
- if (last_access >= initial_time && last_access <= end_time) {
- KeyMap::iterator next = i;
- ++next;
- Remove(i->second);
- map_.erase(i);
- i = next;
- continue;
- }
- ++i;
- }
-
- file_util::Delete(path_, false);
- StoreData();
- *result = OK;
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.DeleteRange", true);
-}
-
-void InfiniteCache::Worker::Process(
- scoped_ptr<InfiniteCacheTransaction::ResourceData> data) {
- if (!init_)
- return;
-
- if (data->details.response_size > kMaxTrackingSize)
- return;
-
- if (header_->num_entries == kMaxNumEntries || header_->disabled)
- return;
-
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.TotalRequests", true);
- if (data->details.flags & NO_STORE)
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.NoStore", true);
-
- if (data->details.flags & (GA_JS_HTTP | GA_JS_HTTPS)) {
- bool https = data->details.flags & GA_JS_HTTPS ? true : false;
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.GaJs_Https", https);
- }
-
- // True if the first range of the http request was validated or used
- // unconditionally, false if it was not found in the cache, was updated,
- // or was found but was unconditionalizable.
- bool http_used_or_validated = (data->details.flags & CACHED) == CACHED;
-
- header_->num_requests++;
- KeyMap::iterator i = map_.find(data->key);
- if (i != map_.end()) {
- if (data->details.flags & DOOM_METHOD) {
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.DoomMethodHit", true);
- Remove(i->second);
- map_.erase(i);
- return;
- }
- data->details.use_count = i->second.use_count;
- data->details.update_count = i->second.update_count;
- bool reused = CanReuse(i->second, data->details);
- bool data_changed = DataChanged(i->second, data->details);
- bool headers_changed = HeadersChanged(i->second, data->details);
-
- RecordComparison(reused, http_used_or_validated);
-
- if (reused && data_changed)
- header_->num_bad_hits++;
-
- if (reused)
- RecordHit(i->second, &data->details);
-
- if (headers_changed)
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.HeadersChange", true);
-
- if (data_changed)
- RecordUpdate(i->second, &data->details);
-
- if (data->details.flags & NO_STORE) {
- Remove(i->second);
- map_.erase(i);
- return;
- }
-
- map_[data->key] = data->details;
- return;
- } else {
- RecordComparison(false, http_used_or_validated);
- }
-
- if (data->details.flags & NO_STORE)
- return;
-
- if (data->details.flags & DOOM_METHOD) {
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.DoomMethodHit", false);
- return;
- }
-
- map_[data->key] = data->details;
- Add(data->details);
-}
-
-void InfiniteCache::Worker::LoadData() {
- if (path_.empty())
- return InitializeData();
-
- PlatformFile file = base::CreatePlatformFile(
- path_, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL, NULL);
- if (file == base::kInvalidPlatformFileValue)
- return InitializeData();
- if (!ReadData(file))
- InitializeData();
- base::ClosePlatformFile(file);
- if (header_->disabled) {
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.Full", true);
- InitializeData();
- }
-}
-
-void InfiniteCache::Worker::StoreData() {
- if (!init_ || flushed_ || path_.empty())
- return;
-
- header_->update_time = Time::Now().ToInternalValue();
- header_->generation++;
- header_->header_hash = base::Hash(
- reinterpret_cast<char*>(header_.get()), offsetof(Header, header_hash));
-
- base::FilePath temp_file = path_.ReplaceExtension(FILE_PATH_LITERAL("tmp"));
- PlatformFile file = base::CreatePlatformFile(
- temp_file, base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
- NULL, NULL);
- if (file == base::kInvalidPlatformFileValue)
- return;
- bool success = WriteData(file);
- base::ClosePlatformFile(file);
- if (success) {
- if (!file_util::ReplaceFile(temp_file, path_))
- file_util::Delete(temp_file, false);
- } else {
- LOG(ERROR) << "Failed to write experiment data";
- }
-}
-
-void InfiniteCache::Worker::InitializeData() {
- header_.reset(new Header);
- memset(header_.get(), 0, sizeof(Header));
- header_->magic = kMagicSignature;
- header_->version = kCurrentVersion;
- header_->creation_time = Time::Now().ToInternalValue();
- map_.clear();
-
- UMA_HISTOGRAM_BOOLEAN("InfiniteCache.Initialize", true);
- init_ = true;
-}
-
-bool InfiniteCache::Worker::ReadData(PlatformFile file) {
- if (!ReadAndVerifyHeader(file))
- return false;
-
- scoped_array<char> buffer(new char[kBufferSize]);
- size_t offset = sizeof(Header);
- uint32 hash = adler32(0, Z_NULL, 0);
-
- for (int remaining_records = header_->num_entries; remaining_records;) {
- int num_records = std::min(remaining_records,
- static_cast<int>(kMaxRecordsToRead));
- size_t num_bytes = num_records * kRecordSize;
- remaining_records -= num_records;
- if (!remaining_records)
- num_bytes += sizeof(uint32); // Trailing hash.
- DCHECK_LE(num_bytes, kBufferSize);
-
- if (!ReadPlatformFile(file, offset, buffer.get(), num_bytes))
- return false;
-
- hash = adler32(hash, reinterpret_cast<const Bytef*>(buffer.get()),
- num_records * kRecordSize);
- if (!remaining_records &&
- hash != *reinterpret_cast<uint32*>(buffer.get() +
- num_records * kRecordSize)) {
- return false;
- }
-
- for (int i = 0; i < num_records; i++) {
- char* record = buffer.get() + i * kRecordSize;
- Key key = *reinterpret_cast<Key*>(record);
- Details details = *reinterpret_cast<Details*>(record + sizeof(key));
- map_[key] = details;
- }
- offset += num_bytes;
- }
- if (header_->num_entries != static_cast<int>(map_.size())) {
- NOTREACHED();
- return false;
- }
-
- init_ = true;
- return true;
-}
-
-bool InfiniteCache::Worker::WriteData(PlatformFile file) {
- if (!base::TruncatePlatformFile(file, 0))
- return false;
-
- if (!WritePlatformFile(file, 0, header_.get(), sizeof(Header)))
- return false;
-
- scoped_array<char> buffer(new char[kBufferSize]);
- size_t offset = sizeof(Header);
- uint32 hash = adler32(0, Z_NULL, 0);
- int unused_entries = 0;
- static bool first_time = true;
-
- DCHECK_EQ(header_->num_entries, static_cast<int32>(map_.size()));
- KeyMap::iterator iterator = map_.begin();
- for (int remaining_records = header_->num_entries; remaining_records;) {
- int num_records = std::min(remaining_records,
- static_cast<int>(kMaxRecordsToRead));
- size_t num_bytes = num_records * kRecordSize;
- remaining_records -= num_records;
-
- for (int i = 0; i < num_records; i++) {
- if (iterator == map_.end()) {
- NOTREACHED();
- return false;
- }
- int use_count = iterator->second.use_count;
- if (!use_count)
- unused_entries++;
-
- if (first_time) {
- int response_size = iterator->second.response_size;
- if (response_size < 16 * 1024)
- CACHE_COUNT_HISTOGRAM("InfiniteCache.Reuse-16k", use_count);
- else if (response_size < 128 * 1024)
- CACHE_COUNT_HISTOGRAM("InfiniteCache.Reuse-128k", use_count);
- else if (response_size < 2048 * 1024)
- CACHE_COUNT_HISTOGRAM("InfiniteCache.Reuse-2M", use_count);
- else
- CACHE_COUNT_HISTOGRAM("InfiniteCache.Reuse-40M", use_count);
- }
-
- char* record = buffer.get() + i * kRecordSize;
- *reinterpret_cast<Key*>(record) = iterator->first;
- *reinterpret_cast<Details*>(record + sizeof(Key)) = iterator->second;
- ++iterator;
- }
-
- hash = adler32(hash, reinterpret_cast<const Bytef*>(buffer.get()),
- num_bytes);
-
- if (!remaining_records) {
- num_bytes += sizeof(uint32); // Trailing hash.
- *reinterpret_cast<uint32*>(buffer.get() +
- num_records * kRecordSize) = hash;
- }
-
- DCHECK_LE(num_bytes, kBufferSize);
- if (!WritePlatformFile(file, offset, buffer.get(), num_bytes))
- return false;
-
- offset += num_bytes;
- }
- base::FlushPlatformFile(file); // Ignore return value.
- first_time = false;
-
- if (header_->num_entries)
- unused_entries = unused_entries * 100 / header_->num_entries;
-
- UMA_HISTOGRAM_PERCENTAGE("InfiniteCache.UnusedEntries", unused_entries);
- UMA_HISTOGRAM_COUNTS("InfiniteCache.StoredEntries", header_->num_entries);
- if (base::RandInt(0, 99) < unused_entries) {
- UMA_HISTOGRAM_COUNTS("InfiniteCache.UnusedEntriesByStoredEntries",
- header_->num_entries);
- }
- return true;
-}
-
-bool InfiniteCache::Worker::ReadAndVerifyHeader(PlatformFile file) {
- base::PlatformFileInfo info;
- if (!base::GetPlatformFileInfo(file, &info))
- return false;
-
- if (info.size < static_cast<int>(sizeof(Header)))
- return false;
-
- header_.reset(new Header);
- if (!ReadPlatformFile(file, 0, header_.get(), sizeof(Header)))
- return false;
-
- if (header_->magic != kMagicSignature)
- return false;
-
- if (header_->version != kCurrentVersion)
- return false;
-
- if (header_->num_entries > kMaxNumEntries)
- return false;
-
- size_t expected_size = kRecordSize * header_->num_entries +
- sizeof(Header) + sizeof(uint32); // Trailing hash.
-
- if (info.size < static_cast<int>(expected_size))
- return false;
-
- uint32 hash = base::Hash(reinterpret_cast<char*>(header_.get()),
- offsetof(Header, header_hash));
- if (hash != header_->header_hash)
- return false;
-
- return true;
-}
-
-void InfiniteCache::Worker::Query(int* result) {
- *result = static_cast<int>(map_.size());
-}
-
-void InfiniteCache::Worker::Flush(int* result) {
- flushed_ = false;
- StoreData();
- flushed_ = true;
- *result = OK;
-}
-
-void InfiniteCache::Worker::OnTimer() {
- header_->use_minutes += kTimerMinutes;
- GenerateHistograms();
- StoreData();
-}
-
-void InfiniteCache::Worker::Add(const Details& details) {
- UpdateSize(0, details.headers_size);
- UpdateSize(0, details.response_size);
- header_->num_entries = static_cast<int>(map_.size());
- if (header_->num_entries == kMaxNumEntries) {
- int use_hours = header_->use_minutes / 60;
- int age_hours = (Time::Now() -
- Time::FromInternalValue(header_->creation_time)).InHours();
- UMA_HISTOGRAM_COUNTS_10000("InfiniteCache.MaxUseTime", use_hours);
- UMA_HISTOGRAM_COUNTS_10000("InfiniteCache.MaxAge", age_hours);
-
- int entry_size = static_cast<int>(header_->total_size / kMaxNumEntries);
- UMA_HISTOGRAM_COUNTS("InfiniteCache.FinalAvgEntrySize", entry_size);
- header_->disabled = 1;
- header_->num_entries = 0;
- map_.clear();
- }
-}
-
-void InfiniteCache::Worker::Remove(const Details& details) {
- UpdateSize(details.headers_size, 0);
- UpdateSize(details.response_size, 0);
- header_->num_entries--;
-}
-
-void InfiniteCache::Worker::UpdateSize(int old_size, int new_size) {
- header_->total_size += new_size - old_size;
- DCHECK_GE(header_->total_size, 0);
-}
-
-void InfiniteCache::Worker::RecordHit(const Details& old, Details* details) {
- header_->num_hits++;
- int access_delta = (IntToTime(details->last_access) -
- IntToTime(old.last_access)).InMinutes();
- if (old.use_count) {
- UMA_HISTOGRAM_COUNTS("InfiniteCache.ReuseAge2", access_delta);
- if (details->flags & GA_JS_HTTP) {
- UMA_HISTOGRAM_COUNTS("InfiniteCache.GaJsHttpReuseAge2", access_delta);
- } else if (details->flags & GA_JS_HTTPS) {
- UMA_HISTOGRAM_COUNTS("InfiniteCache.GaJsHttpsReuseAge2", access_delta);
- }
- } else {
- UMA_HISTOGRAM_COUNTS("InfiniteCache.FirstReuseAge2", access_delta);
- if (details->flags & GA_JS_HTTP) {
- UMA_HISTOGRAM_COUNTS(
- "InfiniteCache.GaJsHttpFirstReuseAge2", access_delta);
- } else if (details->flags & GA_JS_HTTPS) {
- UMA_HISTOGRAM_COUNTS(
- "InfiniteCache.GaJsHttpsFirstReuseAge2", access_delta);
- }
- }
-
- details->use_count = old.use_count;
- if (details->use_count < kuint8max)
- details->use_count++;
- CACHE_COUNT_HISTOGRAM("InfiniteCache.UseCount", details->use_count);
- if (details->flags & GA_JS_HTTP) {
- CACHE_COUNT_HISTOGRAM("InfiniteCache.GaJsHttpUseCount", details->use_count);
- } else if (details->flags & GA_JS_HTTPS) {
- CACHE_COUNT_HISTOGRAM("InfiniteCache.GaJsHttpsUseCount",
- details->use_count);
- }
-}
-
-void InfiniteCache::Worker::RecordUpdate(const Details& old, Details* details) {
- int access_delta = (IntToTime(details->last_access) -
- IntToTime(old.last_access)).InMinutes();
- if (old.update_count) {
- UMA_HISTOGRAM_COUNTS("InfiniteCache.UpdateAge2", access_delta);
- if (details->flags & GA_JS_HTTP) {
- UMA_HISTOGRAM_COUNTS(
- "InfiniteCache.GaJsHttpUpdateAge2", access_delta);
- } else if (details->flags & GA_JS_HTTPS) {
- UMA_HISTOGRAM_COUNTS(
- "InfiniteCache.GaJsHttpsUpdateAge2", access_delta);
- }
- } else {
- UMA_HISTOGRAM_COUNTS("InfiniteCache.FirstUpdateAge2", access_delta);
- if (details->flags & GA_JS_HTTP) {
- UMA_HISTOGRAM_COUNTS(
- "InfiniteCache.GaJsHttpFirstUpdateAge2", access_delta);
- } else if (details->flags & GA_JS_HTTPS) {
- UMA_HISTOGRAM_COUNTS(
- "InfiniteCache.GaJsHttpsFirstUpdateAge2", access_delta);
- }
- }
-
- details->update_count = old.update_count;
- if (details->update_count < kuint8max)
- details->update_count++;
-
- CACHE_COUNT_HISTOGRAM("InfiniteCache.UpdateCount", details->update_count);
- if (details->flags & GA_JS_HTTP) {
- CACHE_COUNT_HISTOGRAM("InfiniteCache.GaJsHttpUpdateCount",
- details->update_count);
- } else if (details->flags & GA_JS_HTTPS) {
- CACHE_COUNT_HISTOGRAM("InfiniteCache.GaJsHttpsUpdateCount",
- details->update_count);
- }
- details->use_count = 0;
-}
-
-void InfiniteCache::Worker::RecordComparison(
- bool infinite_used_or_validated,
- bool http_used_or_validated) const {
- enum Comparison {
- INFINITE_NOT_STRONG_HIT_HTTP_NOT_STRONG_HIT,
- INFINITE_NOT_STRONG_HIT_HTTP_STRONG_HIT,
- INFINITE_STRONG_HIT_HTTP_NOT_STRONG_HIT,
- INFINITE_STRONG_HIT_HTTP_STRONG_HIT,
- COMPARISON_ENUM_MAX,
- };
-
- Comparison comparison;
- if (infinite_used_or_validated) {
- if (http_used_or_validated)
- comparison = INFINITE_STRONG_HIT_HTTP_STRONG_HIT;
- else
- comparison = INFINITE_STRONG_HIT_HTTP_NOT_STRONG_HIT;
- } else {
- if (http_used_or_validated)
- comparison = INFINITE_NOT_STRONG_HIT_HTTP_STRONG_HIT;
- else
- comparison = INFINITE_NOT_STRONG_HIT_HTTP_NOT_STRONG_HIT;
- }
-
- UMA_HISTOGRAM_ENUMERATION("InfiniteCache.Comparison",
- comparison, COMPARISON_ENUM_MAX);
- const int size_bucket =
- static_cast<int>(header_->total_size / kReportSizeStep);
- const int kComparisonBuckets = 50;
- UMA_HISTOGRAM_ENUMERATION(
- "InfiniteCache.ComparisonBySize",
- comparison * kComparisonBuckets + std::min(size_bucket,
- kComparisonBuckets-1),
- kComparisonBuckets * COMPARISON_ENUM_MAX);
-}
-
-void InfiniteCache::Worker::GenerateHistograms() {
- bool new_size_step = (header_->total_size / kReportSizeStep !=
- header_->size_last_report / kReportSizeStep);
- header_->size_last_report = header_->total_size;
- if (!new_size_step && (header_->use_minutes % 60 != 0))
- return;
-
- if (header_->disabled)
- return;
-
- int hit_ratio = header_->num_hits * 100;
- if (header_->num_requests)
- hit_ratio /= header_->num_requests;
- else
- hit_ratio = 0;
-
- // We'll be generating pairs of histograms that can be used to get the hit
- // ratio for any bucket of the paired histogram.
- bool report_second_stat = base::RandInt(0, 99) < hit_ratio;
-
- if (header_->use_minutes % 60 == 0) {
- int use_hours = header_->use_minutes / 60;
- int age_hours = (Time::Now() -
- Time::FromInternalValue(header_->creation_time)).InHours();
- UMA_HISTOGRAM_COUNTS_10000("InfiniteCache.UseTime", use_hours);
- UMA_HISTOGRAM_COUNTS_10000("InfiniteCache.Age", age_hours);
- if (report_second_stat) {
- UMA_HISTOGRAM_COUNTS_10000("InfiniteCache.HitRatioByUseTime", use_hours);
- UMA_HISTOGRAM_COUNTS_10000("InfiniteCache.HitRatioByAge", age_hours);
- }
- }
-
- if (new_size_step) {
- int size_bucket = static_cast<int>(header_->total_size / kReportSizeStep);
- UMA_HISTOGRAM_ENUMERATION("InfiniteCache.Size", std::min(size_bucket, 50),
- 51);
- UMA_HISTOGRAM_ENUMERATION("InfiniteCache.SizeCoarse", size_bucket / 5, 51);
- UMA_HISTOGRAM_COUNTS("InfiniteCache.Entries", header_->num_entries);
- UMA_HISTOGRAM_COUNTS_10000("InfiniteCache.BadHits", header_->num_bad_hits);
- if (report_second_stat) {
- UMA_HISTOGRAM_ENUMERATION("InfiniteCache.HitRatioBySize",
- std::min(size_bucket, 50), 51);
- UMA_HISTOGRAM_ENUMERATION("InfiniteCache.HitRatioBySizeCoarse",
- size_bucket / 5, 51);
- UMA_HISTOGRAM_COUNTS("InfiniteCache.HitRatioByEntries",
- header_->num_entries);
- }
- header_->num_hits = 0;
- header_->num_bad_hits = 0;
- header_->num_requests = 0;
- }
-}
-
-bool InfiniteCache::Worker::CanReuse(const Details& old,
- const Details& current) {
- enum ReuseStatus {
- REUSE_OK = 0,
- REUSE_NO_CACHE,
- REUSE_ALWAYS_EXPIRED,
- REUSE_EXPIRED,
- REUSE_TRUNCATED,
- REUSE_VARY,
- REUSE_DUMMY_VALUE,
- // Not an individual value; it's added to another reason.
- REUSE_REVALIDATEABLE = 7
- };
- int reason = REUSE_OK;
-
- if (old.expiration < current.last_access)
- reason = REUSE_EXPIRED;
-
- if (old.flags & EXPIRED)
- reason = REUSE_ALWAYS_EXPIRED;
-
- if (old.flags & NO_CACHE)
- reason = REUSE_NO_CACHE;
-
- if (old.flags & TRUNCATED)
- reason = REUSE_TRUNCATED;
-
- if (old.vary_hash != current.vary_hash)
- reason = REUSE_VARY;
-
- bool have_to_drop = (old.flags & TRUNCATED) && !(old.flags & RESUMABLE);
- if (reason && (old.flags & (REVALIDATEABLE | RESUMABLE)) && !have_to_drop)
- reason += REUSE_REVALIDATEABLE;
-
- UMA_HISTOGRAM_ENUMERATION("InfiniteCache.ReuseFailure2", reason, 15);
- if (current.flags & GA_JS_HTTP) {
- UMA_HISTOGRAM_ENUMERATION(
- "InfiniteCache.GaJsHttpReuseFailure2", reason, 15);
- } else if (current.flags & GA_JS_HTTPS) {
- UMA_HISTOGRAM_ENUMERATION(
- "InfiniteCache.GaJsHttpsReuseFailure2", reason, 15);
- }
- return !reason;
-}
-
-bool InfiniteCache::Worker::DataChanged(const Details& old,
- const Details& current) {
- if (current.flags & CACHED)
- return false;
-
- bool changed = false;
- if (old.response_size != current.response_size) {
- changed = true;
- UpdateSize(old.response_size, current.response_size);
- }
-
- if (old.response_hash != current.response_hash)
- changed = true;
-
- return changed;
-}
-
-bool InfiniteCache::Worker::HeadersChanged(const Details& old,
- const Details& current) {
- bool changed = false;
- if (old.headers_size != current.headers_size) {
- changed = true;
- UpdateSize(old.headers_size, current.headers_size);
- }
-
- if (old.headers_hash != current.headers_hash)
- changed = true;
-
- return changed;
-}
-
-// ----------------------------------------------------------------------------
-
-InfiniteCache::InfiniteCache() {
-}
-
-InfiniteCache::~InfiniteCache() {
- if (!worker_)
- return;
-
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&InfiniteCache::Worker::Cleanup, worker_));
- worker_ = NULL;
-}
-
-void InfiniteCache::Init(const base::FilePath& path) {
- worker_pool_ = new base::SequencedWorkerPool(1, "Infinite cache thread");
- task_runner_ = worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
- worker_pool_->GetSequenceToken(),
- base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
-
- worker_ = new Worker();
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&InfiniteCache::Worker::Init, worker_,
- path));
-
- timer_.Start(FROM_HERE, TimeDelta::FromMinutes(kTimerMinutes), this,
- &InfiniteCache::OnTimer);
-}
-
-InfiniteCacheTransaction* InfiniteCache::CreateInfiniteCacheTransaction() {
- if (!worker_)
- return NULL;
- return new InfiniteCacheTransaction(this);
-}
-
-int InfiniteCache::DeleteData(const CompletionCallback& callback) {
- if (!worker_)
- return OK;
- int* result = new int;
- task_runner_->PostTaskAndReply(
- FROM_HERE, base::Bind(&InfiniteCache::Worker::DeleteData, worker_,
- result),
- base::Bind(&OnComplete, callback, base::Owned(result)));
- return ERR_IO_PENDING;
-}
-
-int InfiniteCache::DeleteDataBetween(base::Time initial_time,
- base::Time end_time,
- const CompletionCallback& callback) {
- if (!worker_)
- return OK;
- int* result = new int;
- task_runner_->PostTaskAndReply(
- FROM_HERE, base::Bind(&InfiniteCache::Worker::DeleteDataBetween, worker_,
- initial_time, end_time, result),
- base::Bind(&OnComplete, callback, base::Owned(result)));
- return ERR_IO_PENDING;
-}
-
-std::string InfiniteCache::GenerateKey(const HttpRequestInfo* request) {
- // Don't add any upload data identifier.
- return HttpUtil::SpecForRequest(request->url);
-}
-
-void InfiniteCache::ProcessResource(
- scoped_ptr<InfiniteCacheTransaction::ResourceData> data) {
- if (!worker_)
- return;
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&InfiniteCache::Worker::Process, worker_,
- base::Passed(&data)));
-}
-
-void InfiniteCache::OnTimer() {
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&InfiniteCache::Worker::OnTimer, worker_));
-}
-
-int InfiniteCache::QueryItemsForTest(const CompletionCallback& callback) {
- DCHECK(worker_);
- int* result = new int;
- task_runner_->PostTaskAndReply(
- FROM_HERE, base::Bind(&InfiniteCache::Worker::Query, worker_, result),
- base::Bind(&OnComplete, callback, base::Owned(result)));
- return net::ERR_IO_PENDING;
-}
-
-int InfiniteCache::FlushDataForTest(const CompletionCallback& callback) {
- DCHECK(worker_);
- int* result = new int;
- task_runner_->PostTaskAndReply(
- FROM_HERE, base::Bind(&InfiniteCache::Worker::Flush, worker_, result),
- base::Bind(&OnComplete, callback, base::Owned(result)));
- return net::ERR_IO_PENDING;
-}
-
-} // namespace net
diff --git a/net/http/infinite_cache.h b/net/http/infinite_cache.h
deleted file mode 100644
index a93d4c1..0000000
--- a/net/http/infinite_cache.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This is the interface of a simulated infinite cache. The purpose of this
-// code is to evaluate the performance of an HTTP cache that is not constrained
-// to evict resources.
-
-#ifndef NET_HTTP_INFINITE_CACHE_H_
-#define NET_HTTP_INFINITE_CACHE_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/timer.h"
-#include "net/base/completion_callback.h"
-#include "net/base/net_export.h"
-
-namespace base {
-class FilePath;
-class SequencedTaskRunner;
-class SequencedWorkerPool;
-}
-
-namespace net {
-
-class HttpCache;
-class HttpResponseInfo;
-class InfiniteCache;
-struct HttpRequestInfo;
-
-// An InfiniteCacheTransaction is paired with an HttpCache::Transaction to track
-// every request that goes through the HttpCache. This object is notified when
-// relevant steps are reached while processing the request.
-class NET_EXPORT_PRIVATE InfiniteCacheTransaction {
- public:
- explicit InfiniteCacheTransaction(InfiniteCache* cache);
- ~InfiniteCacheTransaction();
-
- // Called when a new HttpTransaction is started.
- void OnRequestStart(const HttpRequestInfo* request);
-
- // Called when the transaction corresponds to a back navigation.
- void OnBackForwardNavigation();
-
- // Called when the response headers are available.
- void OnResponseReceived(const HttpResponseInfo* response);
-
- // Called when the response data is received from the network.
- void OnDataRead(const char* data, int data_len);
-
- // Called when the resource is marked as truncated by the HttpCache.
- void OnTruncatedResponse();
-
- // Called when the resource is served from the cache, so OnDataRead will not
- // be called for this request.
- void OnServedFromCache(const HttpResponseInfo* response);
-
- private:
- friend class InfiniteCache;
- struct ResourceData;
- void Finish();
-
- base::WeakPtr<InfiniteCache> cache_;
- scoped_ptr<ResourceData> resource_data_;
- DISALLOW_COPY_AND_ASSIGN(InfiniteCacheTransaction);
-};
-
-// An InfiniteCache is paired with an HttpCache instance to simulate an infinite
-// backend storage.
-class NET_EXPORT_PRIVATE InfiniteCache
- : public base::SupportsWeakPtr<InfiniteCache> {
- public:
- InfiniteCache();
- ~InfiniteCache();
-
- // Initializes this object to start tracking requests. |path| is the location
- // of the file to use to store data; it can be empty, in which case the data
- // will not be persisted to disk.
- void Init(const base::FilePath& path);
-
- InfiniteCacheTransaction* CreateInfiniteCacheTransaction();
-
- // Removes all data for this experiment. Returns a net error code.
- int DeleteData(const CompletionCallback& callback);
-
- // Removes requests between |initial_time| and |end_time|.
- int DeleteDataBetween(base::Time initial_time,
- base::Time end_time,
- const CompletionCallback& callback);
-
- // Returns the number of elements currently tracked.
- int QueryItemsForTest(const CompletionCallback& callback);
-
- // Flush the data to disk, preventing flushing when the destructor runs. Any
- // data added to the cache after calling this method will not be written to
- // disk, unless this method is called again to do so.
- int FlushDataForTest(const CompletionCallback& callback);
-
- private:
- class Worker;
- friend class base::RepeatingTimer<InfiniteCache>;
- friend class InfiniteCacheTransaction;
-
- std::string GenerateKey(const HttpRequestInfo* request);
- void ProcessResource(scoped_ptr<InfiniteCacheTransaction::ResourceData> data);
- void OnTimer();
-
- scoped_refptr<Worker> worker_;
- scoped_refptr<base::SequencedWorkerPool> worker_pool_;
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- base::RepeatingTimer<InfiniteCache> timer_;
-
- DISALLOW_COPY_AND_ASSIGN(InfiniteCache);
-};
-
-} // namespace net
-
-#endif // NET_HTTP_INFINITE_CACHE_H_
diff --git a/net/http/infinite_cache_unittest.cc b/net/http/infinite_cache_unittest.cc
deleted file mode 100644
index 24d2ccc..0000000
--- a/net/http/infinite_cache_unittest.cc
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/http/infinite_cache.h"
-
-#include "base/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/stringprintf.h"
-#include "base/threading/platform_thread.h"
-#include "base/time.h"
-#include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
-#include "net/http/http_transaction_unittest.h"
-#include "net/http/http_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::Time;
-using base::TimeDelta;
-using net::InfiniteCache;
-using net::InfiniteCacheTransaction;
-
-namespace {
-
-void StartRequest(const MockTransaction& http_transaction,
- InfiniteCacheTransaction* transaction) {
- std::string standard_headers(http_transaction.status);
- standard_headers.push_back('\n');
- standard_headers.append(http_transaction.response_headers);
- std::string raw_headers =
- net::HttpUtil::AssembleRawHeaders(standard_headers.c_str(),
- standard_headers.size());
-
- scoped_refptr<net::HttpResponseHeaders> headers(
- new net::HttpResponseHeaders(raw_headers));
- net::HttpResponseInfo response;
- response.headers = headers;
- response.request_time = http_transaction.request_time.is_null() ?
- Time::Now() : http_transaction.request_time;
- response.response_time = http_transaction.response_time.is_null() ?
- Time::Now() : http_transaction.response_time;
-
- MockHttpRequest request(http_transaction);
- transaction->OnRequestStart(&request);
- transaction->OnResponseReceived(&response);
-}
-
-void ProcessRequest(const MockTransaction& http_transaction,
- InfiniteCache* cache) {
- scoped_ptr<InfiniteCacheTransaction> transaction
- (cache->CreateInfiniteCacheTransaction());
-
- StartRequest(http_transaction, transaction.get());
- transaction->OnDataRead(http_transaction.data, strlen(http_transaction.data));
-}
-
-void ProcessRequestWithTime(const MockTransaction& http_transaction,
- InfiniteCache* cache,
- Time time) {
- scoped_ptr<InfiniteCacheTransaction> transaction
- (cache->CreateInfiniteCacheTransaction());
-
- MockTransaction timed_transaction = http_transaction;
- timed_transaction.request_time = time;
- timed_transaction.response_time = time;
- StartRequest(timed_transaction, transaction.get());
- transaction->OnDataRead(http_transaction.data, strlen(http_transaction.data));
-}
-
-} // namespace
-
-TEST(InfiniteCache, Basics) {
- InfiniteCache cache;
- cache.Init(base::FilePath());
-
- scoped_ptr<InfiniteCacheTransaction> transaction
- (cache.CreateInfiniteCacheTransaction());
-
- // Don't even Start() this transaction.
- transaction.reset(cache.CreateInfiniteCacheTransaction());
-
- net::TestCompletionCallback cb;
- EXPECT_EQ(0, cb.GetResult(cache.QueryItemsForTest(cb.callback())));
-
- MockHttpRequest request(kTypicalGET_Transaction);
- transaction->OnRequestStart(&request);
-
- // Don't have a response yet.
- transaction.reset(cache.CreateInfiniteCacheTransaction());
- EXPECT_EQ(0, cb.GetResult(cache.QueryItemsForTest(cb.callback())));
-
- net::HttpResponseInfo response;
- scoped_refptr<net::HttpResponseHeaders> headers(
- new net::HttpResponseHeaders(kTypicalGET_Transaction.response_headers));
- response.headers = headers;
-
- transaction->OnRequestStart(&request);
- transaction->OnResponseReceived(&response);
- transaction.reset(cache.CreateInfiniteCacheTransaction());
- EXPECT_EQ(1, cb.GetResult(cache.QueryItemsForTest(cb.callback())));
-
- // Hit the same URL again.
- transaction->OnRequestStart(&request);
- transaction->OnResponseReceived(&response);
- transaction.reset(cache.CreateInfiniteCacheTransaction());
- EXPECT_EQ(1, cb.GetResult(cache.QueryItemsForTest(cb.callback())));
-
- // Now a different URL.
- MockHttpRequest request2(kSimpleGET_Transaction);
- transaction->OnRequestStart(&request2);
- transaction->OnResponseReceived(&response);
- transaction.reset();
- EXPECT_EQ(2, cb.GetResult(cache.QueryItemsForTest(cb.callback())));
-}
-
-TEST(InfiniteCache, Save_Restore) {
- base::ScopedTempDir dir;
- ASSERT_TRUE(dir.CreateUniqueTempDir());
- base::FilePath path = dir.path().Append(FILE_PATH_LITERAL("infinite"));
-
- scoped_ptr<InfiniteCache> cache(new InfiniteCache);
- cache->Init(path);
- net::TestCompletionCallback cb;
-
- ProcessRequest(kTypicalGET_Transaction, cache.get());
- ProcessRequest(kSimpleGET_Transaction, cache.get());
- ProcessRequest(kETagGET_Transaction, cache.get());
- ProcessRequest(kSimplePOST_Transaction, cache.get());
-
- EXPECT_EQ(3, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
- EXPECT_EQ(net::OK, cb.GetResult(cache->FlushDataForTest(cb.callback())));
-
- cache.reset(new InfiniteCache);
- cache->Init(path);
- EXPECT_EQ(3, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
-
- ProcessRequest(kTypicalGET_Transaction, cache.get());
- EXPECT_EQ(3, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
- EXPECT_EQ(net::OK, cb.GetResult(cache->FlushDataForTest(cb.callback())));
-}
-
-TEST(InfiniteCache, DoomMethod) {
- InfiniteCache cache;
- cache.Init(base::FilePath());
-
- ProcessRequest(kTypicalGET_Transaction, &cache);
- ProcessRequest(kSimpleGET_Transaction, &cache);
- ProcessRequest(kETagGET_Transaction, &cache);
- net::TestCompletionCallback cb;
- EXPECT_EQ(3, cb.GetResult(cache.QueryItemsForTest(cb.callback())));
-
- MockTransaction request(kTypicalGET_Transaction);
- request.method = "PUT";
- ProcessRequest(request, &cache);
- EXPECT_EQ(2, cb.GetResult(cache.QueryItemsForTest(cb.callback())));
-
- request.method = "POST";
- request.url = kSimpleGET_Transaction.url;
- ProcessRequest(request, &cache);
- EXPECT_EQ(1, cb.GetResult(cache.QueryItemsForTest(cb.callback())));
-
- request.method = "DELETE";
- request.url = kETagGET_Transaction.url;
- ProcessRequest(request, &cache);
- EXPECT_EQ(0, cb.GetResult(cache.QueryItemsForTest(cb.callback())));
-}
-
-TEST(InfiniteCache, Delete) {
- base::ScopedTempDir dir;
- ASSERT_TRUE(dir.CreateUniqueTempDir());
- base::FilePath path = dir.path().Append(FILE_PATH_LITERAL("infinite"));
-
- scoped_ptr<InfiniteCache> cache(new InfiniteCache);
- cache->Init(path);
- net::TestCompletionCallback cb;
-
- ProcessRequest(kTypicalGET_Transaction, cache.get());
- ProcessRequest(kSimpleGET_Transaction, cache.get());
- EXPECT_EQ(2, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
- EXPECT_EQ(net::OK, cb.GetResult(cache->FlushDataForTest(cb.callback())));
- EXPECT_TRUE(file_util::PathExists(path));
-
- cache.reset(new InfiniteCache);
- cache->Init(path);
- EXPECT_EQ(2, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
- EXPECT_EQ(net::OK, cb.GetResult(cache->DeleteData(cb.callback())));
- EXPECT_EQ(0, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
- EXPECT_FALSE(file_util::PathExists(path));
-
- EXPECT_EQ(net::OK, cb.GetResult(cache->FlushDataForTest(cb.callback())));
-}
-
-TEST(InfiniteCache, DeleteBetween) {
-#if !defined(OS_ANDROID)
- base::ScopedTempDir dir;
- ASSERT_TRUE(dir.CreateUniqueTempDir());
- base::FilePath path = dir.path().Append(FILE_PATH_LITERAL("infinite"));
-
- scoped_ptr<InfiniteCache> cache(new InfiniteCache);
- cache->Init(path);
- net::TestCompletionCallback cb;
-
- Time::Exploded baseline = {};
- baseline.year = 2012;
- baseline.month = 1;
- baseline.day_of_month = 1;
- Time base_time = Time::FromUTCExploded(baseline);
-
- ProcessRequestWithTime(kTypicalGET_Transaction, cache.get(), base_time);
-
- Time start = base_time + TimeDelta::FromSeconds(2);
- ProcessRequestWithTime(kSimpleGET_Transaction, cache.get(), start);
- Time end = start + TimeDelta::FromSeconds(2);
-
- ProcessRequestWithTime(kETagGET_Transaction, cache.get(),
- end + TimeDelta::FromSeconds(2));
-
- EXPECT_EQ(3, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
- EXPECT_EQ(net::OK,
- cb.GetResult(cache->DeleteDataBetween(start, end,
- cb.callback())));
- EXPECT_EQ(2, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
-
- // Make sure the data is deleted from disk.
- EXPECT_EQ(net::OK, cb.GetResult(cache->FlushDataForTest(cb.callback())));
- cache.reset(new InfiniteCache);
- cache->Init(path);
-
- EXPECT_EQ(2, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
- ProcessRequestWithTime(kETagGET_Transaction, cache.get(),
- end + TimeDelta::FromMinutes(5));
- EXPECT_EQ(2, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
-
- EXPECT_EQ(net::OK,
- cb.GetResult(cache->DeleteDataBetween(start, Time::Now(),
- cb.callback())));
- EXPECT_EQ(1, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
-
- // Make sure the data is deleted from disk.
- EXPECT_EQ(net::OK, cb.GetResult(cache->FlushDataForTest(cb.callback())));
- cache.reset(new InfiniteCache);
- cache->Init(path);
-
- EXPECT_EQ(1, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
- ProcessRequest(kTypicalGET_Transaction, cache.get());
- EXPECT_EQ(1, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
-#endif // OS_ANDROID
-}
-
-#if 0
-// This test is too slow for the bots.
-TEST(InfiniteCache, FillUp) {
- base::ScopedTempDir dir;
- ASSERT_TRUE(dir.CreateUniqueTempDir());
- base::FilePath path = dir.path().Append(FILE_PATH_LITERAL("infinite"));
-
- scoped_ptr<InfiniteCache> cache(new InfiniteCache);
- cache->Init(path);
- net::TestCompletionCallback cb;
-
- const int kNumEntries = 25000;
- for (int i = 0; i < kNumEntries; i++) {
- std::string url = StringPrintf("http://foo.com/%d/foo.html", i);
- MockTransaction transaction = kTypicalGET_Transaction;
- transaction.url = url.c_str();
- ProcessRequest(transaction, cache.get());
- }
-
- EXPECT_EQ(kNumEntries, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
- EXPECT_EQ(net::OK, cb.GetResult(cache->FlushDataForTest(cb.callback())));
-
- cache.reset(new InfiniteCache);
- cache->Init(path);
- EXPECT_EQ(kNumEntries, cb.GetResult(cache->QueryItemsForTest(cb.callback())));
-}
-#endif
diff --git a/net/net.gyp b/net/net.gyp
index 715d7ef..46d8225 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -577,8 +577,6 @@
'http/http_vary_data.cc',
'http/http_vary_data.h',
'http/http_version.h',
- 'http/infinite_cache.cc',
- 'http/infinite_cache.h',
'http/md4.cc',
'http/md4.h',
'http/partial_data.cc',
@@ -1511,7 +1509,6 @@
'http/http_transaction_unittest.h',
'http/http_util_unittest.cc',
'http/http_vary_data_unittest.cc',
- 'http/infinite_cache_unittest.cc',
'http/mock_allow_url_security_manager.cc',
'http/mock_allow_url_security_manager.h',
'http/mock_gssapi_library_posix.cc',