OLD | NEW |
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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 <stdio.h> | 9 #include <stdio.h> |
10 #include <string> | 10 #include <string> |
11 | 11 |
12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
14 #include "net/base/file_stream.h" | 14 #include "net/base/file_stream.h" |
15 #include "net/disk_cache/block_files.h" | 15 #include "net/disk_cache/block_files.h" |
16 #include "net/disk_cache/disk_format.h" | 16 #include "net/disk_cache/disk_format.h" |
17 #include "net/disk_cache/mapped_file.h" | 17 #include "net/disk_cache/mapped_file.h" |
18 #include "net/disk_cache/storage_block.h" | 18 #include "net/disk_cache/storage_block.h" |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
22 const wchar_t kIndexName[] = L"index"; | 22 const wchar_t kIndexName[] = L"index"; |
23 const wchar_t kDataPrefix[] = L"data_"; | 23 const wchar_t kDataPrefix[] = L"data_"; |
24 | 24 |
25 // Reads the |header_size| bytes from the beginning of file |name|. | 25 // Reads the |header_size| bytes from the beginning of file |name|. |
26 bool ReadHeader(const std::wstring name, char* header, int header_size) { | 26 bool ReadHeader(const std::wstring& name, char* header, int header_size) { |
27 net::FileStream file; | 27 net::FileStream file; |
28 file.Open(FilePath::FromWStringHack(name), | 28 file.Open(FilePath::FromWStringHack(name), |
29 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); | 29 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); |
30 if (!file.IsOpen()) { | 30 if (!file.IsOpen()) { |
31 printf("Unable to open file %ls\n", name.c_str()); | 31 printf("Unable to open file %ls\n", name.c_str()); |
32 return false; | 32 return false; |
33 } | 33 } |
34 | 34 |
35 int read = file.Read(header, header_size, NULL); | 35 int read = file.Read(header, header_size, NULL); |
36 if (read != header_size) { | 36 if (read != header_size) { |
37 printf("Unable to read file %ls\n", name.c_str()); | 37 printf("Unable to read file %ls\n", name.c_str()); |
38 return false; | 38 return false; |
39 } | 39 } |
40 return true; | 40 return true; |
41 } | 41 } |
42 | 42 |
43 int GetMajorVersionFromFile(const std::wstring name) { | 43 int GetMajorVersionFromFile(const std::wstring& name) { |
44 disk_cache::IndexHeader header; | 44 disk_cache::IndexHeader header; |
45 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) | 45 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) |
46 return 0; | 46 return 0; |
47 | 47 |
48 return header.version >> 16; | 48 return header.version >> 16; |
49 } | 49 } |
50 | 50 |
51 // Dumps the contents of the Index-file header. | 51 // Dumps the contents of the Index-file header. |
52 void DumpIndexHeader(const std::wstring name) { | 52 void DumpIndexHeader(const std::wstring& name) { |
53 disk_cache::IndexHeader header; | 53 disk_cache::IndexHeader header; |
54 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) | 54 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) |
55 return; | 55 return; |
56 | 56 |
57 printf("Index file:\n"); | 57 printf("Index file:\n"); |
58 printf("magic: %x\n", header.magic); | 58 printf("magic: %x\n", header.magic); |
59 printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff); | 59 printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff); |
60 printf("entries: %d\n", header.num_entries); | 60 printf("entries: %d\n", header.num_entries); |
61 printf("total bytes: %d\n", header.num_bytes); | 61 printf("total bytes: %d\n", header.num_bytes); |
62 printf("last file number: %d\n", header.last_file); | 62 printf("last file number: %d\n", header.last_file); |
63 printf("current id: %d\n", header.this_id); | 63 printf("current id: %d\n", header.this_id); |
64 printf("table length: %d\n", header.table_len); | 64 printf("table length: %d\n", header.table_len); |
65 printf("last crash: %d\n", header.crash); | 65 printf("last crash: %d\n", header.crash); |
66 printf("experiment: %d\n", header.experiment); | 66 printf("experiment: %d\n", header.experiment); |
67 for (int i = 0; i < 5; i++) { | 67 for (int i = 0; i < 5; i++) { |
68 printf("head %d: 0x%x\n", i, header.lru.heads[i]); | 68 printf("head %d: 0x%x\n", i, header.lru.heads[i]); |
69 printf("tail %d: 0x%x\n", i, header.lru.tails[i]); | 69 printf("tail %d: 0x%x\n", i, header.lru.tails[i]); |
70 } | 70 } |
71 printf("transaction: 0x%x\n", header.lru.transaction); | 71 printf("transaction: 0x%x\n", header.lru.transaction); |
72 printf("operation: %d\n", header.lru.operation); | 72 printf("operation: %d\n", header.lru.operation); |
73 printf("operation list: %d\n", header.lru.operation_list); | 73 printf("operation list: %d\n", header.lru.operation_list); |
74 printf("-------------------------\n\n"); | 74 printf("-------------------------\n\n"); |
75 } | 75 } |
76 | 76 |
77 // Dumps the contents of a block-file header. | 77 // Dumps the contents of a block-file header. |
78 void DumpBlockHeader(const std::wstring name) { | 78 void DumpBlockHeader(const std::wstring& name) { |
79 disk_cache::BlockFileHeader header; | 79 disk_cache::BlockFileHeader header; |
80 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) | 80 if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) |
81 return; | 81 return; |
82 | 82 |
83 std::wstring file_name = file_util::GetFilenameFromPath(name); | 83 std::wstring file_name = file_util::GetFilenameFromPath(name); |
84 | 84 |
85 printf("Block file: %ls\n", file_name.c_str()); | 85 printf("Block file: %ls\n", file_name.c_str()); |
86 printf("magic: %x\n", header.magic); | 86 printf("magic: %x\n", header.magic); |
87 printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff); | 87 printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff); |
88 printf("file id: %d\n", header.this_file); | 88 printf("file id: %d\n", header.this_file); |
89 printf("next file id: %d\n", header.next_file); | 89 printf("next file id: %d\n", header.next_file); |
90 printf("entry size: %d\n", header.entry_size); | 90 printf("entry size: %d\n", header.entry_size); |
91 printf("current entries: %d\n", header.num_entries); | 91 printf("current entries: %d\n", header.num_entries); |
92 printf("max entries: %d\n", header.max_entries); | 92 printf("max entries: %d\n", header.max_entries); |
93 printf("updating: %d\n", header.updating); | 93 printf("updating: %d\n", header.updating); |
94 printf("empty sz 1: %d\n", header.empty[0]); | 94 printf("empty sz 1: %d\n", header.empty[0]); |
95 printf("empty sz 2: %d\n", header.empty[1]); | 95 printf("empty sz 2: %d\n", header.empty[1]); |
96 printf("empty sz 3: %d\n", header.empty[2]); | 96 printf("empty sz 3: %d\n", header.empty[2]); |
97 printf("empty sz 4: %d\n", header.empty[3]); | 97 printf("empty sz 4: %d\n", header.empty[3]); |
98 printf("user 0: 0x%x\n", header.user[0]); | 98 printf("user 0: 0x%x\n", header.user[0]); |
99 printf("user 1: 0x%x\n", header.user[1]); | 99 printf("user 1: 0x%x\n", header.user[1]); |
100 printf("user 2: 0x%x\n", header.user[2]); | 100 printf("user 2: 0x%x\n", header.user[2]); |
101 printf("user 3: 0x%x\n", header.user[3]); | 101 printf("user 3: 0x%x\n", header.user[3]); |
102 printf("-------------------------\n\n"); | 102 printf("-------------------------\n\n"); |
103 } | 103 } |
104 | 104 |
105 // Simple class that interacts with the set of cache files. | 105 // Simple class that interacts with the set of cache files. |
106 class CacheDumper { | 106 class CacheDumper { |
107 public: | 107 public: |
108 explicit CacheDumper(const std::wstring path) | 108 explicit CacheDumper(const std::wstring& path) |
109 : path_(path), block_files_(path), index_(NULL) {} | 109 : path_(path), block_files_(path), index_(NULL) {} |
110 | 110 |
111 bool Init(); | 111 bool Init(); |
112 | 112 |
113 // Reads an entry from disk. Return false when all entries have been already | 113 // Reads an entry from disk. Return false when all entries have been already |
114 // returned. | 114 // returned. |
115 bool GetEntry(disk_cache::EntryStore* entry); | 115 bool GetEntry(disk_cache::EntryStore* entry); |
116 | 116 |
117 // Loads a specific block from the block files. | 117 // Loads a specific block from the block files. |
118 bool LoadEntry(disk_cache::CacheAddr addr, disk_cache::EntryStore* entry); | 118 bool LoadEntry(disk_cache::CacheAddr addr, disk_cache::EntryStore* entry); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 printf("entry: 0x%x\n", rankings.contents); | 244 printf("entry: 0x%x\n", rankings.contents); |
245 printf("dirty: %d\n", rankings.dirty); | 245 printf("dirty: %d\n", rankings.dirty); |
246 printf("pointer: 0x%x\n", rankings.pointer); | 246 printf("pointer: 0x%x\n", rankings.pointer); |
247 printf("----------\n\n"); | 247 printf("----------\n\n"); |
248 } | 248 } |
249 | 249 |
250 } // namespace. | 250 } // namespace. |
251 | 251 |
252 // ----------------------------------------------------------------------- | 252 // ----------------------------------------------------------------------- |
253 | 253 |
254 int GetMajorVersion(const std::wstring input_path) { | 254 int GetMajorVersion(const std::wstring& input_path) { |
255 std::wstring index_name(input_path); | 255 std::wstring index_name(input_path); |
256 file_util::AppendToPath(&index_name, kIndexName); | 256 file_util::AppendToPath(&index_name, kIndexName); |
257 | 257 |
258 int version = GetMajorVersionFromFile(index_name); | 258 int version = GetMajorVersionFromFile(index_name); |
259 if (!version) | 259 if (!version) |
260 return 0; | 260 return 0; |
261 | 261 |
262 std::wstring data_name(input_path); | 262 std::wstring data_name(input_path); |
263 file_util::AppendToPath(&data_name, L"data_0"); | 263 file_util::AppendToPath(&data_name, L"data_0"); |
264 if (version != GetMajorVersionFromFile(data_name)) | 264 if (version != GetMajorVersionFromFile(data_name)) |
265 return 0; | 265 return 0; |
266 | 266 |
267 data_name = input_path; | 267 data_name = input_path; |
268 file_util::AppendToPath(&data_name, L"data_1"); | 268 file_util::AppendToPath(&data_name, L"data_1"); |
269 if (version != GetMajorVersionFromFile(data_name)) | 269 if (version != GetMajorVersionFromFile(data_name)) |
270 return 0; | 270 return 0; |
271 | 271 |
272 return version; | 272 return version; |
273 } | 273 } |
274 | 274 |
275 // Dumps the headers of all files. | 275 // Dumps the headers of all files. |
276 int DumpHeaders(const std::wstring input_path) { | 276 int DumpHeaders(const std::wstring& input_path) { |
277 std::wstring index_name(input_path); | 277 std::wstring index_name(input_path); |
278 file_util::AppendToPath(&index_name, kIndexName); | 278 file_util::AppendToPath(&index_name, kIndexName); |
279 DumpIndexHeader(index_name); | 279 DumpIndexHeader(index_name); |
280 | 280 |
281 std::wstring pattern(kDataPrefix); | 281 std::wstring pattern(kDataPrefix); |
282 pattern.append(L"*"); | 282 pattern.append(L"*"); |
283 file_util::FileEnumerator iter(FilePath::FromWStringHack(input_path), false, | 283 file_util::FileEnumerator iter(FilePath::FromWStringHack(input_path), false, |
284 file_util::FileEnumerator::FILES, pattern); | 284 file_util::FileEnumerator::FILES, pattern); |
285 for (std::wstring file = iter.Next().ToWStringHack(); !file.empty(); | 285 for (std::wstring file = iter.Next().ToWStringHack(); !file.empty(); |
286 file = iter.Next().ToWStringHack()) { | 286 file = iter.Next().ToWStringHack()) { |
287 DumpBlockHeader(file); | 287 DumpBlockHeader(file); |
288 } | 288 } |
289 | 289 |
290 return 0; | 290 return 0; |
291 } | 291 } |
292 | 292 |
293 // Dumps all entries from the cache. | 293 // Dumps all entries from the cache. |
294 int DumpContents(const std::wstring input_path) { | 294 int DumpContents(const std::wstring& input_path) { |
295 DumpHeaders(input_path); | 295 DumpHeaders(input_path); |
296 | 296 |
297 // We need a message loop, although we really don't run any task. | 297 // We need a message loop, although we really don't run any task. |
298 MessageLoop loop(MessageLoop::TYPE_IO); | 298 MessageLoop loop(MessageLoop::TYPE_IO); |
299 CacheDumper dumper(input_path); | 299 CacheDumper dumper(input_path); |
300 if (!dumper.Init()) | 300 if (!dumper.Init()) |
301 return -1; | 301 return -1; |
302 | 302 |
303 disk_cache::EntryStore entry; | 303 disk_cache::EntryStore entry; |
304 while (dumper.GetEntry(&entry)) { | 304 while (dumper.GetEntry(&entry)) { |
305 DumpEntry(entry); | 305 DumpEntry(entry); |
306 disk_cache::RankingsNode rankings; | 306 disk_cache::RankingsNode rankings; |
307 if (dumper.LoadRankings(entry.rankings_node, &rankings)) | 307 if (dumper.LoadRankings(entry.rankings_node, &rankings)) |
308 DumpRankings(rankings); | 308 DumpRankings(rankings); |
309 } | 309 } |
310 | 310 |
311 printf("Done.\n"); | 311 printf("Done.\n"); |
312 | 312 |
313 return 0; | 313 return 0; |
314 } | 314 } |
OLD | NEW |