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

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: Remove uses of vector::data() which is C++11 only 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 <algorithm>
8 #include <cstring>
7 #include <vector> 9 #include <vector>
8 10
9 #include "base/file_util.h" 11 #include "base/file_util.h"
10 #include "base/files/file_enumerator.h"
11 #include "base/files/memory_mapped_file.h" 12 #include "base/files/memory_mapped_file.h"
12 #include "base/hash.h" 13 #include "base/hash.h"
13 #include "base/logging.h" 14 #include "base/logging.h"
14 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
15 #include "base/pickle.h" 16 #include "base/pickle.h"
16 #include "base/single_thread_task_runner.h" 17 #include "base/single_thread_task_runner.h"
17 #include "base/task_runner_util.h" 18 #include "base/task_runner_util.h"
18 #include "base/threading/thread_restrictions.h" 19 #include "base/threading/thread_restrictions.h"
19 #include "net/disk_cache/simple/simple_entry_format.h" 20 #include "net/disk_cache/simple/simple_entry_format.h"
20 #include "net/disk_cache/simple/simple_index.h" 21 #include "net/disk_cache/simple/simple_index.h"
21 #include "net/disk_cache/simple/simple_synchronous_entry.h" 22 #include "net/disk_cache/simple/simple_synchronous_entry.h"
22 #include "net/disk_cache/simple/simple_util.h" 23 #include "net/disk_cache/simple/simple_util.h"
23 #include "third_party/zlib/zlib.h" 24 #include "third_party/zlib/zlib.h"
24 25
26 namespace {
25 27
26 namespace { 28 const int kEntryFilesHashLength = 16;
29 const int kEntryFilesSuffixLength = 2;
27 30
28 const uint64 kMaxEntiresInIndex = 100000000; 31 const uint64 kMaxEntiresInIndex = 100000000;
29 32
30 uint32 CalculatePickleCRC(const Pickle& pickle) { 33 uint32 CalculatePickleCRC(const Pickle& pickle) {
31 return crc32(crc32(0, Z_NULL, 0), 34 return crc32(crc32(0, Z_NULL, 0),
32 reinterpret_cast<const Bytef*>(pickle.payload()), 35 reinterpret_cast<const Bytef*>(pickle.payload()),
33 pickle.payload_size()); 36 pickle.payload_size());
34 } 37 }
35 38
36 void DoomEntrySetReply(const net::CompletionCallback& reply_callback, 39 void DoomEntrySetReply(const net::CompletionCallback& reply_callback,
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 entries->clear(); 341 entries->clear();
339 return; 342 return;
340 } 343 }
341 SimpleIndex::InsertInEntrySet(hash_key, entry_metadata, entries); 344 SimpleIndex::InsertInEntrySet(hash_key, entry_metadata, entries);
342 } 345 }
343 346
344 out_result->did_load = true; 347 out_result->did_load = true;
345 } 348 }
346 349
347 // static 350 // static
351 void SimpleIndexFile::ProcessEntryFile(const std::string& cache_path,
352 std::vector<char>* buffer,
353 SimpleIndex::EntrySet* entries,
354 const char* file_name) {
355 static const size_t kEntryFilesLength =
356 kEntryFilesHashLength + kEntryFilesSuffixLength;
357 const size_t file_name_length = strlen(file_name);
358 if (file_name_length != kEntryFilesLength) {
359 if (strcmp(file_name, "index") && strcmp(file_name, "fake_index"))
pasko 2013/08/21 11:37:56 "the-real-index", reuse constants please
gavinp 2013/08/21 11:49:47 Nit: I know it's well defined as written, but I ca
Philippe 2013/08/21 12:41:38 Yeah, what a shame, I hadn't seen them (in the sam
360 LOG(ERROR) << "unexpected file " << file_name;
361 return;
362 }
363 const size_t kFullPathLength = cache_path.size() + 1 + kEntryFilesLength;
364 if (buffer->size() < kFullPathLength)
365 buffer->resize(kFullPathLength + 1);
366
367 // Note that base::FilePath is not used here to avoid extra heap allocations.
368 std::vector<char>::iterator range_end_it = std::copy(
369 cache_path.begin(), cache_path.end(), buffer->begin());
370 const char* const separator = &base::FilePath::kSeparators[0];
371 range_end_it = std::copy(separator, separator + 1, range_end_it);
372 std::copy(file_name, file_name + file_name_length, range_end_it);
373 const size_t file_name_start_pos = range_end_it - buffer->begin();
374
375 uint64 hash_key = 0;
376 const char* const buffer_data = &buffer->front();
377 const base::StringPiece hash_string(
378 buffer_data + file_name_start_pos, kEntryFilesHashLength);
gavinp 2013/08/21 11:49:47 I don't believe a std::vector<> is guaranteed to b
Philippe 2013/08/21 12:41:38 I got rid of the vector.
379 if (!simple_util::GetEntryHashKeyFromHexString(hash_string, &hash_key)) {
380 LOG(WARNING) << "Invalid entry hash key filename while restoring index from"
381 << " disk: " << file_name;
382 // TODO(felipeg): Should we delete the invalid file here ?
383 return;
384 }
385
386 base::PlatformFileInfo file_info;
387 if (!GetPlatformFileInfo(buffer_data, &file_info)) {
388 LOG(INFO) << "Could not get file info for path " << buffer_data;
389 return;
390 }
391 base::Time last_used_time;
392 #if defined(OS_POSIX)
393 // For POSIX systems, a last access time is available. However, it's not
394 // guaranteed to be more accurate than mtime. It is no worse though.
395 last_used_time = file_info.last_accessed;
396 #endif
397 if (last_used_time.is_null())
398 last_used_time = file_info.last_modified;
399
400 int64 file_size = file_info.size;
401 SimpleIndex::EntrySet::iterator it = entries->find(hash_key);
402 if (it == entries->end()) {
403 SimpleIndex::InsertInEntrySet(
404 hash_key,
405 EntryMetadata(last_used_time, file_size),
406 entries);
407 } else {
408 // Summing up the total size of the entry through all the *_[0-2] files
409 it->second.SetEntrySize(it->second.GetEntrySize() + file_size);
410 }
411 }
412
413 // static
348 void SimpleIndexFile::SyncRestoreFromDisk( 414 void SimpleIndexFile::SyncRestoreFromDisk(
349 const base::FilePath& cache_directory, 415 const base::FilePath& cache_directory,
350 const base::FilePath& index_file_path, 416 const base::FilePath& index_file_path,
351 SimpleIndexLoadResult* out_result) { 417 SimpleIndexLoadResult* out_result) {
352 LOG(INFO) << "Simple Cache Index is being restored from disk."; 418 LOG(INFO) << "Simple Cache Index is being restored from disk.";
353
354 base::DeleteFile(index_file_path, /* recursive = */ false); 419 base::DeleteFile(index_file_path, /* recursive = */ false);
355 out_result->Reset(); 420 out_result->Reset();
356 SimpleIndex::EntrySet* entries = &out_result->entries; 421 SimpleIndex::EntrySet* entries = &out_result->entries;
357 422
358 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format. 423 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format.
359 COMPILE_ASSERT(kSimpleEntryFileCount == 3, 424 COMPILE_ASSERT(kSimpleEntryFileCount == 3,
360 file_pattern_must_match_file_count); 425 file_pattern_must_match_file_count);
361 426
362 const int kFileSuffixLength = sizeof("_0") - 1; 427 const std::string cache_path = cache_directory.value();
pasko 2013/08/21 11:37:56 wstring to string conversion would probably not wo
Philippe 2013/08/21 12:41:38 Yeah we have been slightly paranoiac on this. Meas
363 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]"); 428 std::vector<char> buffer;
364 base::FileEnumerator enumerator(cache_directory, 429 const bool did_succeed = TraverseCacheDirectory(
365 false /* recursive */, 430 cache_path,
366 base::FileEnumerator::FILES, 431 base::Bind(&SimpleIndexFile::ProcessEntryFile, cache_path, &buffer,
367 file_pattern); 432 entries));
368 for (base::FilePath file_path = enumerator.Next(); !file_path.empty(); 433 if (!did_succeed) {
369 file_path = enumerator.Next()) { 434 LOG(ERROR) << "Could not reconstruct index from disk";
370 const base::FilePath::StringType base_name = file_path.BaseName().value(); 435 return;
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 } 436 }
406
407 out_result->did_load = true; 437 out_result->did_load = true;
408
409 // When we restore from disk we write the merged index file to disk right 438 // 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. 439 // away, this might save us from having to restore again next time.
411 out_result->flush_required = true; 440 out_result->flush_required = true;
412 } 441 }
413 442
414 // static 443 // static
415 bool SimpleIndexFile::IsIndexFileStale(base::Time cache_last_modified, 444 bool SimpleIndexFile::IsIndexFileStale(base::Time cache_last_modified,
416 const base::FilePath& index_file_path) { 445 const base::FilePath& index_file_path) {
417 base::Time index_mtime; 446 base::Time index_mtime;
418 if (!simple_util::GetMTime(index_file_path, &index_mtime)) 447 if (!simple_util::GetMTime(index_file_path, &index_mtime))
419 return true; 448 return true;
420 return index_mtime < cache_last_modified; 449 return index_mtime < cache_last_modified;
421 } 450 }
422 451
423 } // namespace disk_cache 452 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698