Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: net/disk_cache/simple/simple_index.cc

Issue 14362009: Receive app notifications in SimpleCache, so we save our index file (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: gavins comments Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/disk_cache/simple/simple_index.h" 5 #include "net/disk_cache/simple/simple_index.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/message_loop.h" 13 #include "base/message_loop.h"
14 #include "base/pickle.h" 14 #include "base/pickle.h"
15 #include "base/task_runner.h" 15 #include "base/task_runner.h"
16 #include "base/threading/worker_pool.h" 16 #include "base/threading/worker_pool.h"
17 #include "net/base/net_errors.h" 17 #include "net/base/net_errors.h"
18 #include "net/disk_cache/simple/simple_entry_format.h" 18 #include "net/disk_cache/simple/simple_entry_format.h"
19 #include "net/disk_cache/simple/simple_index_file.h" 19 #include "net/disk_cache/simple/simple_index_file.h"
20 #include "net/disk_cache/simple/simple_util.h" 20 #include "net/disk_cache/simple/simple_util.h"
21 21
22
Philippe 2013/04/22 11:35:48 Nit: change not needed.
felipeg 2013/04/22 16:14:32 Done.
22 namespace { 23 namespace {
23 24
24 // How many seconds we delay writing the index to disk since the last cache 25 // How many seconds we delay writing the index to disk since the last cache
25 // operation has happened. 26 // operation has happened.
26 const int kWriteToDiskDelaySecs = 20; 27 const int kWriteToDiskDelay_ms = 20000;
Philippe 2013/04/22 11:35:48 Nit: s/_ms/MSecs here and below.
felipeg 2013/04/22 16:14:32 Done.
27 28 const int kWriteToDiskOnBackgroundDelay_ms = 100;
28 // WriteToDisk at lest every 5 minutes.
29 const int kMaxWriteToDiskDelaySecs = 300;
30 29
31 } // namespace 30 } // namespace
32 31
33 namespace disk_cache { 32 namespace disk_cache {
34 33
35 EntryMetadata::EntryMetadata() : hash_key_(0), 34 EntryMetadata::EntryMetadata() : hash_key_(0),
36 last_used_time_(0), 35 last_used_time_(0),
37 entry_size_(0) { 36 entry_size_(0) {
38 } 37 }
39 38
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 } 78 }
80 79
81 SimpleIndex::SimpleIndex( 80 SimpleIndex::SimpleIndex(
82 base::SingleThreadTaskRunner* cache_thread, 81 base::SingleThreadTaskRunner* cache_thread,
83 base::SingleThreadTaskRunner* io_thread, 82 base::SingleThreadTaskRunner* io_thread,
84 const base::FilePath& path) 83 const base::FilePath& path)
85 : cache_size_(0), 84 : cache_size_(0),
86 initialized_(false), 85 initialized_(false),
87 index_filename_(path.AppendASCII("simple-index")), 86 index_filename_(path.AppendASCII("simple-index")),
88 cache_thread_(cache_thread), 87 cache_thread_(cache_thread),
89 io_thread_(io_thread) { 88 io_thread_(io_thread),
89 #if defined(OS_ANDROID)
90 activity_status_notifier_(
91 io_thread,
92 base::Bind(&SimpleIndex::ActivityStatusChanged, AsWeakPtr())),
93 #endif
94 app_on_background_(false) {
90 } 95 }
91 96
92 SimpleIndex::~SimpleIndex() { 97 SimpleIndex::~SimpleIndex() {
93 DCHECK(io_thread_checker_.CalledOnValidThread()); 98 DCHECK(io_thread_checker_.CalledOnValidThread());
94 99
95 // Fail all callbacks waiting for the index to come up. 100 // Fail all callbacks waiting for the index to come up.
96 for (CallbackList::iterator it = to_run_when_initialized_.begin(), 101 for (CallbackList::iterator it = to_run_when_initialized_.begin(),
97 end = to_run_when_initialized_.end(); it != end; ++it) { 102 end = to_run_when_initialized_.end(); it != end; ++it) {
98 it->Run(net::ERR_ABORTED); 103 it->Run(net::ERR_ABORTED);
99 } 104 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 // static 212 // static
208 void SimpleIndex::InsertInEntrySet( 213 void SimpleIndex::InsertInEntrySet(
209 const disk_cache::EntryMetadata& entry_metadata, 214 const disk_cache::EntryMetadata& entry_metadata,
210 EntrySet* entry_set) { 215 EntrySet* entry_set) {
211 DCHECK(entry_set); 216 DCHECK(entry_set);
212 entry_set->insert( 217 entry_set->insert(
213 std::make_pair(entry_metadata.GetHashKey(), entry_metadata)); 218 std::make_pair(entry_metadata.GetHashKey(), entry_metadata));
214 } 219 }
215 220
216 void SimpleIndex::PostponeWritingToDisk() { 221 void SimpleIndex::PostponeWritingToDisk() {
217 const base::TimeDelta file_age = base::Time::Now() - last_write_to_disk_; 222 if (!initialized_)
218 if (file_age > base::TimeDelta::FromSeconds(kMaxWriteToDiskDelaySecs) &&
219 write_to_disk_timer_.IsRunning()) {
220 // If the index file is too old and there is a timer programmed to run a
221 // WriteToDisk soon, we don't postpone it, so we always WriteToDisk
222 // approximately every kMaxWriteToDiskDelaySecs.
223 return; 223 return;
224 int delay = kWriteToDiskDelay_ms;
225 if (app_on_background_) {
226 // When the app is in the background we can write the index much more
227 // frequently. We could even write it to disk on every operation if we
228 // wanted to.
229 delay = kWriteToDiskOnBackgroundDelay_ms;
224 } 230 }
225
226 // If the timer is already active, Start() will just Reset it, postponing it. 231 // If the timer is already active, Start() will just Reset it, postponing it.
227 write_to_disk_timer_.Start( 232 write_to_disk_timer_.Start(
228 FROM_HERE, 233 FROM_HERE,
229 base::TimeDelta::FromSeconds(kWriteToDiskDelaySecs), 234 base::TimeDelta::FromMilliseconds(delay),
230 base::Bind(&SimpleIndex::WriteToDisk, AsWeakPtr())); 235 base::Bind(&SimpleIndex::WriteToDisk, AsWeakPtr()));
231 } 236 }
232 237
233 // static 238 // static
234 void SimpleIndex::LoadFromDisk( 239 void SimpleIndex::LoadFromDisk(
235 const base::FilePath& index_filename, 240 const base::FilePath& index_filename,
236 base::SingleThreadTaskRunner* io_thread, 241 base::SingleThreadTaskRunner* io_thread,
237 const IndexCompletionCallback& completion_callback) { 242 const IndexCompletionCallback& completion_callback) {
238 scoped_ptr<EntrySet> index_file_entries = 243 scoped_ptr<EntrySet> index_file_entries =
239 SimpleIndexFile::LoadFromDisk(index_filename); 244 SimpleIndexFile::LoadFromDisk(index_filename);
(...skipping 10 matching lines...) Expand all
250 base::Bind(completion_callback, 255 base::Bind(completion_callback,
251 base::Passed(&index_file_entries), 256 base::Passed(&index_file_entries),
252 force_index_flush)); 257 force_index_flush));
253 } 258 }
254 259
255 // static 260 // static
256 scoped_ptr<SimpleIndex::EntrySet> SimpleIndex::RestoreFromDisk( 261 scoped_ptr<SimpleIndex::EntrySet> SimpleIndex::RestoreFromDisk(
257 const base::FilePath& index_filename) { 262 const base::FilePath& index_filename) {
258 using file_util::FileEnumerator; 263 using file_util::FileEnumerator;
259 LOG(INFO) << "Simple Cache Index is being restored from disk."; 264 LOG(INFO) << "Simple Cache Index is being restored from disk.";
260
261 file_util::Delete(index_filename, /* recursive = */ false);
262 scoped_ptr<EntrySet> index_file_entries(new EntrySet()); 265 scoped_ptr<EntrySet> index_file_entries(new EntrySet());
263 266
264 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format. 267 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format.
265 COMPILE_ASSERT(kSimpleEntryFileCount == 3, 268 COMPILE_ASSERT(kSimpleEntryFileCount == 3,
266 file_pattern_must_match_file_count); 269 file_pattern_must_match_file_count);
267 270
268 const int kFileSuffixLenght = std::string("_0").size(); 271 const int kFileSuffixLenght = std::string("_0").size();
269 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]"); 272 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]");
270 FileEnumerator enumerator(index_filename.DirName(), 273 FileEnumerator enumerator(index_filename.DirName(),
271 false /* recursive */, 274 false /* recursive */,
272 FileEnumerator::FILES, 275 FileEnumerator::FILES,
273 file_pattern); 276 file_pattern);
274 for (base::FilePath file_path = enumerator.Next(); !file_path.empty(); 277 for (base::FilePath file_path = enumerator.Next(); !file_path.empty();
275 file_path = enumerator.Next()) { 278 file_path = enumerator.Next()) {
276 const base::FilePath::StringType base_name = file_path.BaseName().value(); 279 const base::FilePath::StringType base_name = file_path.BaseName().value();
277 // Converting to std::string is OK since we never use UTF8 wide chars in our 280 // Converting to std::string is OK since we never use UTF8 wide chars in our
278 // file names. 281 // file names.
279 const std::string hash_name(base_name.begin(), base_name.end()); 282 const std::string hash_name(base_name.begin(), base_name.end());
280 const std::string hash_key_string = 283 const std::string hash_key_string =
281 hash_name.substr(0, hash_name.size() - kFileSuffixLenght); 284 hash_name.substr(0, hash_name.size() - kFileSuffixLenght);
282 uint64 hash_key = 0; 285 uint64 hash_key = 0;
283 if (!simple_util::GetEntryHashKeyFromHexString( 286 if (!simple_util::GetEntryHashKeyFromHexString(
284 hash_key_string, &hash_key)) { 287 hash_key_string, &hash_key)) {
285 LOG(WARNING) << "Invalid Entry Hash Key filename while restoring " 288 LOG(WARNING) << "Invalid Entry Hash Key filename while restoring "
286 << "Simple Index from disk: " << hash_name; 289 << "Simple Index from disk: " << hash_name;
287 // TODO(felipeg): Should we delete the invalid file here ?
288 continue; 290 continue;
289 } 291 }
290 292
291 FileEnumerator::FindInfo find_info = {}; 293 FileEnumerator::FindInfo find_info = {};
292 enumerator.GetFindInfo(&find_info); 294 enumerator.GetFindInfo(&find_info);
293 base::Time last_used_time; 295 base::Time last_used_time;
294 #if defined(OS_POSIX) 296 #if defined(OS_POSIX)
295 // For POSIX systems, a last access time is available. However, it's not 297 // For POSIX systems, a last access time is available. However, it's not
296 // guaranteed to be more accurate than mtime. It is no worse though. 298 // guaranteed to be more accurate than mtime. It is no worse though.
297 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime); 299 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 EntrySet::iterator current_entry = entries_set_.find(it->first); 341 EntrySet::iterator current_entry = entries_set_.find(it->first);
340 if (current_entry != entries_set_.end()) { 342 if (current_entry != entries_set_.end()) {
341 // When Merging, existing valid data in the |current_entry| will prevail. 343 // When Merging, existing valid data in the |current_entry| will prevail.
342 current_entry->second.MergeWith(it->second); 344 current_entry->second.MergeWith(it->second);
343 cache_size_ += current_entry->second.GetEntrySize(); 345 cache_size_ += current_entry->second.GetEntrySize();
344 } else { 346 } else {
345 InsertInEntrySet(it->second, &entries_set_); 347 InsertInEntrySet(it->second, &entries_set_);
346 cache_size_ += it->second.GetEntrySize(); 348 cache_size_ += it->second.GetEntrySize();
347 } 349 }
348 } 350 }
349 last_write_to_disk_ = base::Time::Now();
350 initialized_ = true; 351 initialized_ = true;
351 removed_entries_.clear(); 352 removed_entries_.clear();
352 353
353 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow down 354 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow down
354 // much the merge. 355 // much the merge.
355 if (force_index_flush) 356 if (force_index_flush)
356 WriteToDisk(); 357 WriteToDisk();
357 358
358 // Run all callbacks waiting for the index to come up. 359 // Run all callbacks waiting for the index to come up.
359 for (CallbackList::iterator it = to_run_when_initialized_.begin(), 360 for (CallbackList::iterator it = to_run_when_initialized_.begin(),
360 end = to_run_when_initialized_.end(); it != end; ++it) { 361 end = to_run_when_initialized_.end(); it != end; ++it) {
361 io_thread_->PostTask(FROM_HERE, base::Bind((*it), net::OK)); 362 io_thread_->PostTask(FROM_HERE, base::Bind((*it), net::OK));
362 } 363 }
363 to_run_when_initialized_.clear(); 364 to_run_when_initialized_.clear();
364 } 365 }
365 366
367 #if defined(OS_ANDROID)
368 void SimpleIndex::ActivityStatusChanged(
369 net::SimpleCacheActivityStatusNotifier::ActivityStatus activity_status) {
370 DCHECK(io_thread_checker_.CalledOnValidThread());
371 // These values are defined in the file ActivityStatus.java
372 if (activity_status == net::SimpleCacheActivityStatusNotifier::RESUMED) {
373 app_on_background_ = false;
374 } else if (activity_status ==
375 net::SimpleCacheActivityStatusNotifier::PAUSED) {
376 app_on_background_ = true;
377 WriteToDisk();
378 } else if (activity_status ==
379 net::SimpleCacheActivityStatusNotifier::STOPPED) {
380 WriteToDisk();
381 } else if (activity_status ==
382 net::SimpleCacheActivityStatusNotifier::DESTROYED) {
383 WriteToDisk();
384 }
385 }
386 #endif
387
366 void SimpleIndex::WriteToDisk() { 388 void SimpleIndex::WriteToDisk() {
367 DCHECK(io_thread_checker_.CalledOnValidThread()); 389 DCHECK(io_thread_checker_.CalledOnValidThread());
368 if (!initialized_) 390 if (!initialized_)
369 return; 391 return;
370 last_write_to_disk_ = base::Time::Now();
371 SimpleIndexFile::IndexMetadata index_metadata(entries_set_.size(), 392 SimpleIndexFile::IndexMetadata index_metadata(entries_set_.size(),
372 cache_size_); 393 cache_size_);
373 scoped_ptr<Pickle> pickle = SimpleIndexFile::Serialize(index_metadata, 394 scoped_ptr<Pickle> pickle = SimpleIndexFile::Serialize(index_metadata,
374 entries_set_); 395 entries_set_);
375 cache_thread_->PostTask(FROM_HERE, base::Bind( 396 cache_thread_->PostTask(FROM_HERE, base::Bind(
376 &SimpleIndex::WriteToDiskInternal, 397 &SimpleIndex::WriteToDiskInternal,
377 index_filename_, 398 index_filename_,
378 base::Passed(&pickle))); 399 base::Passed(&pickle)));
379 } 400 }
380 401
381 } // namespace disk_cache 402 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698