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