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

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: Fix windows build (part 2) 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 kIndexFileName[] = "the-real-index";
33 const char kTempIndexFileName[] = "temp-index";
34
30 uint32 CalculatePickleCRC(const Pickle& pickle) { 35 uint32 CalculatePickleCRC(const Pickle& pickle) {
31 return crc32(crc32(0, Z_NULL, 0), 36 return crc32(crc32(0, Z_NULL, 0),
32 reinterpret_cast<const Bytef*>(pickle.payload()), 37 reinterpret_cast<const Bytef*>(pickle.payload()),
33 pickle.payload_size()); 38 pickle.payload_size());
34 } 39 }
35 40
36 void DoomEntrySetReply(const net::CompletionCallback& reply_callback, 41 void DoomEntrySetReply(const net::CompletionCallback& reply_callback,
37 int result) { 42 int result) {
38 reply_callback.Run(result); 43 reply_callback.Run(result);
39 } 44 }
(...skipping 20 matching lines...) Expand all
60 } 65 }
61 if (app_on_background) { 66 if (app_on_background) {
62 UMA_HISTOGRAM_TIMES("SimpleCache.IndexWriteToDiskTime.Background", 67 UMA_HISTOGRAM_TIMES("SimpleCache.IndexWriteToDiskTime.Background",
63 (base::TimeTicks::Now() - start_time)); 68 (base::TimeTicks::Now() - start_time));
64 } else { 69 } else {
65 UMA_HISTOGRAM_TIMES("SimpleCache.IndexWriteToDiskTime.Foreground", 70 UMA_HISTOGRAM_TIMES("SimpleCache.IndexWriteToDiskTime.Foreground",
66 (base::TimeTicks::Now() - start_time)); 71 (base::TimeTicks::Now() - start_time));
67 } 72 }
68 } 73 }
69 74
75 // Called for each cache directory traversal iteration.
76 void ProcessEntryFile(SimpleIndex::EntrySet* entries,
77 const base::FilePath& file_path) {
78 static const size_t kEntryFilesLength =
79 kEntryFilesHashLength + kEntryFilesSuffixLength;
80 // Converting to std::string is OK since we never use UTF8 wide chars in our
81 // file names.
82 const base::FilePath::StringType base_name = file_path.BaseName().value();
83 const std::string file_name(base_name.begin(), base_name.end());
84 if (file_name.size() != kEntryFilesLength)
85 return;
86 const base::StringPiece hash_string(
87 file_name.begin(), file_name.begin() + kEntryFilesHashLength);
88 uint64 hash_key = 0;
89 if (!simple_util::GetEntryHashKeyFromHexString(hash_string, &hash_key)) {
90 LOG(WARNING) << "Invalid entry hash key filename while restoring index from"
91 << " disk: " << file_name;
92 return;
93 }
94
95 base::PlatformFileInfo file_info;
96 if (!file_util::GetFileInfo(file_path, &file_info)) {
97 LOG(ERROR) << "Could not get file info for " << file_path.value();
98 return;
99 }
100 base::Time last_used_time;
101 #if defined(OS_POSIX)
102 // For POSIX systems, a last access time is available. However, it's not
103 // guaranteed to be more accurate than mtime. It is no worse though.
104 last_used_time = file_info.last_accessed;
105 #endif
106 if (last_used_time.is_null())
107 last_used_time = file_info.last_modified;
108
109 int64 file_size = file_info.size;
110 SimpleIndex::EntrySet::iterator it = entries->find(hash_key);
111 if (it == entries->end()) {
112 SimpleIndex::InsertInEntrySet(
113 hash_key,
114 EntryMetadata(last_used_time, file_size),
115 entries);
116 } else {
117 // Summing up the total size of the entry through all the *_[0-2] files
118 it->second.SetEntrySize(it->second.GetEntrySize() + file_size);
119 }
120 }
121
70 } // namespace 122 } // namespace
71 123
72 namespace disk_cache {
73
74 SimpleIndexLoadResult::SimpleIndexLoadResult() : did_load(false), 124 SimpleIndexLoadResult::SimpleIndexLoadResult() : did_load(false),
75 flush_required(false) { 125 flush_required(false) {
76 } 126 }
77 127
78 SimpleIndexLoadResult::~SimpleIndexLoadResult() { 128 SimpleIndexLoadResult::~SimpleIndexLoadResult() {
79 } 129 }
80 130
81 void SimpleIndexLoadResult::Reset() { 131 void SimpleIndexLoadResult::Reset() {
82 did_load = false; 132 did_load = false;
83 flush_required = false; 133 flush_required = false;
84 entries.clear(); 134 entries.clear();
85 } 135 }
86 136
87 // static
88 const char SimpleIndexFile::kIndexFileName[] = "the-real-index";
89 // static
90 const char SimpleIndexFile::kTempIndexFileName[] = "temp-index";
91
92 SimpleIndexFile::IndexMetadata::IndexMetadata() : 137 SimpleIndexFile::IndexMetadata::IndexMetadata() :
93 magic_number_(kSimpleIndexMagicNumber), 138 magic_number_(kSimpleIndexMagicNumber),
94 version_(kSimpleVersion), 139 version_(kSimpleVersion),
95 number_of_entries_(0), 140 number_of_entries_(0),
96 cache_size_(0) {} 141 cache_size_(0) {}
97 142
98 SimpleIndexFile::IndexMetadata::IndexMetadata( 143 SimpleIndexFile::IndexMetadata::IndexMetadata(
99 uint64 number_of_entries, uint64 cache_size) : 144 uint64 number_of_entries, uint64 cache_size) :
100 magic_number_(kSimpleIndexMagicNumber), 145 magic_number_(kSimpleIndexMagicNumber),
101 version_(kSimpleVersion), 146 version_(kSimpleVersion),
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 388
344 out_result->did_load = true; 389 out_result->did_load = true;
345 } 390 }
346 391
347 // static 392 // static
348 void SimpleIndexFile::SyncRestoreFromDisk( 393 void SimpleIndexFile::SyncRestoreFromDisk(
349 const base::FilePath& cache_directory, 394 const base::FilePath& cache_directory,
350 const base::FilePath& index_file_path, 395 const base::FilePath& index_file_path,
351 SimpleIndexLoadResult* out_result) { 396 SimpleIndexLoadResult* out_result) {
352 LOG(INFO) << "Simple Cache Index is being restored from disk."; 397 LOG(INFO) << "Simple Cache Index is being restored from disk.";
353
354 base::DeleteFile(index_file_path, /* recursive = */ false); 398 base::DeleteFile(index_file_path, /* recursive = */ false);
355 out_result->Reset(); 399 out_result->Reset();
356 SimpleIndex::EntrySet* entries = &out_result->entries; 400 SimpleIndex::EntrySet* entries = &out_result->entries;
357 401
358 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format. 402 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format.
359 COMPILE_ASSERT(kSimpleEntryFileCount == 3, 403 COMPILE_ASSERT(kSimpleEntryFileCount == 3,
360 file_pattern_must_match_file_count); 404 file_pattern_must_match_file_count);
361 405
362 const int kFileSuffixLength = sizeof("_0") - 1; 406 const bool did_succeed = TraverseCacheDirectory(
363 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]"); 407 cache_directory, base::Bind(&ProcessEntryFile, entries));
364 base::FileEnumerator enumerator(cache_directory, 408 if (!did_succeed) {
365 false /* recursive */, 409 LOG(ERROR) << "Could not reconstruct index from disk";
366 base::FileEnumerator::FILES, 410 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 } 411 }
406
407 out_result->did_load = true; 412 out_result->did_load = true;
408
409 // When we restore from disk we write the merged index file to disk right 413 // 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. 414 // away, this might save us from having to restore again next time.
411 out_result->flush_required = true; 415 out_result->flush_required = true;
412 } 416 }
413 417
414 // static 418 // static
415 bool SimpleIndexFile::IsIndexFileStale(base::Time cache_last_modified, 419 bool SimpleIndexFile::IsIndexFileStale(base::Time cache_last_modified,
416 const base::FilePath& index_file_path) { 420 const base::FilePath& index_file_path) {
417 base::Time index_mtime; 421 base::Time index_mtime;
418 if (!simple_util::GetMTime(index_file_path, &index_mtime)) 422 if (!simple_util::GetMTime(index_file_path, &index_mtime))
419 return true; 423 return true;
420 return index_mtime < cache_last_modified; 424 return index_mtime < cache_last_modified;
421 } 425 }
422 426
423 } // namespace disk_cache 427 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/simple/simple_index_file.h ('k') | net/disk_cache/simple/simple_index_file_posix.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698