13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Performs basic inspection of the disk cache files with minimal disruption 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to the actual files (they still may change if an error is detected on the 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// files). 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <set> 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdio.h> 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string> 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_util.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h" 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/file_stream.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/block_files.h" 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/disk_format.h" 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/mapped_file.h" 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/storage_block.h" 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst wchar_t kIndexName[] = L"index"; 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst wchar_t kDataPrefix[] = L"data_"; 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Reads the |header_size| bytes from the beginning of file |name|. 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ReadHeader(const std::wstring& name, char* header, int header_size) { 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott net::FileStream file; 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file.Open(FilePath::FromWStringHack(name), 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!file.IsOpen()) { 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("Unable to open file %ls\n", name.c_str()); 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int read = file.Read(header, header_size, NULL); 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read != header_size) { 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("Unable to read file %ls\n", name.c_str()); 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint GetMajorVersionFromFile(const std::wstring& name) { 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::IndexHeader header; 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return header.version >> 16; 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Dumps the contents of the Index-file header. 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DumpIndexHeader(const std::wstring& name) { 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::IndexHeader header; 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("Index file:\n"); 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("magic: %x\n", header.magic); 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff); 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("entries: %d\n", header.num_entries); 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("total bytes: %d\n", header.num_bytes); 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("last file number: %d\n", header.last_file); 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("current id: %d\n", header.this_id); 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("table length: %d\n", header.table_len); 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("last crash: %d\n", header.crash); 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("experiment: %d\n", header.experiment); 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < 5; i++) { 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("head %d: 0x%x\n", i, header.lru.heads[i]); 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("tail %d: 0x%x\n", i, header.lru.tails[i]); 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen printf("size %d: 0x%x\n", i, header.lru.sizes[i]); 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("transaction: 0x%x\n", header.lru.transaction); 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("operation: %d\n", header.lru.operation); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("operation list: %d\n", header.lru.operation_list); 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("-------------------------\n\n"); 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Dumps the contents of a block-file header. 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DumpBlockHeader(const std::wstring& name) { 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::BlockFileHeader header; 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header))) 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen std::wstring file_name = FilePath(name).BaseName().value(); 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("Block file: %ls\n", file_name.c_str()); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("magic: %x\n", header.magic); 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff); 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("file id: %d\n", header.this_file); 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("next file id: %d\n", header.next_file); 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("entry size: %d\n", header.entry_size); 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("current entries: %d\n", header.num_entries); 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("max entries: %d\n", header.max_entries); 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("updating: %d\n", header.updating); 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("empty sz 1: %d\n", header.empty[0]); 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("empty sz 2: %d\n", header.empty[1]); 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("empty sz 3: %d\n", header.empty[2]); 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("empty sz 4: %d\n", header.empty[3]); 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("user 0: 0x%x\n", header.user[0]); 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("user 1: 0x%x\n", header.user[1]); 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("user 2: 0x%x\n", header.user[2]); 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("user 3: 0x%x\n", header.user[3]); 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("-------------------------\n\n"); 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Simple class that interacts with the set of cache files. 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass CacheDumper { 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit CacheDumper(const std::wstring& path) 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : path_(path), 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott block_files_(FilePath::FromWStringHack(path)), 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick index_(NULL), 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick current_hash_(0), 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_addr_(0) { 1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool Init(); 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Reads an entry from disk. Return false when all entries have been already 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // returned. 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool GetEntry(disk_cache::EntryStore* entry); 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Loads a specific block from the block files. 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool LoadEntry(disk_cache::CacheAddr addr, disk_cache::EntryStore* entry); 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool LoadRankings(disk_cache::CacheAddr addr, 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::RankingsNode* rankings); 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::wstring path_; 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::BlockFiles block_files_; 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<disk_cache::MappedFile> index_file_; 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::Index* index_; 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int current_hash_; 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::CacheAddr next_addr_; 13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::set<disk_cache::CacheAddr> dumped_entries_; 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(CacheDumper); 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool CacheDumper::Init() { 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!block_files_.Init(false)) { 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("Unable to init block files\n"); 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::wstring index_name(path_); 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file_util::AppendToPath(&index_name, kIndexName); 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott index_file_ = new disk_cache::MappedFile; 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott index_ = reinterpret_cast<disk_cache::Index*>(index_file_->Init( 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FilePath::FromWStringHack(index_name), 0)); 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!index_) { 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("Unable to map index\n"); 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool CacheDumper::GetEntry(disk_cache::EntryStore* entry) { 16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (dumped_entries_.find(next_addr_) != dumped_entries_.end()) { 16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen printf("Loop detected\n"); 16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen next_addr_ = 0; 16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_hash_++; 16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (next_addr_) { 16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (LoadEntry(next_addr_, entry)) 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen printf("Unable to load entry at address 0x%x\n", next_addr_); 17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen next_addr_ = 0; 17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_hash_++; 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = current_hash_; i < index_->header.table_len; i++) { 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Yes, we'll crash if the table is shorter than expected, but only after 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // dumping every entry that we can find. 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (index_->table[i]) { 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_hash_ = i; 18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (LoadEntry(index_->table[i], entry)) 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen printf("Unable to load entry at address 0x%x\n", index_->table[i]); 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool CacheDumper::LoadEntry(disk_cache::CacheAddr addr, 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::EntryStore* entry) { 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::Addr address(addr); 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::MappedFile* file = block_files_.GetFile(address); 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!file) 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::CacheEntryBlock entry_block(file, address); 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!entry_block.Load()) 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(entry, entry_block.Data(), sizeof(*entry)); 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("Entry at 0x%x\n", addr); 20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 20372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Prepare for the next entry to load. 20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen next_addr_ = entry->next; 20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (next_addr_) { 20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dumped_entries_.insert(addr); 20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 20872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_hash_++; 20972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dumped_entries_.clear(); 21072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool CacheDumper::LoadRankings(disk_cache::CacheAddr addr, 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::RankingsNode* rankings) { 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::Addr address(addr); 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::MappedFile* file = block_files_.GetFile(address); 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!file) 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::CacheRankingsBlock rank_block(file, address); 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!rank_block.Load()) 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(rankings, rank_block.Data(), sizeof(*rankings)); 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("Rankings at 0x%x\n", addr); 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DumpEntry(const disk_cache::EntryStore& entry) { 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string key; 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!entry.long_key) { 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott key = entry.key; 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (key.size() > 50) 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott key.resize(50); 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("hash: 0x%x\n", entry.hash); 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("next entry: 0x%x\n", entry.next); 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("rankings: 0x%x\n", entry.rankings_node); 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("key length: %d\n", entry.key_len); 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("key: \"%s\"\n", key.c_str()); 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("key addr: 0x%x\n", entry.long_key); 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("reuse count: %d\n", entry.reuse_count); 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("refetch count: %d\n", entry.refetch_count); 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("state: %d\n", entry.state); 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < 4; i++) { 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("data size %d: %d\n", i, entry.data_size[i]); 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("data addr %d: 0x%x\n", i, entry.data_addr[i]); 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("----------\n\n"); 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DumpRankings(const disk_cache::RankingsNode& rankings) { 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("next: 0x%x\n", rankings.next); 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("prev: 0x%x\n", rankings.prev); 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("entry: 0x%x\n", rankings.contents); 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("dirty: %d\n", rankings.dirty); 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("pointer: 0x%x\n", rankings.dummy); 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("----------\n\n"); 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace. 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ----------------------------------------------------------------------- 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint GetMajorVersion(const std::wstring& input_path) { 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::wstring index_name(input_path); 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file_util::AppendToPath(&index_name, kIndexName); 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int version = GetMajorVersionFromFile(index_name); 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!version) 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::wstring data_name(input_path); 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file_util::AppendToPath(&data_name, L"data_0"); 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (version != GetMajorVersionFromFile(data_name)) 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data_name = input_path; 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file_util::AppendToPath(&data_name, L"data_1"); 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (version != GetMajorVersionFromFile(data_name)) 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return version; 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Dumps the headers of all files. 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint DumpHeaders(const std::wstring& input_path) { 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::wstring index_name(input_path); 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file_util::AppendToPath(&index_name, kIndexName); 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DumpIndexHeader(index_name); 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::wstring pattern(kDataPrefix); 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pattern.append(L"*"); 29672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen file_util::FileEnumerator iter(FilePath(input_path), false, 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file_util::FileEnumerator::FILES, pattern); 29872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (std::wstring file = iter.Next().value(); !file.empty(); 29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen file = iter.Next().value()) { 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DumpBlockHeader(file); 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Dumps all entries from the cache. 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint DumpContents(const std::wstring& input_path) { 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DumpHeaders(input_path); 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We need a message loop, although we really don't run any task. 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop loop(MessageLoop::TYPE_IO); 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CacheDumper dumper(input_path); 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!dumper.Init()) 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::EntryStore entry; 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (dumper.GetEntry(&entry)) { 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DumpEntry(entry); 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::RankingsNode rankings; 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (dumper.LoadRankings(entry.rankings_node, &rankings)) 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DumpRankings(rankings); 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("Done.\n"); 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 328