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

Side by Side Diff: net/disk_cache/backend_impl.cc

Issue 15203004: Disk cache: Reference CL for the implementation of file format version 3. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 6 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
« no previous file with comments | « net/disk_cache/backend_impl.h ('k') | net/disk_cache/backend_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/backend_impl.h" 5 #include "net/disk_cache/backend_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
11 #include "base/hash.h" 11 #include "base/hash.h"
12 #include "base/message_loop.h" 12 #include "base/message_loop.h"
13 #include "base/metrics/field_trial.h" 13 #include "base/metrics/field_trial.h"
14 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
15 #include "base/metrics/stats_counters.h" 15 #include "base/metrics/stats_counters.h"
16 #include "base/rand_util.h" 16 #include "base/rand_util.h"
17 #include "base/string_util.h" 17 #include "base/string_util.h"
18 #include "base/stringprintf.h" 18 #include "base/stringprintf.h"
19 #include "base/sys_info.h" 19 #include "base/sys_info.h"
20 #include "base/threading/thread_restrictions.h" 20 #include "base/threading/thread_restrictions.h"
21 #include "base/time.h" 21 #include "base/time.h"
22 #include "base/timer.h" 22 #include "base/timer.h"
23 #include "net/base/net_errors.h" 23 #include "net/base/net_errors.h"
24 #include "net/disk_cache/cache_util.h" 24 #include "net/disk_cache/cache_util.h"
25 #include "net/disk_cache/disk_format.h"
25 #include "net/disk_cache/entry_impl.h" 26 #include "net/disk_cache/entry_impl.h"
26 #include "net/disk_cache/errors.h" 27 #include "net/disk_cache/errors.h"
27 #include "net/disk_cache/experiments.h" 28 #include "net/disk_cache/experiments.h"
28 #include "net/disk_cache/file.h" 29 #include "net/disk_cache/file.h"
29 30
30 // This has to be defined before including histogram_macros.h from this file. 31 // This has to be defined before including histogram_macros.h from this file.
31 #define NET_DISK_CACHE_BACKEND_IMPL_CC_ 32 #define NET_DISK_CACHE_BACKEND_IMPL_CC_
32 #include "net/disk_cache/histogram_macros.h" 33 #include "net/disk_cache/histogram_macros.h"
33 34
34 using base::Time; 35 using base::Time;
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 // the id cannot be zero, because that value is used as "not dirty". 278 // the id cannot be zero, because that value is used as "not dirty".
278 // Increasing the value once per second gives us many years before we start 279 // Increasing the value once per second gives us many years before we start
279 // having collisions. 280 // having collisions.
280 data_->header.this_id++; 281 data_->header.this_id++;
281 if (!data_->header.this_id) 282 if (!data_->header.this_id)
282 data_->header.this_id++; 283 data_->header.this_id++;
283 284
284 bool previous_crash = (data_->header.crash != 0); 285 bool previous_crash = (data_->header.crash != 0);
285 data_->header.crash = 1; 286 data_->header.crash = 1;
286 287
287 if (!block_files_.Init(create_files)) 288 if (!block_files_.Init(create_files, kFirstAdditionalBlockFile))
288 return net::ERR_FAILED; 289 return net::ERR_FAILED;
289 290
290 // We want to minimize the changes to cache for an AppCache. 291 // We want to minimize the changes to cache for an AppCache.
291 if (cache_type() == net::APP_CACHE) { 292 if (cache_type() == net::APP_CACHE) {
292 DCHECK(!new_eviction_); 293 DCHECK(!new_eviction_);
293 read_only_ = true; 294 read_only_ = true;
294 } else if (cache_type() == net::SHADER_CACHE) { 295 } else if (cache_type() == net::SHADER_CACHE) {
295 DCHECK(!new_eviction_); 296 DCHECK(!new_eviction_);
296 } 297 }
297 298
298 eviction_.Init(this); 299 eviction_.Init(this);
299 300
300 // stats_ and rankings_ may end up calling back to us so we better be enabled. 301 // stats_ and rankings_ may end up calling back to us so we better be enabled.
301 disabled_ = false; 302 disabled_ = false;
302 if (!stats_.Init(this, &data_->header.stats)) 303 if (!InitStats())
303 return net::ERR_FAILED; 304 return net::ERR_FAILED;
304 305
305 disabled_ = !rankings_.Init(this, new_eviction_); 306 disabled_ = !rankings_.Init(this, new_eviction_);
306 307
307 #if defined(STRESS_CACHE_EXTENDED_VALIDATION) 308 #if defined(STRESS_CACHE_EXTENDED_VALIDATION)
308 trace_object_->EnableTracing(false); 309 trace_object_->EnableTracing(false);
309 int sc = SelfCheck(); 310 int sc = SelfCheck();
310 if (sc < 0 && sc != ERR_NUM_ENTRIES_MISMATCH) 311 if (sc < 0 && sc != ERR_NUM_ENTRIES_MISMATCH)
311 NOTREACHED(); 312 NOTREACHED();
312 trace_object_->EnableTracing(true); 313 trace_object_->EnableTracing(true);
313 #endif 314 #endif
314 315
315 if (previous_crash) { 316 if (previous_crash) {
316 ReportError(ERR_PREVIOUS_CRASH); 317 ReportError(ERR_PREVIOUS_CRASH);
317 } else if (!restarted_) { 318 } else if (!restarted_) {
318 ReportError(ERR_NO_ERROR); 319 ReportError(ERR_NO_ERROR);
319 } 320 }
320 321
321 FlushIndex(); 322 FlushIndex();
322 323
323 return disabled_ ? net::ERR_FAILED : net::OK; 324 return disabled_ ? net::ERR_FAILED : net::OK;
324 } 325 }
325 326
326 void BackendImpl::CleanupCache() { 327 void BackendImpl::CleanupCache() {
327 Trace("Backend Cleanup"); 328 Trace("Backend Cleanup");
328 eviction_.Stop(); 329 eviction_.Stop();
329 timer_.reset(); 330 timer_.reset();
330 331
331 if (init_) { 332 if (init_) {
332 stats_.Store(); 333 StoreStats();
333 if (data_) 334 if (data_)
334 data_->header.crash = 0; 335 data_->header.crash = 0;
335 336
336 if (user_flags_ & kNoRandom) { 337 if (user_flags_ & kNoRandom) {
337 // This is a net_unittest, verify that we are not 'leaking' entries. 338 // This is a net_unittest, verify that we are not 'leaking' entries.
338 File::WaitForPendingIO(&num_pending_io_); 339 File::WaitForPendingIO(&num_pending_io_);
339 DCHECK(!num_refs_); 340 DCHECK(!num_refs_);
340 } else { 341 } else {
341 File::DropPendingIO(); 342 File::DropPendingIO();
342 } 343 }
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 stats_.OnEvent(Stats::FATAL_ERROR); 994 stats_.OnEvent(Stats::FATAL_ERROR);
994 LogStats(); 995 LogStats();
995 ReportError(error); 996 ReportError(error);
996 997
997 // Setting the index table length to an invalid value will force re-creation 998 // Setting the index table length to an invalid value will force re-creation
998 // of the cache files. 999 // of the cache files.
999 data_->header.table_len = 1; 1000 data_->header.table_len = 1;
1000 disabled_ = true; 1001 disabled_ = true;
1001 1002
1002 if (!num_refs_) 1003 if (!num_refs_)
1003 MessageLoop::current()->PostTask(FROM_HERE, 1004 base::MessageLoop::current()->PostTask(
1004 base::Bind(&BackendImpl::RestartCache, GetWeakPtr(), true)); 1005 FROM_HERE, base::Bind(&BackendImpl::RestartCache, GetWeakPtr(), true));
1005 } 1006 }
1006 1007
1007 void BackendImpl::ReportError(int error) { 1008 void BackendImpl::ReportError(int error) {
1008 STRESS_DCHECK(!error || error == ERR_PREVIOUS_CRASH || 1009 STRESS_DCHECK(!error || error == ERR_PREVIOUS_CRASH ||
1009 error == ERR_CACHE_CREATED); 1010 error == ERR_CACHE_CREATED);
1010 1011
1011 // We transmit positive numbers, instead of direct error codes. 1012 // We transmit positive numbers, instead of direct error codes.
1012 DCHECK_LE(error, 0); 1013 DCHECK_LE(error, 0);
1013 CACHE_UMA(CACHE_ERROR, "Error", 0, error * -1); 1014 CACHE_UMA(CACHE_ERROR, "Error", 0, error * -1);
1014 } 1015 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1059 if (!data_) 1060 if (!data_)
1060 first_timer_ = false; 1061 first_timer_ = false;
1061 if (first_timer_) { 1062 if (first_timer_) {
1062 first_timer_ = false; 1063 first_timer_ = false;
1063 if (ShouldReportAgain()) 1064 if (ShouldReportAgain())
1064 ReportStats(); 1065 ReportStats();
1065 } 1066 }
1066 1067
1067 // Save stats to disk at 5 min intervals. 1068 // Save stats to disk at 5 min intervals.
1068 if (time % 10 == 0) 1069 if (time % 10 == 0)
1069 stats_.Store(); 1070 StoreStats();
1070 } 1071 }
1071 1072
1072 void BackendImpl::IncrementIoCount() { 1073 void BackendImpl::IncrementIoCount() {
1073 num_pending_io_++; 1074 num_pending_io_++;
1074 } 1075 }
1075 1076
1076 void BackendImpl::DecrementIoCount() { 1077 void BackendImpl::DecrementIoCount() {
1077 num_pending_io_--; 1078 num_pending_io_--;
1078 } 1079 }
1079 1080
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
1345 1346
1346 if (!table_len) 1347 if (!table_len)
1347 return; 1348 return;
1348 1349
1349 // If we already have a table, adjust the size to it. 1350 // If we already have a table, adjust the size to it.
1350 int current_max_size = MaxStorageSizeForTable(table_len); 1351 int current_max_size = MaxStorageSizeForTable(table_len);
1351 if (max_size_ > current_max_size) 1352 if (max_size_ > current_max_size)
1352 max_size_= current_max_size; 1353 max_size_= current_max_size;
1353 } 1354 }
1354 1355
1356 bool BackendImpl::InitStats() {
1357 Addr address(data_->header.stats);
1358 int size = stats_.StorageSize();
1359
1360 if (!address.is_initialized()) {
1361 FileType file_type = Addr::RequiredFileType(size);
1362 DCHECK_NE(file_type, EXTERNAL);
1363 int num_blocks = Addr::RequiredBlocks(size, file_type);
1364
1365 if (!CreateBlock(file_type, num_blocks, &address))
1366 return false;
1367 return stats_.Init(NULL, 0, address);
1368 }
1369
1370 if (!address.is_block_file()) {
1371 NOTREACHED();
1372 return false;
1373 }
1374
1375 // Load the required data.
1376 size = address.num_blocks() * address.BlockSize();
1377 MappedFile* file = File(address);
1378 if (!file)
1379 return false;
1380
1381 scoped_ptr<char[]> data(new char[size]);
1382 size_t offset = address.start_block() * address.BlockSize() +
1383 kBlockHeaderSize;
1384 if (!file->Read(data.get(), size, offset))
1385 return false;
1386
1387 if (!stats_.Init(data.get(), size, address))
1388 return false;
1389 if (cache_type_ == net::DISK_CACHE && ShouldReportAgain())
1390 stats_.InitSizeHistogram();
1391 return true;
1392 }
1393
1394 void BackendImpl::StoreStats() {
1395 int size = stats_.StorageSize();
1396 scoped_ptr<char[]> data(new char[size]);
1397 Addr address;
1398 size = stats_.SerializeStats(data.get(), size, &address);
1399 DCHECK(size);
1400 if (!address.is_initialized())
1401 return;
1402
1403 MappedFile* file = File(address);
1404 if (!file)
1405 return;
1406
1407 size_t offset = address.start_block() * address.BlockSize() +
1408 kBlockHeaderSize;
1409 file->Write(data.get(), size, offset); // ignore result.
1410 }
1411
1355 void BackendImpl::RestartCache(bool failure) { 1412 void BackendImpl::RestartCache(bool failure) {
1356 int64 errors = stats_.GetCounter(Stats::FATAL_ERROR); 1413 int64 errors = stats_.GetCounter(Stats::FATAL_ERROR);
1357 int64 full_dooms = stats_.GetCounter(Stats::DOOM_CACHE); 1414 int64 full_dooms = stats_.GetCounter(Stats::DOOM_CACHE);
1358 int64 partial_dooms = stats_.GetCounter(Stats::DOOM_RECENT); 1415 int64 partial_dooms = stats_.GetCounter(Stats::DOOM_RECENT);
1359 int64 ga_evictions = stats_.GetCounter(Stats::GAJS_EVICTED);
1360 int64 last_report = stats_.GetCounter(Stats::LAST_REPORT); 1416 int64 last_report = stats_.GetCounter(Stats::LAST_REPORT);
1361 1417
1362 PrepareForRestart(); 1418 PrepareForRestart();
1363 if (failure) { 1419 if (failure) {
1364 DCHECK(!num_refs_); 1420 DCHECK(!num_refs_);
1365 DCHECK(!open_entries_.size()); 1421 DCHECK(!open_entries_.size());
1366 DelayedCacheCleanup(path_); 1422 DelayedCacheCleanup(path_);
1367 } else { 1423 } else {
1368 DeleteCache(path_, false); 1424 DeleteCache(path_, false);
1369 } 1425 }
1370 1426
1371 // Don't call Init() if directed by the unit test: we are simulating a failure 1427 // Don't call Init() if directed by the unit test: we are simulating a failure
1372 // trying to re-enable the cache. 1428 // trying to re-enable the cache.
1373 if (unit_test_) 1429 if (unit_test_)
1374 init_ = true; // Let the destructor do proper cleanup. 1430 init_ = true; // Let the destructor do proper cleanup.
1375 else if (SyncInit() == net::OK) { 1431 else if (SyncInit() == net::OK) {
1376 stats_.SetCounter(Stats::FATAL_ERROR, errors); 1432 stats_.SetCounter(Stats::FATAL_ERROR, errors);
1377 stats_.SetCounter(Stats::DOOM_CACHE, full_dooms); 1433 stats_.SetCounter(Stats::DOOM_CACHE, full_dooms);
1378 stats_.SetCounter(Stats::DOOM_RECENT, partial_dooms); 1434 stats_.SetCounter(Stats::DOOM_RECENT, partial_dooms);
1379 stats_.SetCounter(Stats::GAJS_EVICTED, ga_evictions);
1380 stats_.SetCounter(Stats::LAST_REPORT, last_report); 1435 stats_.SetCounter(Stats::LAST_REPORT, last_report);
1381 } 1436 }
1382 } 1437 }
1383 1438
1384 void BackendImpl::PrepareForRestart() { 1439 void BackendImpl::PrepareForRestart() {
1385 // Reset the mask_ if it was not given by the user. 1440 // Reset the mask_ if it was not given by the user.
1386 if (!(user_flags_ & kMask)) 1441 if (!(user_flags_ & kMask))
1387 mask_ = 0; 1442 mask_ = 0;
1388 1443
1389 if (!(user_flags_ & kNewEviction)) 1444 if (!(user_flags_ & kNewEviction))
(...skipping 15 matching lines...) Expand all
1405 if (it != open_entries_.end()) { 1460 if (it != open_entries_.end()) {
1406 // Easy job. This entry is already in memory. 1461 // Easy job. This entry is already in memory.
1407 EntryImpl* this_entry = it->second; 1462 EntryImpl* this_entry = it->second;
1408 this_entry->AddRef(); 1463 this_entry->AddRef();
1409 *entry = this_entry; 1464 *entry = this_entry;
1410 return 0; 1465 return 0;
1411 } 1466 }
1412 1467
1413 STRESS_DCHECK(block_files_.IsValid(address)); 1468 STRESS_DCHECK(block_files_.IsValid(address));
1414 1469
1415 if (!address.SanityCheckForEntry()) { 1470 if (!address.SanityCheckForEntryV2()) {
1416 LOG(WARNING) << "Wrong entry address."; 1471 LOG(WARNING) << "Wrong entry address.";
1417 STRESS_NOTREACHED(); 1472 STRESS_NOTREACHED();
1418 return ERR_INVALID_ADDRESS; 1473 return ERR_INVALID_ADDRESS;
1419 } 1474 }
1420 1475
1421 scoped_refptr<EntryImpl> cache_entry( 1476 scoped_refptr<EntryImpl> cache_entry(
1422 new EntryImpl(this, address, read_only_)); 1477 new EntryImpl(this, address, read_only_));
1423 IncreaseNumRefs(); 1478 IncreaseNumRefs();
1424 *entry = NULL; 1479 *entry = NULL;
1425 1480
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
1772 num_refs_++; 1827 num_refs_++;
1773 if (max_refs_ < num_refs_) 1828 if (max_refs_ < num_refs_)
1774 max_refs_ = num_refs_; 1829 max_refs_ = num_refs_;
1775 } 1830 }
1776 1831
1777 void BackendImpl::DecreaseNumRefs() { 1832 void BackendImpl::DecreaseNumRefs() {
1778 DCHECK(num_refs_); 1833 DCHECK(num_refs_);
1779 num_refs_--; 1834 num_refs_--;
1780 1835
1781 if (!num_refs_ && disabled_) 1836 if (!num_refs_ && disabled_)
1782 MessageLoop::current()->PostTask(FROM_HERE, 1837 base::MessageLoop::current()->PostTask(
1783 base::Bind(&BackendImpl::RestartCache, GetWeakPtr(), true)); 1838 FROM_HERE, base::Bind(&BackendImpl::RestartCache, GetWeakPtr(), true));
1784 } 1839 }
1785 1840
1786 void BackendImpl::IncreaseNumEntries() { 1841 void BackendImpl::IncreaseNumEntries() {
1787 data_->header.num_entries++; 1842 data_->header.num_entries++;
1788 DCHECK_GT(data_->header.num_entries, 0); 1843 DCHECK_GT(data_->header.num_entries, 0);
1789 } 1844 }
1790 1845
1791 void BackendImpl::DecreaseNumEntries() { 1846 void BackendImpl::DecreaseNumEntries() {
1792 data_->header.num_entries--; 1847 data_->header.num_entries--;
1793 if (data_->header.num_entries < 0) { 1848 if (data_->header.num_entries < 0) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1827 CACHE_UMA(COUNTS_10000, "MaxOpenEntries2", 0, 1882 CACHE_UMA(COUNTS_10000, "MaxOpenEntries2", 0,
1828 static_cast<int>(stats_.GetCounter(Stats::MAX_ENTRIES))); 1883 static_cast<int>(stats_.GetCounter(Stats::MAX_ENTRIES)));
1829 stats_.SetCounter(Stats::MAX_ENTRIES, 0); 1884 stats_.SetCounter(Stats::MAX_ENTRIES, 0);
1830 1885
1831 CACHE_UMA(COUNTS_10000, "TotalFatalErrors", 0, 1886 CACHE_UMA(COUNTS_10000, "TotalFatalErrors", 0,
1832 static_cast<int>(stats_.GetCounter(Stats::FATAL_ERROR))); 1887 static_cast<int>(stats_.GetCounter(Stats::FATAL_ERROR)));
1833 CACHE_UMA(COUNTS_10000, "TotalDoomCache", 0, 1888 CACHE_UMA(COUNTS_10000, "TotalDoomCache", 0,
1834 static_cast<int>(stats_.GetCounter(Stats::DOOM_CACHE))); 1889 static_cast<int>(stats_.GetCounter(Stats::DOOM_CACHE)));
1835 CACHE_UMA(COUNTS_10000, "TotalDoomRecentEntries", 0, 1890 CACHE_UMA(COUNTS_10000, "TotalDoomRecentEntries", 0,
1836 static_cast<int>(stats_.GetCounter(Stats::DOOM_RECENT))); 1891 static_cast<int>(stats_.GetCounter(Stats::DOOM_RECENT)));
1837 CACHE_UMA(COUNTS_10000, "TotalEvictionsGaJs", 0,
1838 static_cast<int>(stats_.GetCounter(Stats::GAJS_EVICTED)));
1839 stats_.SetCounter(Stats::FATAL_ERROR, 0); 1892 stats_.SetCounter(Stats::FATAL_ERROR, 0);
1840 stats_.SetCounter(Stats::DOOM_CACHE, 0); 1893 stats_.SetCounter(Stats::DOOM_CACHE, 0);
1841 stats_.SetCounter(Stats::DOOM_RECENT, 0); 1894 stats_.SetCounter(Stats::DOOM_RECENT, 0);
1842 stats_.SetCounter(Stats::GAJS_EVICTED, 0);
1843 1895
1844 int64 total_hours = stats_.GetCounter(Stats::TIMER) / 120; 1896 int64 total_hours = stats_.GetCounter(Stats::TIMER) / 120;
1845 if (!data_->header.create_time || !data_->header.lru.filled) { 1897 if (!data_->header.create_time || !data_->header.lru.filled) {
1846 int cause = data_->header.create_time ? 0 : 1; 1898 int cause = data_->header.create_time ? 0 : 1;
1847 if (!data_->header.lru.filled) 1899 if (!data_->header.lru.filled)
1848 cause |= 2; 1900 cause |= 2;
1849 CACHE_UMA(CACHE_ERROR, "ShortReport", 0, cause); 1901 CACHE_UMA(CACHE_ERROR, "ShortReport", 0, cause);
1850 CACHE_UMA(HOURS, "TotalTimeNotFull", 0, static_cast<int>(total_hours)); 1902 CACHE_UMA(HOURS, "TotalTimeNotFull", 0, static_cast<int>(total_hours));
1851 return; 1903 return;
1852 } 1904 }
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
2054 if (total_memory > kMaxBuffersSize || total_memory <= 0) 2106 if (total_memory > kMaxBuffersSize || total_memory <= 0)
2055 total_memory = kMaxBuffersSize; 2107 total_memory = kMaxBuffersSize;
2056 2108
2057 done = true; 2109 done = true;
2058 } 2110 }
2059 2111
2060 return static_cast<int>(total_memory); 2112 return static_cast<int>(total_memory);
2061 } 2113 }
2062 2114
2063 } // namespace disk_cache 2115 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/backend_impl.h ('k') | net/disk_cache/backend_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698