| OLD | NEW |
| 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 // Performs basic inspection of the disk cache files with minimal disruption | 5 // Performs basic inspection of the disk cache files with minimal disruption |
| 6 // to the actual files (they still may change if an error is detected on the | 6 // to the actual files (they still may change if an error is detected on the |
| 7 // files). | 7 // files). |
| 8 | 8 |
| 9 #include "net/tools/dump_cache/dump_files.h" | 9 #include "net/tools/dump_cache/dump_files.h" |
| 10 | 10 |
| 11 #include <stdio.h> | 11 #include <stdio.h> |
| 12 | 12 |
| 13 #include <set> | 13 #include <set> |
| 14 #include <string> | 14 #include <string> |
| 15 | 15 |
| 16 #include "base/file_util.h" | 16 #include "base/file_util.h" |
| 17 #include "base/format_macros.h" | 17 #include "base/format_macros.h" |
| 18 #include "base/message_loop.h" | 18 #include "base/message_loop.h" |
| 19 #include "net/base/file_stream.h" | 19 #include "net/base/file_stream.h" |
| 20 #include "net/disk_cache/block_files.h" | 20 #include "net/disk_cache/block_files.h" |
| 21 #include "net/disk_cache/disk_format.h" | 21 #include "net/disk_cache/disk_format.h" |
| 22 #include "net/disk_cache/mapped_file.h" | 22 #include "net/disk_cache/mapped_file.h" |
| 23 #include "net/disk_cache/stats.h" | 23 #include "net/disk_cache/stats.h" |
| 24 #include "net/disk_cache/storage_block.h" | 24 #include "net/disk_cache/storage_block.h" |
| 25 #include "net/disk_cache/storage_block-inl.h" | 25 #include "net/disk_cache/storage_block-inl.h" |
| 26 | 26 |
| 27 namespace disk_cache { |
| 28 typedef StorageBlock<EntryStore> CacheEntryBlock; |
| 29 typedef StorageBlock<RankingsNode> CacheRankingsBlock; |
| 30 } |
| 31 |
| 27 namespace { | 32 namespace { |
| 28 | 33 |
| 29 const base::FilePath::CharType kIndexName[] = FILE_PATH_LITERAL("index"); | 34 const base::FilePath::CharType kIndexName[] = FILE_PATH_LITERAL("index"); |
| 30 | 35 |
| 31 // Reads the |header_size| bytes from the beginning of file |name|. | 36 // Reads the |header_size| bytes from the beginning of file |name|. |
| 32 bool ReadHeader(const base::FilePath& name, char* header, int header_size) { | 37 bool ReadHeader(const base::FilePath& name, char* header, int header_size) { |
| 38 if (name.value().back() == FILE_PATH_LITERAL('d')) |
| 39 return false; |
| 40 |
| 33 net::FileStream file(NULL); | 41 net::FileStream file(NULL); |
| 34 file.OpenSync(name, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); | 42 file.OpenSync(name, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); |
| 35 if (!file.IsOpen()) { | 43 if (!file.IsOpen()) { |
| 36 printf("Unable to open file %s\n", name.MaybeAsASCII().c_str()); | 44 printf("Unable to open file %s\n", name.MaybeAsASCII().c_str()); |
| 37 return false; | 45 return false; |
| 38 } | 46 } |
| 39 | 47 |
| 40 int read = file.ReadSync(header, header_size); | 48 int read = file.ReadSync(header, header_size); |
| 41 if (read != header_size) { | 49 if (read != header_size) { |
| 42 printf("Unable to read file %s\n", name.MaybeAsASCII().c_str()); | 50 printf("Unable to read file %s\n", name.MaybeAsASCII().c_str()); |
| 43 return false; | 51 return false; |
| 44 } | 52 } |
| 45 return true; | 53 return true; |
| 46 } | 54 } |
| 47 | 55 |
| 48 int GetMajorVersionFromFile(const base::FilePath& name) { | 56 int GetMajorVersionFromFile(const base::FilePath& name) { |
| 49 disk_cache::IndexHeader header; | 57 disk_cache::IndexHeader header; |
| 50 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) | 58 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) |
| 51 return 0; | 59 return 0; |
| 52 | 60 |
| 53 return header.version >> 16; | 61 return header.version >> 16; |
| 54 } | 62 } |
| 55 | 63 |
| 56 // Dumps the contents of the Stats record. | 64 // Dumps the contents of the Stats record. |
| 57 void DumpStats(const base::FilePath& path, disk_cache::CacheAddr addr) { | 65 void DumpStats(const base::FilePath& path, disk_cache::CacheAddr addr, |
| 66 int version) { |
| 58 // We need a message loop, although we really don't run any task. | 67 // We need a message loop, although we really don't run any task. |
| 59 MessageLoop loop(MessageLoop::TYPE_IO); | 68 MessageLoop loop(MessageLoop::TYPE_IO); |
| 60 | 69 |
| 61 disk_cache::BlockFiles block_files(path); | 70 disk_cache::BlockFiles block_files(path); |
| 62 if (!block_files.Init(false)) { | 71 int num_files = (version == 2) ? disk_cache::kFirstAdditionalBlockFile : |
| 72 disk_cache::kFirstAdditionalBlockFileV3; |
| 73 if (!block_files.Init(false, num_files)) { |
| 63 printf("Unable to init block files\n"); | 74 printf("Unable to init block files\n"); |
| 64 return; | 75 return; |
| 65 } | 76 } |
| 66 | 77 |
| 67 disk_cache::Addr address(addr); | 78 disk_cache::Addr address(addr); |
| 68 disk_cache::MappedFile* file = block_files.GetFile(address); | 79 disk_cache::MappedFile* file = block_files.GetFile(address); |
| 69 if (!file) | 80 if (!file) |
| 70 return; | 81 return; |
| 71 | 82 |
| 72 size_t length = (2 + disk_cache::Stats::kDataSizesLength) * sizeof(int32) + | 83 size_t length = (2 + disk_cache::Stats::kDataSizesLength) * sizeof(int32) + |
| (...skipping 11 matching lines...) Expand all Loading... |
| 84 for (int i = 0; i < disk_cache::Stats::kDataSizesLength; i++) | 95 for (int i = 0; i < disk_cache::Stats::kDataSizesLength; i++) |
| 85 printf("Size(%d): %d\n", i, buffer[i + 2]); | 96 printf("Size(%d): %d\n", i, buffer[i + 2]); |
| 86 | 97 |
| 87 int64* counters = reinterpret_cast<int64*>( | 98 int64* counters = reinterpret_cast<int64*>( |
| 88 buffer.get() + 2 + disk_cache::Stats::kDataSizesLength); | 99 buffer.get() + 2 + disk_cache::Stats::kDataSizesLength); |
| 89 for (int i = 0; i < disk_cache::Stats::MAX_COUNTER; i++) | 100 for (int i = 0; i < disk_cache::Stats::MAX_COUNTER; i++) |
| 90 printf("Count(%d): %" PRId64 "\n", i, *counters++); | 101 printf("Count(%d): %" PRId64 "\n", i, *counters++); |
| 91 printf("-------------------------\n\n"); | 102 printf("-------------------------\n\n"); |
| 92 } | 103 } |
| 93 | 104 |
| 94 // Dumps the contents of the Index-file header. | 105 // Dumps the contents of the Index-file header. Returns the major version. |
| 95 void DumpIndexHeader(const base::FilePath& name, | 106 int DumpIndexHeader(const base::FilePath& name, |
| 96 disk_cache::CacheAddr* stats_addr) { | 107 disk_cache::CacheAddr* stats_addr) { |
| 97 disk_cache::IndexHeader header; | 108 disk_cache::IndexHeader header; |
| 98 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) | 109 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) |
| 99 return; | 110 return 0; |
| 100 | 111 |
| 101 printf("Index file:\n"); | 112 printf("Index file:\n"); |
| 102 printf("magic: %x\n", header.magic); | 113 printf("magic: %x\n", header.magic); |
| 103 printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff); | 114 printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff); |
| 104 printf("entries: %d\n", header.num_entries); | 115 printf("entries: %d\n", header.num_entries); |
| 105 printf("total bytes: %d\n", header.num_bytes); | 116 printf("total bytes: %d\n", header.num_bytes); |
| 106 printf("last file number: %d\n", header.last_file); | 117 printf("last file number: %d\n", header.last_file); |
| 107 printf("current id: %d\n", header.this_id); | 118 printf("current id: %d\n", header.this_id); |
| 108 printf("table length: %d\n", header.table_len); | 119 printf("table length: %d\n", header.table_len); |
| 109 printf("last crash: %d\n", header.crash); | 120 printf("last crash: %d\n", header.crash); |
| 110 printf("experiment: %d\n", header.experiment); | 121 printf("experiment: %d\n", header.experiment); |
| 111 printf("stats: %x\n", header.stats); | 122 printf("stats: %x\n", header.stats); |
| 112 for (int i = 0; i < 5; i++) { | 123 |
| 113 printf("head %d: 0x%x\n", i, header.lru.heads[i]); | 124 if (header.version >> 16 == 2) { |
| 114 printf("tail %d: 0x%x\n", i, header.lru.tails[i]); | 125 for (int i = 0; i < 5; i++) { |
| 115 printf("size %d: 0x%x\n", i, header.lru.sizes[i]); | 126 printf("head %d: 0x%x\n", i, header.lru.heads[i]); |
| 127 printf("tail %d: 0x%x\n", i, header.lru.tails[i]); |
| 128 printf("size %d: 0x%x\n", i, header.lru.sizes[i]); |
| 129 } |
| 130 printf("transaction: 0x%x\n", header.lru.transaction); |
| 131 printf("operation: %d\n", header.lru.operation); |
| 132 printf("operation list: %d\n", header.lru.operation_list); |
| 133 } else { |
| 134 DumpIndexHeaderPart2(&header); |
| 116 } | 135 } |
| 117 printf("transaction: 0x%x\n", header.lru.transaction); | |
| 118 printf("operation: %d\n", header.lru.operation); | |
| 119 printf("operation list: %d\n", header.lru.operation_list); | |
| 120 printf("-------------------------\n\n"); | 136 printf("-------------------------\n\n"); |
| 121 | 137 |
| 122 *stats_addr = header.stats; | 138 *stats_addr = header.stats; |
| 139 return header.version >> 16; |
| 123 } | 140 } |
| 124 | 141 |
| 125 // Dumps the contents of a block-file header. | 142 // Dumps the contents of a block-file header. |
| 126 void DumpBlockHeader(const base::FilePath& name) { | 143 void DumpBlockHeader(const base::FilePath& name) { |
| 127 disk_cache::BlockFileHeader header; | 144 disk_cache::BlockFileHeader header; |
| 128 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) | 145 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) |
| 129 return; | 146 return; |
| 130 | 147 |
| 131 printf("Block file: %s\n", name.BaseName().MaybeAsASCII().c_str()); | 148 printf("Block file: %s\n", name.BaseName().MaybeAsASCII().c_str()); |
| 132 printf("magic: %x\n", header.magic); | 149 printf("magic: %x\n", header.magic); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 disk_cache::BlockFiles block_files_; | 192 disk_cache::BlockFiles block_files_; |
| 176 scoped_refptr<disk_cache::MappedFile> index_file_; | 193 scoped_refptr<disk_cache::MappedFile> index_file_; |
| 177 disk_cache::Index* index_; | 194 disk_cache::Index* index_; |
| 178 int current_hash_; | 195 int current_hash_; |
| 179 disk_cache::CacheAddr next_addr_; | 196 disk_cache::CacheAddr next_addr_; |
| 180 std::set<disk_cache::CacheAddr> dumped_entries_; | 197 std::set<disk_cache::CacheAddr> dumped_entries_; |
| 181 DISALLOW_COPY_AND_ASSIGN(CacheDumper); | 198 DISALLOW_COPY_AND_ASSIGN(CacheDumper); |
| 182 }; | 199 }; |
| 183 | 200 |
| 184 bool CacheDumper::Init() { | 201 bool CacheDumper::Init() { |
| 185 if (!block_files_.Init(false)) { | 202 if (!block_files_.Init(false, disk_cache::kFirstAdditionalBlockFile)) { |
| 186 printf("Unable to init block files\n"); | 203 printf("Unable to init block files\n"); |
| 187 return false; | 204 return false; |
| 188 } | 205 } |
| 189 | 206 |
| 190 base::FilePath index_name(path_.Append(kIndexName)); | 207 base::FilePath index_name(path_.Append(kIndexName)); |
| 191 index_file_ = new disk_cache::MappedFile; | 208 index_file_ = new disk_cache::MappedFile; |
| 192 index_ = reinterpret_cast<disk_cache::Index*>( | 209 index_ = reinterpret_cast<disk_cache::Index*>( |
| 193 index_file_->Init(index_name, 0)); | 210 index_file_->Init(index_name, 0)); |
| 194 if (!index_) { | 211 if (!index_) { |
| 195 printf("Unable to map index\n"); | 212 printf("Unable to map index\n"); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 if (version != GetMajorVersionFromFile(data_name)) | 347 if (version != GetMajorVersionFromFile(data_name)) |
| 331 return 0; | 348 return 0; |
| 332 | 349 |
| 333 return version; | 350 return version; |
| 334 } | 351 } |
| 335 | 352 |
| 336 // Dumps the headers of all files. | 353 // Dumps the headers of all files. |
| 337 int DumpHeaders(const base::FilePath& input_path) { | 354 int DumpHeaders(const base::FilePath& input_path) { |
| 338 base::FilePath index_name(input_path.Append(kIndexName)); | 355 base::FilePath index_name(input_path.Append(kIndexName)); |
| 339 disk_cache::CacheAddr stats_addr = 0; | 356 disk_cache::CacheAddr stats_addr = 0; |
| 340 DumpIndexHeader(index_name, &stats_addr); | 357 int version = DumpIndexHeader(index_name, &stats_addr); |
| 341 | 358 |
| 342 file_util::FileEnumerator iter(input_path, false, | 359 file_util::FileEnumerator iter(input_path, false, |
| 343 file_util::FileEnumerator::FILES, | 360 file_util::FileEnumerator::FILES, |
| 344 FILE_PATH_LITERAL("data_*")); | 361 FILE_PATH_LITERAL("data_*")); |
| 345 for (base::FilePath file = iter.Next(); !file.empty(); file = iter.Next()) | 362 for (base::FilePath file = iter.Next(); !file.empty(); file = iter.Next()) |
| 346 DumpBlockHeader(file); | 363 DumpBlockHeader(file); |
| 347 | 364 |
| 348 DumpStats(input_path, stats_addr); | 365 DumpStats(input_path, stats_addr, version); |
| 349 return 0; | 366 return 0; |
| 350 } | 367 } |
| 351 | 368 |
| 352 // Dumps all entries from the cache. | 369 // Dumps all entries from the cache. |
| 353 int DumpContents(const base::FilePath& input_path) { | 370 int DumpContentsV2(const base::FilePath& input_path) { |
| 354 DumpHeaders(input_path); | 371 DumpHeaders(input_path); |
| 355 | 372 |
| 356 // We need a message loop, although we really don't run any task. | 373 // We need a message loop, although we really don't run any task. |
| 357 MessageLoop loop(MessageLoop::TYPE_IO); | 374 MessageLoop loop(MessageLoop::TYPE_IO); |
| 358 CacheDumper dumper(input_path); | 375 CacheDumper dumper(input_path); |
| 359 if (!dumper.Init()) | 376 if (!dumper.Init()) |
| 360 return -1; | 377 return -1; |
| 361 | 378 |
| 362 disk_cache::EntryStore entry; | 379 disk_cache::EntryStore entry; |
| 363 while (dumper.GetEntry(&entry)) { | 380 while (dumper.GetEntry(&entry)) { |
| 364 DumpEntry(entry); | 381 DumpEntry(entry); |
| 365 disk_cache::RankingsNode rankings; | 382 disk_cache::RankingsNode rankings; |
| 366 if (dumper.LoadRankings(entry.rankings_node, &rankings)) | 383 if (dumper.LoadRankings(entry.rankings_node, &rankings)) |
| 367 DumpRankings(rankings); | 384 DumpRankings(rankings); |
| 368 } | 385 } |
| 369 | 386 |
| 370 printf("Done.\n"); | 387 printf("Done.\n"); |
| 371 | 388 |
| 372 return 0; | 389 return 0; |
| 373 } | 390 } |
| OLD | NEW |