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 |