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