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

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

Issue 22927018: Avoid fragmenting the heap too much while reconstructing the index. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Egor's and Gavin's comments Created 7 years, 4 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 | Annotate | Revision Log
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_file.h" 5 #include "net/disk_cache/simple/simple_index_file.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/files/file_enumerator.h"
11 #include "base/files/memory_mapped_file.h" 10 #include "base/files/memory_mapped_file.h"
12 #include "base/hash.h" 11 #include "base/hash.h"
13 #include "base/logging.h" 12 #include "base/logging.h"
14 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
15 #include "base/pickle.h" 14 #include "base/pickle.h"
16 #include "base/single_thread_task_runner.h" 15 #include "base/single_thread_task_runner.h"
17 #include "base/task_runner_util.h" 16 #include "base/task_runner_util.h"
18 #include "base/threading/thread_restrictions.h" 17 #include "base/threading/thread_restrictions.h"
19 #include "net/disk_cache/simple/simple_entry_format.h" 18 #include "net/disk_cache/simple/simple_entry_format.h"
20 #include "net/disk_cache/simple/simple_index.h" 19 #include "net/disk_cache/simple/simple_index.h"
21 #include "net/disk_cache/simple/simple_synchronous_entry.h" 20 #include "net/disk_cache/simple/simple_synchronous_entry.h"
22 #include "net/disk_cache/simple/simple_util.h" 21 #include "net/disk_cache/simple/simple_util.h"
23 #include "third_party/zlib/zlib.h" 22 #include "third_party/zlib/zlib.h"
24 23
25 24 namespace disk_cache {
26 namespace { 25 namespace {
27 26
27 const int kEntryFilesHashLength = 16;
28 const int kEntryFilesSuffixLength = 2;
29
28 const uint64 kMaxEntiresInIndex = 100000000; 30 const uint64 kMaxEntiresInIndex = 100000000;
29 31
32 const char kFakeIndexFileName[] = "index";
33 const char kIndexFileName[] = "the-real-index";
34 const char kTempIndexFileName[] = "temp-index";
35
30 uint32 CalculatePickleCRC(const Pickle& pickle) { 36 uint32 CalculatePickleCRC(const Pickle& pickle) {
31 return crc32(crc32(0, Z_NULL, 0), 37 return crc32(crc32(0, Z_NULL, 0),
32 reinterpret_cast<const Bytef*>(pickle.payload()), 38 reinterpret_cast<const Bytef*>(pickle.payload()),
33 pickle.payload_size()); 39 pickle.payload_size());
34 } 40 }
35 41
36 void DoomEntrySetReply(const net::CompletionCallback& reply_callback, 42 void DoomEntrySetReply(const net::CompletionCallback& reply_callback,
37 int result) { 43 int result) {
38 reply_callback.Run(result); 44 reply_callback.Run(result);
39 } 45 }
(...skipping 20 matching lines...) Expand all
60 } 66 }
61 if (app_on_background) { 67 if (app_on_background) {
62 UMA_HISTOGRAM_TIMES("SimpleCache.IndexWriteToDiskTime.Background", 68 UMA_HISTOGRAM_TIMES("SimpleCache.IndexWriteToDiskTime.Background",
63 (base::TimeTicks::Now() - start_time)); 69 (base::TimeTicks::Now() - start_time));
64 } else { 70 } else {
65 UMA_HISTOGRAM_TIMES("SimpleCache.IndexWriteToDiskTime.Foreground", 71 UMA_HISTOGRAM_TIMES("SimpleCache.IndexWriteToDiskTime.Foreground",
66 (base::TimeTicks::Now() - start_time)); 72 (base::TimeTicks::Now() - start_time));
67 } 73 }
68 } 74 }
69 75
76 // Called for each cache directory traversal iteration.
77 void ProcessEntryFile(SimpleIndex::EntrySet* entries,
78 const base::FilePath& file_path) {
79 static const size_t kEntryFilesLength =
80 kEntryFilesHashLength + kEntryFilesSuffixLength;
81 const base::FilePath::StringType file_name_string =
82 file_path.BaseName().value();
83 if (file_name_string.size() != kEntryFilesLength) {
84 if (file_name_string != kFakeIndexFileName &&
85 file_name_string != kIndexFileName) {
86 LOG(ERROR) << "unexpected file " << file_name_string;
pasko 2013/08/21 16:03:17 it would be easy to forget to update this check wh
Philippe 2013/08/21 16:20:58 Done.
87 }
88 return;
89 }
90
91 const base::StringPiece hash_string(
92 file_name_string.begin(),
93 file_name_string.begin() + kEntryFilesHashLength);
94 uint64 hash_key = 0;
95 if (!simple_util::GetEntryHashKeyFromHexString(hash_string, &hash_key)) {
96 LOG(WARNING) << "Invalid entry hash key filename while restoring index from"
97 << " disk: " << file_name_string;
98 // TODO(felipeg): Should we delete the invalid file here ?
pasko 2013/08/21 16:03:17 I am absolutely sure we must *not* delete the inva
Philippe 2013/08/21 16:20:58 Done.
99 return;
100 }
101
102 base::PlatformFileInfo file_info;
103 if (!file_util::GetFileInfo(file_path, &file_info)) {
104 LOG(ERROR) << "Could not get file info for " << file_path.value();
105 return;
106 }
107 base::Time last_used_time;
108 #if defined(OS_POSIX)
109 // For POSIX systems, a last access time is available. However, it's not
110 // guaranteed to be more accurate than mtime. It is no worse though.
111 last_used_time = file_info.last_accessed;
112 #endif
113 if (last_used_time.is_null())
114 last_used_time = file_info.last_modified;
115
116 int64 file_size = file_info.size;
117 SimpleIndex::EntrySet::iterator it = entries->find(hash_key);
118 if (it == entries->end()) {
119 SimpleIndex::InsertInEntrySet(
120 hash_key,
121 EntryMetadata(last_used_time, file_size),
122 entries);
123 } else {
124 // Summing up the total size of the entry through all the *_[0-2] files
125 it->second.SetEntrySize(it->second.GetEntrySize() + file_size);
126 }
127 }
128
70 } // namespace 129 } // namespace
71 130
72 namespace disk_cache {
73
74 SimpleIndexLoadResult::SimpleIndexLoadResult() : did_load(false), 131 SimpleIndexLoadResult::SimpleIndexLoadResult() : did_load(false),
75 flush_required(false) { 132 flush_required(false) {
76 } 133 }
77 134
78 SimpleIndexLoadResult::~SimpleIndexLoadResult() { 135 SimpleIndexLoadResult::~SimpleIndexLoadResult() {
79 } 136 }
80 137
81 void SimpleIndexLoadResult::Reset() { 138 void SimpleIndexLoadResult::Reset() {
82 did_load = false; 139 did_load = false;
83 flush_required = false; 140 flush_required = false;
84 entries.clear(); 141 entries.clear();
85 } 142 }
86 143
87 // static
88 const char SimpleIndexFile::kIndexFileName[] = "the-real-index";
89 // static
90 const char SimpleIndexFile::kTempIndexFileName[] = "temp-index";
91
92 SimpleIndexFile::IndexMetadata::IndexMetadata() : 144 SimpleIndexFile::IndexMetadata::IndexMetadata() :
93 magic_number_(kSimpleIndexMagicNumber), 145 magic_number_(kSimpleIndexMagicNumber),
94 version_(kSimpleVersion), 146 version_(kSimpleVersion),
95 number_of_entries_(0), 147 number_of_entries_(0),
96 cache_size_(0) {} 148 cache_size_(0) {}
97 149
98 SimpleIndexFile::IndexMetadata::IndexMetadata( 150 SimpleIndexFile::IndexMetadata::IndexMetadata(
99 uint64 number_of_entries, uint64 cache_size) : 151 uint64 number_of_entries, uint64 cache_size) :
100 magic_number_(kSimpleIndexMagicNumber), 152 magic_number_(kSimpleIndexMagicNumber),
101 version_(kSimpleVersion), 153 version_(kSimpleVersion),
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 395
344 out_result->did_load = true; 396 out_result->did_load = true;
345 } 397 }
346 398
347 // static 399 // static
348 void SimpleIndexFile::SyncRestoreFromDisk( 400 void SimpleIndexFile::SyncRestoreFromDisk(
349 const base::FilePath& cache_directory, 401 const base::FilePath& cache_directory,
350 const base::FilePath& index_file_path, 402 const base::FilePath& index_file_path,
351 SimpleIndexLoadResult* out_result) { 403 SimpleIndexLoadResult* out_result) {
352 LOG(INFO) << "Simple Cache Index is being restored from disk."; 404 LOG(INFO) << "Simple Cache Index is being restored from disk.";
353
354 base::DeleteFile(index_file_path, /* recursive = */ false); 405 base::DeleteFile(index_file_path, /* recursive = */ false);
355 out_result->Reset(); 406 out_result->Reset();
356 SimpleIndex::EntrySet* entries = &out_result->entries; 407 SimpleIndex::EntrySet* entries = &out_result->entries;
357 408
358 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format. 409 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format.
359 COMPILE_ASSERT(kSimpleEntryFileCount == 3, 410 COMPILE_ASSERT(kSimpleEntryFileCount == 3,
360 file_pattern_must_match_file_count); 411 file_pattern_must_match_file_count);
361 412
362 const int kFileSuffixLength = sizeof("_0") - 1; 413 const bool did_succeed = TraverseCacheDirectory(
363 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]"); 414 cache_directory, base::Bind(&ProcessEntryFile, entries));
364 base::FileEnumerator enumerator(cache_directory, 415 if (!did_succeed) {
365 false /* recursive */, 416 LOG(ERROR) << "Could not reconstruct index from disk";
366 base::FileEnumerator::FILES, 417 return;
367 file_pattern);
368 for (base::FilePath file_path = enumerator.Next(); !file_path.empty();
369 file_path = enumerator.Next()) {
370 const base::FilePath::StringType base_name = file_path.BaseName().value();
371 // Converting to std::string is OK since we never use UTF8 wide chars in our
372 // file names.
373 const std::string hash_key_string(base_name.begin(),
374 base_name.end() - kFileSuffixLength);
375 uint64 hash_key = 0;
376 if (!simple_util::GetEntryHashKeyFromHexString(
377 hash_key_string, &hash_key)) {
378 LOG(WARNING) << "Invalid Entry Hash Key filename while restoring "
379 << "Simple Index from disk: " << base_name;
380 // TODO(felipeg): Should we delete the invalid file here ?
381 continue;
382 }
383
384 base::FileEnumerator::FileInfo info = enumerator.GetInfo();
385 base::Time last_used_time;
386 #if defined(OS_POSIX)
387 // For POSIX systems, a last access time is available. However, it's not
388 // guaranteed to be more accurate than mtime. It is no worse though.
389 last_used_time = base::Time::FromTimeT(info.stat().st_atime);
390 #endif
391 if (last_used_time.is_null())
392 last_used_time = info.GetLastModifiedTime();
393
394 int64 file_size = info.GetSize();
395 SimpleIndex::EntrySet::iterator it = entries->find(hash_key);
396 if (it == entries->end()) {
397 SimpleIndex::InsertInEntrySet(
398 hash_key,
399 EntryMetadata(last_used_time, file_size),
400 entries);
401 } else {
402 // Summing up the total size of the entry through all the *_[0-2] files
403 it->second.SetEntrySize(it->second.GetEntrySize() + file_size);
404 }
405 } 418 }
406
407 out_result->did_load = true; 419 out_result->did_load = true;
408
409 // When we restore from disk we write the merged index file to disk right 420 // When we restore from disk we write the merged index file to disk right
410 // away, this might save us from having to restore again next time. 421 // away, this might save us from having to restore again next time.
411 out_result->flush_required = true; 422 out_result->flush_required = true;
412 } 423 }
413 424
414 // static 425 // static
415 bool SimpleIndexFile::IsIndexFileStale(base::Time cache_last_modified, 426 bool SimpleIndexFile::IsIndexFileStale(base::Time cache_last_modified,
416 const base::FilePath& index_file_path) { 427 const base::FilePath& index_file_path) {
417 base::Time index_mtime; 428 base::Time index_mtime;
418 if (!simple_util::GetMTime(index_file_path, &index_mtime)) 429 if (!simple_util::GetMTime(index_file_path, &index_mtime))
419 return true; 430 return true;
420 return index_mtime < cache_last_modified; 431 return index_mtime < cache_last_modified;
421 } 432 }
422 433
423 } // namespace disk_cache 434 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698