15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Performs basic inspection of the disk cache files with minimal disruption 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the actual files (they still may change if an error is detected on the 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// files). 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/tools/dump_cache/dump_files.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/files/file.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/format_macros.h" 209ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/block_files.h" 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/disk_format.h" 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/mapped_file.h" 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/stats.h" 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/storage_block-inl.h" 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/storage_block.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType kIndexName[] = FILE_PATH_LITERAL("index"); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads the |header_size| bytes from the beginning of file |name|. 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ReadHeader(const base::FilePath& name, char* header, int header_size) { 34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::File file(name, base::File::FLAG_OPEN | base::File::FLAG_READ); 35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!file.IsValid()) { 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("Unable to open file %s\n", name.MaybeAsASCII().c_str()); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int read = file.Read(0, header, header_size); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read != header_size) { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("Unable to read file %s\n", name.MaybeAsASCII().c_str()); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int GetMajorVersionFromFile(const base::FilePath& name) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::IndexHeader header; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return header.version >> 16; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Dumps the contents of the Stats record. 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DumpStats(const base::FilePath& path, disk_cache::CacheAddr addr) { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We need a message loop, although we really don't run any task. 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoopForIO loop; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) disk_cache::BlockFiles block_files(path); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!block_files.Init(false)) { 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("Unable to init block files\n"); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) disk_cache::Addr address(addr); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) disk_cache::MappedFile* file = block_files.GetFile(address); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!file) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t length = (2 + disk_cache::Stats::kDataSizesLength) * sizeof(int32) + 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) disk_cache::Stats::MAX_COUNTER * sizeof(int64); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t offset = address.start_block() * address.BlockSize() + 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) disk_cache::kBlockHeaderSize; 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<int32[]> buffer(new int32[length]); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!file->Read(buffer.get(), length, offset)) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("Stats:\nSignatrure: 0x%x\n", buffer[0]); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("Total size: %d\n", buffer[1]); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < disk_cache::Stats::kDataSizesLength; i++) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("Size(%d): %d\n", i, buffer[i + 2]); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64* counters = reinterpret_cast<int64*>( 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer.get() + 2 + disk_cache::Stats::kDataSizesLength); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < disk_cache::Stats::MAX_COUNTER; i++) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("Count(%d): %" PRId64 "\n", i, *counters++); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("-------------------------\n\n"); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Dumps the contents of the Index-file header. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DumpIndexHeader(const base::FilePath& name, 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) disk_cache::CacheAddr* stats_addr) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::IndexHeader header; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Index file:\n"); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("magic: %x\n", header.magic); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("entries: %d\n", header.num_entries); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("total bytes: %d\n", header.num_bytes); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("last file number: %d\n", header.last_file); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("current id: %d\n", header.this_id); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("table length: %d\n", header.table_len); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("last crash: %d\n", header.crash); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("experiment: %d\n", header.experiment); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("stats: %x\n", header.stats); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 5; i++) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("head %d: 0x%x\n", i, header.lru.heads[i]); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("tail %d: 0x%x\n", i, header.lru.tails[i]); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("size %d: 0x%x\n", i, header.lru.sizes[i]); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("transaction: 0x%x\n", header.lru.transaction); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("operation: %d\n", header.lru.operation); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("operation list: %d\n", header.lru.operation_list); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("-------------------------\n\n"); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *stats_addr = header.stats; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Dumps the contents of a block-file header. 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DumpBlockHeader(const base::FilePath& name) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::BlockFileHeader header; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("Block file: %s\n", name.BaseName().MaybeAsASCII().c_str()); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("magic: %x\n", header.magic); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("file id: %d\n", header.this_file); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("next file id: %d\n", header.next_file); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("entry size: %d\n", header.entry_size); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("current entries: %d\n", header.num_entries); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("max entries: %d\n", header.max_entries); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("updating: %d\n", header.updating); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("empty sz 1: %d\n", header.empty[0]); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("empty sz 2: %d\n", header.empty[1]); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("empty sz 3: %d\n", header.empty[2]); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("empty sz 4: %d\n", header.empty[3]); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("user 0: 0x%x\n", header.user[0]); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("user 1: 0x%x\n", header.user[1]); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("user 2: 0x%x\n", header.user[2]); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("user 3: 0x%x\n", header.user[3]); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("-------------------------\n\n"); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple class that interacts with the set of cache files. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CacheDumper { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit CacheDumper(const base::FilePath& path) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : path_(path), 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) block_files_(path), 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_(NULL), 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_hash_(0), 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_addr_(0) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Init(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reads an entry from disk. Return false when all entries have been already 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returned. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool GetEntry(disk_cache::EntryStore* entry); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Loads a specific block from the block files. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool LoadEntry(disk_cache::CacheAddr addr, disk_cache::EntryStore* entry); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool LoadRankings(disk_cache::CacheAddr addr, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::RankingsNode* rankings); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path_; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::BlockFiles block_files_; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<disk_cache::MappedFile> index_file_; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::Index* index_; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int current_hash_; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::CacheAddr next_addr_; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<disk_cache::CacheAddr> dumped_entries_; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(CacheDumper); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CacheDumper::Init() { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!block_files_.Init(false)) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Unable to init block files\n"); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath index_name(path_.Append(kIndexName)); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_file_ = new disk_cache::MappedFile; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_ = reinterpret_cast<disk_cache::Index*>( 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_file_->Init(index_name, 0)); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!index_) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Unable to map index\n"); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CacheDumper::GetEntry(disk_cache::EntryStore* entry) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dumped_entries_.find(next_addr_) != dumped_entries_.end()) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Loop detected\n"); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_addr_ = 0; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_hash_++; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_addr_) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LoadEntry(next_addr_, entry)) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Unable to load entry at address 0x%x\n", next_addr_); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_addr_ = 0; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_hash_++; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = current_hash_; i < index_->header.table_len; i++) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Yes, we'll crash if the table is shorter than expected, but only after 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dumping every entry that we can find. 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index_->table[i]) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_hash_ = i; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LoadEntry(index_->table[i], entry)) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Unable to load entry at address 0x%x\n", index_->table[i]); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CacheDumper::LoadEntry(disk_cache::CacheAddr addr, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::EntryStore* entry) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::Addr address(addr); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::MappedFile* file = block_files_.GetFile(address); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) disk_cache::StorageBlock<disk_cache::EntryStore> entry_block(file, address); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!entry_block.Load()) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(entry, entry_block.Data(), sizeof(*entry)); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Entry at 0x%x\n", addr); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prepare for the next entry to load. 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_addr_ = entry->next; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_addr_) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dumped_entries_.insert(addr); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_hash_++; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dumped_entries_.clear(); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CacheDumper::LoadRankings(disk_cache::CacheAddr addr, 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::RankingsNode* rankings) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::Addr address(addr); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::MappedFile* file = block_files_.GetFile(address); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) disk_cache::StorageBlock<disk_cache::RankingsNode> rank_block(file, address); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!rank_block.Load()) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(rankings, rank_block.Data(), sizeof(*rankings)); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Rankings at 0x%x\n", addr); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DumpEntry(const disk_cache::EntryStore& entry) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string key; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!entry.long_key) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = entry.key; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key.size() > 50) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key.resize(50); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("hash: 0x%x\n", entry.hash); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("next entry: 0x%x\n", entry.next); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("rankings: 0x%x\n", entry.rankings_node); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("key length: %d\n", entry.key_len); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("key: \"%s\"\n", key.c_str()); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("key addr: 0x%x\n", entry.long_key); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("reuse count: %d\n", entry.reuse_count); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("refetch count: %d\n", entry.refetch_count); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("state: %d\n", entry.state); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 4; i++) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("data size %d: %d\n", i, entry.data_size[i]); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("data addr %d: 0x%x\n", i, entry.data_addr[i]); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("----------\n\n"); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DumpRankings(const disk_cache::RankingsNode& rankings) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("next: 0x%x\n", rankings.next); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("prev: 0x%x\n", rankings.prev); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("entry: 0x%x\n", rankings.contents); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("dirty: %d\n", rankings.dirty); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("hash: 0x%x\n", rankings.self_hash); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("----------\n\n"); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------- 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int GetMajorVersion(const base::FilePath& input_path) { 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath index_name(input_path.Append(kIndexName)); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int version = GetMajorVersionFromFile(index_name); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!version) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath data_name(input_path.Append(FILE_PATH_LITERAL("data_0"))); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version != GetMajorVersionFromFile(data_name)) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_name = input_path.Append(FILE_PATH_LITERAL("data_1")); 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (version != GetMajorVersionFromFile(data_name)) 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_name = input_path.Append(FILE_PATH_LITERAL("data_2")); 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (version != GetMajorVersionFromFile(data_name)) 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_name = input_path.Append(FILE_PATH_LITERAL("data_3")); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version != GetMajorVersionFromFile(data_name)) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return version; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Dumps the headers of all files. 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int DumpHeaders(const base::FilePath& input_path) { 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath index_name(input_path.Append(kIndexName)); 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) disk_cache::CacheAddr stats_addr = 0; 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DumpIndexHeader(index_name, &stats_addr); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator iter(input_path, false, 343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator::FILES, 344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FILE_PATH_LITERAL("data_*")); 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (base::FilePath file = iter.Next(); !file.empty(); file = iter.Next()) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpBlockHeader(file); 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DumpStats(input_path, stats_addr); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Dumps all entries from the cache. 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int DumpContents(const base::FilePath& input_path) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpHeaders(input_path); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need a message loop, although we really don't run any task. 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoopForIO loop; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CacheDumper dumper(input_path); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dumper.Init()) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::EntryStore entry; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (dumper.GetEntry(&entry)) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpEntry(entry); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disk_cache::RankingsNode rankings; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dumper.LoadRankings(entry.rankings_node, &rankings)) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpRankings(rankings); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Done.\n"); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 374