// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Performs basic inspection of the disk cache files with minimal disruption
// to the actual files (they still may change if an error is detected on the
// files).

#include "net/tools/dump_cache/dump_files.h"

#include <stdio.h>

#include <memory>
#include <set>
#include <string>

#include "base/command_line.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "net/disk_cache/blockfile/block_files.h"
#include "net/disk_cache/blockfile/disk_format.h"
#include "net/disk_cache/blockfile/mapped_file.h"
#include "net/disk_cache/blockfile/stats.h"
#include "net/disk_cache/blockfile/storage_block-inl.h"
#include "net/disk_cache/blockfile/storage_block.h"
#include "net/url_request/view_cache_helper.h"
#include "starboard/memory.h"
#include "starboard/types.h"

namespace {

const base::FilePath::CharType kIndexName[] = FILE_PATH_LITERAL("index");

// Reads the |header_size| bytes from the beginning of file |name|.
bool ReadHeader(const base::FilePath& name, char* header, int header_size) {
  base::File file(name, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid()) {
    printf("Unable to open file %s\n", name.MaybeAsASCII().c_str());
    return false;
  }

  int read = file.Read(0, header, header_size);
  if (read != header_size) {
    printf("Unable to read file %s\n", name.MaybeAsASCII().c_str());
    return false;
  }
  return true;
}

int GetMajorVersionFromFile(const base::FilePath& name) {
  disk_cache::IndexHeader header;
  if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header)))
    return 0;

  return header.version >> 16;
}

// Dumps the contents of the Stats record.
void DumpStats(const base::FilePath& path, disk_cache::CacheAddr addr) {
  // We need a message loop, although we really don't run any task.
  base::MessageLoopForIO loop;

  disk_cache::BlockFiles block_files(path);
  if (!block_files.Init(false)) {
    printf("Unable to init block files\n");
    return;
  }

  disk_cache::Addr address(addr);
  disk_cache::MappedFile* file = block_files.GetFile(address);
  if (!file)
    return;

  size_t length = (2 + disk_cache::Stats::kDataSizesLength) * sizeof(int32_t) +
                  disk_cache::Stats::MAX_COUNTER * sizeof(int64_t);

  size_t offset = address.start_block() * address.BlockSize() +
                  disk_cache::kBlockHeaderSize;

  std::unique_ptr<int32_t[]> buffer(new int32_t[length]);
  if (!file->Read(buffer.get(), length, offset))
    return;

  printf("Stats:\nSignatrure: 0x%x\n", buffer[0]);
  printf("Total size: %d\n", buffer[1]);
  for (int i = 0; i < disk_cache::Stats::kDataSizesLength; i++)
    printf("Size(%d): %d\n", i, buffer[i + 2]);

  int64_t* counters = reinterpret_cast<int64_t*>(
      buffer.get() + 2 + disk_cache::Stats::kDataSizesLength);
  for (int i = 0; i < disk_cache::Stats::MAX_COUNTER; i++)
    printf("Count(%d): %" PRId64 "\n", i, *counters++);
  printf("-------------------------\n\n");
}

// Dumps the contents of the Index-file header.
void DumpIndexHeader(const base::FilePath& name,
                     disk_cache::CacheAddr* stats_addr) {
  disk_cache::IndexHeader header;
  if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header)))
    return;

  printf("Index file:\n");
  printf("magic: %x\n", header.magic);
  printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff);
  printf("entries: %d\n", header.num_entries);
  printf("total bytes: %d\n", header.num_bytes);
  printf("last file number: %d\n", header.last_file);
  printf("current id: %d\n", header.this_id);
  printf("table length: %d\n", header.table_len);
  printf("last crash: %d\n", header.crash);
  printf("experiment: %d\n", header.experiment);
  printf("stats: %x\n", header.stats);
  for (int i = 0; i < 5; i++) {
    printf("head %d: 0x%x\n", i, header.lru.heads[i]);
    printf("tail %d: 0x%x\n", i, header.lru.tails[i]);
    printf("size %d: 0x%x\n", i, header.lru.sizes[i]);
  }
  printf("transaction: 0x%x\n", header.lru.transaction);
  printf("operation: %d\n", header.lru.operation);
  printf("operation list: %d\n", header.lru.operation_list);
  printf("-------------------------\n\n");

  if (stats_addr)
    *stats_addr = header.stats;
}

// Dumps the contents of a block-file header.
void DumpBlockHeader(const base::FilePath& name) {
  disk_cache::BlockFileHeader header;
  if (!ReadHeader(name, reinterpret_cast<char*>(&header), sizeof(header)))
    return;

  printf("Block file: %s\n", name.BaseName().MaybeAsASCII().c_str());
  printf("magic: %x\n", header.magic);
  printf("version: %d.%d\n", header.version >> 16, header.version & 0xffff);
  printf("file id: %d\n", header.this_file);
  printf("next file id: %d\n", header.next_file);
  printf("entry size: %d\n", header.entry_size);
  printf("current entries: %d\n", header.num_entries);
  printf("max entries: %d\n", header.max_entries);
  printf("updating: %d\n", header.updating);
  printf("empty sz 1: %d\n", header.empty[0]);
  printf("empty sz 2: %d\n", header.empty[1]);
  printf("empty sz 3: %d\n", header.empty[2]);
  printf("empty sz 4: %d\n", header.empty[3]);
  printf("user 0: 0x%x\n", header.user[0]);
  printf("user 1: 0x%x\n", header.user[1]);
  printf("user 2: 0x%x\n", header.user[2]);
  printf("user 3: 0x%x\n", header.user[3]);
  printf("-------------------------\n\n");
}

// Simple class that interacts with the set of cache files.
class CacheDumper {
 public:
  explicit CacheDumper(const base::FilePath& path)
      : path_(path),
        block_files_(path),
        index_(NULL),
        current_hash_(0),
        next_addr_(0) {
  }

  bool Init();

  // Reads an entry from disk. Return false when all entries have been already
  // returned.
  bool GetEntry(disk_cache::EntryStore* entry, disk_cache::CacheAddr* addr);

  // Loads a specific block from the block files.
  bool LoadEntry(disk_cache::CacheAddr addr, disk_cache::EntryStore* entry);
  bool LoadRankings(disk_cache::CacheAddr addr,
                    disk_cache::RankingsNode* rankings);

  // Appends the data store at |addr| to |out|.
  bool HexDump(disk_cache::CacheAddr addr, std::string* out);

 private:
  base::FilePath path_;
  disk_cache::BlockFiles block_files_;
  scoped_refptr<disk_cache::MappedFile> index_file_;
  disk_cache::Index* index_;
  int current_hash_;
  disk_cache::CacheAddr next_addr_;
  std::set<disk_cache::CacheAddr> dumped_entries_;
  DISALLOW_COPY_AND_ASSIGN(CacheDumper);
};

bool CacheDumper::Init() {
  if (!block_files_.Init(false)) {
    printf("Unable to init block files\n");
    return false;
  }

  base::FilePath index_name(path_.Append(kIndexName));
  index_file_ = new disk_cache::MappedFile;
  index_ = reinterpret_cast<disk_cache::Index*>(
      index_file_->Init(index_name, 0));
  if (!index_) {
    printf("Unable to map index\n");
    return false;
  }

  return true;
}

bool CacheDumper::GetEntry(disk_cache::EntryStore* entry,
                           disk_cache::CacheAddr* addr) {
  if (dumped_entries_.find(next_addr_) != dumped_entries_.end()) {
    printf("Loop detected\n");
    next_addr_ = 0;
    current_hash_++;
  }

  if (next_addr_) {
    *addr = next_addr_;
    if (LoadEntry(next_addr_, entry))
      return true;

    printf("Unable to load entry at address 0x%x\n", next_addr_);
    next_addr_ = 0;
    current_hash_++;
  }

  for (int i = current_hash_; i < index_->header.table_len; i++) {
    // Yes, we'll crash if the table is shorter than expected, but only after
    // dumping every entry that we can find.
    if (index_->table[i]) {
      current_hash_ = i;
      *addr = index_->table[i];
      if (LoadEntry(index_->table[i], entry))
        return true;

      printf("Unable to load entry at address 0x%x\n", index_->table[i]);
    }
  }
  return false;
}

bool CacheDumper::LoadEntry(disk_cache::CacheAddr addr,
                            disk_cache::EntryStore* entry) {
  disk_cache::Addr address(addr);
  disk_cache::MappedFile* file = block_files_.GetFile(address);
  if (!file)
    return false;

  disk_cache::StorageBlock<disk_cache::EntryStore> entry_block(file, address);
  if (!entry_block.Load())
    return false;

  memcpy(entry, entry_block.Data(), sizeof(*entry));
  if (!entry_block.VerifyHash())
    printf("Self hash failed at 0x%x\n", addr);

  // Prepare for the next entry to load.
  next_addr_ = entry->next;
  if (next_addr_) {
    dumped_entries_.insert(addr);
  } else {
    current_hash_++;
    dumped_entries_.clear();
  }
  return true;
}

bool CacheDumper::LoadRankings(disk_cache::CacheAddr addr,
                               disk_cache::RankingsNode* rankings) {
  disk_cache::Addr address(addr);
  if (address.file_type() != disk_cache::RANKINGS)
    return false;

  disk_cache::MappedFile* file = block_files_.GetFile(address);
  if (!file)
    return false;

  disk_cache::StorageBlock<disk_cache::RankingsNode> rank_block(file, address);
  if (!rank_block.Load())
    return false;

  if (!rank_block.VerifyHash())
    printf("Self hash failed at 0x%x\n", addr);

  memcpy(rankings, rank_block.Data(), sizeof(*rankings));
  return true;
}

bool CacheDumper::HexDump(disk_cache::CacheAddr addr, std::string* out) {
  disk_cache::Addr address(addr);
  disk_cache::MappedFile* file = block_files_.GetFile(address);
  if (!file)
    return false;

  size_t size = address.num_blocks() * address.BlockSize();
  std::unique_ptr<char> buffer(new char[size]);

  size_t offset = address.start_block() * address.BlockSize() +
                  disk_cache::kBlockHeaderSize;
  if (!file->Read(buffer.get(), size, offset))
    return false;

  base::StringAppendF(out, "0x%x:\n", addr);
  net::ViewCacheHelper::HexDump(buffer.get(), size, out);
  return true;
}

std::string ToLocalTime(int64_t time_us) {
  base::Time time = base::Time::FromInternalValue(time_us);
  base::Time::Exploded e;
  time.LocalExplode(&e);
  return base::StringPrintf("%d/%d/%d %d:%d:%d.%d", e.year, e.month,
                            e.day_of_month, e.hour, e.minute, e.second,
                            e.millisecond);
}

void DumpEntry(disk_cache::CacheAddr addr,
               const disk_cache::EntryStore& entry,
               bool verbose) {
  std::string key;
  static bool full_key =
      base::CommandLine::ForCurrentProcess()->HasSwitch("full-key");
  if (!entry.long_key) {
    key = std::string(entry.key, std::min(static_cast<size_t>(entry.key_len),
                                          sizeof(entry.key)));
    if (entry.key_len > 90 && !full_key)
      key.resize(90);
  }

  printf("Entry at 0x%x\n", addr);
  printf("rankings: 0x%x\n", entry.rankings_node);
  printf("key length: %d\n", entry.key_len);
  printf("key: \"%s\"\n", key.c_str());

  if (verbose) {
    printf("key addr: 0x%x\n", entry.long_key);
    printf("hash: 0x%x\n", entry.hash);
    printf("next entry: 0x%x\n", entry.next);
    printf("reuse count: %d\n", entry.reuse_count);
    printf("refetch count: %d\n", entry.refetch_count);
    printf("state: %d\n", entry.state);
    printf("creation: %s\n", ToLocalTime(entry.creation_time).c_str());
    for (int i = 0; i < 4; i++) {
      printf("data size %d: %d\n", i, entry.data_size[i]);
      printf("data addr %d: 0x%x\n", i, entry.data_addr[i]);
    }
    printf("----------\n\n");
  }
}

void DumpRankings(disk_cache::CacheAddr addr,
                  const disk_cache::RankingsNode& rankings,
                  bool verbose) {
  printf("Rankings at 0x%x\n", addr);
  printf("next: 0x%x\n", rankings.next);
  printf("prev: 0x%x\n", rankings.prev);
  printf("entry: 0x%x\n", rankings.contents);

  if (verbose) {
    printf("dirty: %d\n", rankings.dirty);
    if (rankings.last_used != rankings.last_modified)
      printf("used: %s\n", ToLocalTime(rankings.last_used).c_str());
    printf("modified: %s\n", ToLocalTime(rankings.last_modified).c_str());
    printf("hash: 0x%x\n", rankings.self_hash);
    printf("----------\n\n");
  } else {
    printf("\n");
  }
}

void PrintCSVHeader() {
  printf(
      "entry,rankings,next,prev,rank-contents,chain,reuse,key,"
      "d0,d1,d2,d3\n");
}

void DumpCSV(disk_cache::CacheAddr addr,
             const disk_cache::EntryStore& entry,
             const disk_cache::RankingsNode& rankings) {
  printf("0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n", addr,
         entry.rankings_node, rankings.next, rankings.prev, rankings.contents,
         entry.next, entry.reuse_count, entry.long_key, entry.data_addr[0],
         entry.data_addr[1], entry.data_addr[2], entry.data_addr[3]);

  if (addr != rankings.contents)
    printf("Broken entry\n");
}

bool CanDump(disk_cache::CacheAddr addr) {
  disk_cache::Addr address(addr);
  return address.is_initialized() && address.is_block_file();
}

}  // namespace.

// -----------------------------------------------------------------------

int GetMajorVersion(const base::FilePath& input_path) {
  base::FilePath index_name(input_path.Append(kIndexName));

  int version = GetMajorVersionFromFile(index_name);
  if (!version)
    return 0;

  base::FilePath data_name(input_path.Append(FILE_PATH_LITERAL("data_0")));
  if (version != GetMajorVersionFromFile(data_name))
    return 0;

  data_name = input_path.Append(FILE_PATH_LITERAL("data_1"));
  if (version != GetMajorVersionFromFile(data_name))
    return 0;

  data_name = input_path.Append(FILE_PATH_LITERAL("data_2"));
  if (version != GetMajorVersionFromFile(data_name))
    return 0;

  data_name = input_path.Append(FILE_PATH_LITERAL("data_3"));
  if (version != GetMajorVersionFromFile(data_name))
    return 0;

  return version;
}

// Dumps the headers of all files.
int DumpHeaders(const base::FilePath& input_path) {
  base::FilePath index_name(input_path.Append(kIndexName));
  disk_cache::CacheAddr stats_addr = 0;
  DumpIndexHeader(index_name, &stats_addr);

  base::FileEnumerator iter(input_path, false,
                            base::FileEnumerator::FILES,
                            FILE_PATH_LITERAL("data_*"));
  for (base::FilePath file = iter.Next(); !file.empty(); file = iter.Next())
    DumpBlockHeader(file);

  DumpStats(input_path, stats_addr);
  return 0;
}

// Dumps all entries from the cache.
int DumpContents(const base::FilePath& input_path) {
  bool print_csv = base::CommandLine::ForCurrentProcess()->HasSwitch("csv");
  if (!print_csv)
    DumpIndexHeader(input_path.Append(kIndexName), nullptr);

  // We need a message loop, although we really don't run any task.
  base::MessageLoopForIO loop;
  CacheDumper dumper(input_path);
  if (!dumper.Init())
    return -1;

  if (print_csv)
    PrintCSVHeader();

  disk_cache::EntryStore entry;
  disk_cache::CacheAddr addr;
  bool verbose = base::CommandLine::ForCurrentProcess()->HasSwitch("v");
  while (dumper.GetEntry(&entry, &addr)) {
    if (!print_csv)
      DumpEntry(addr, entry, verbose);
    disk_cache::RankingsNode rankings;
    if (!dumper.LoadRankings(entry.rankings_node, &rankings))
      continue;

    if (print_csv)
      DumpCSV(addr, entry, rankings);
    else
      DumpRankings(entry.rankings_node, rankings, verbose);
  }

  printf("Done.\n");

  return 0;
}

int DumpLists(const base::FilePath& input_path) {
  base::FilePath index_name(input_path.Append(kIndexName));
  disk_cache::IndexHeader header;
  if (!ReadHeader(index_name, reinterpret_cast<char*>(&header), sizeof(header)))
    return -1;

  // We need a message loop, although we really don't run any task.
  base::MessageLoopForIO loop;
  CacheDumper dumper(input_path);
  if (!dumper.Init())
    return -1;

  printf("list, addr,      next,       prev,       entry\n");

  const int kMaxLength = 1 * 1000 * 1000;
  for (int i = 0; i < 5; i++) {
    int32_t size = header.lru.sizes[i];
    if (size < 0 || size > kMaxLength) {
      printf("Wrong size %d\n", size);
      size = kMaxLength;
    }

    disk_cache::CacheAddr addr = header.lru.tails[i];
    int count = 0;
    for (; size && addr; size--) {
      count++;
      disk_cache::RankingsNode rankings;
      if (!dumper.LoadRankings(addr, &rankings)) {
        printf("Failed to load node at 0x%x\n", addr);
        break;
      }
      printf("%d, 0x%x, 0x%x, 0x%x, 0x%x\n", i, addr, rankings.next,
             rankings.prev, rankings.contents);

      if (rankings.prev == addr)
        break;

      addr = rankings.prev;
    }
    printf("%d nodes found, %d reported\n", count, header.lru.sizes[i]);
  }

  printf("Done.\n");
  return 0;
}

int DumpEntryAt(const base::FilePath& input_path, const std::string& at) {
  disk_cache::CacheAddr addr;
  if (!base::HexStringToUInt(at, &addr))
    return -1;

  if (!CanDump(addr))
    return -1;

  base::FilePath index_name(input_path.Append(kIndexName));
  disk_cache::IndexHeader header;
  if (!ReadHeader(index_name, reinterpret_cast<char*>(&header), sizeof(header)))
    return -1;

  // We need a message loop, although we really don't run any task.
  base::MessageLoopForIO loop;
  CacheDumper dumper(input_path);
  if (!dumper.Init())
    return -1;

  disk_cache::CacheAddr entry_addr = 0;
  disk_cache::CacheAddr rankings_addr = 0;
  disk_cache::Addr address(addr);

  disk_cache::RankingsNode rankings;
  if (address.file_type() == disk_cache::RANKINGS) {
    if (dumper.LoadRankings(addr, &rankings)) {
      rankings_addr = addr;
      addr = rankings.contents;
      address = disk_cache::Addr(addr);
    }
  }

  disk_cache::EntryStore entry = {};
  if (address.file_type() == disk_cache::BLOCK_256 &&
      dumper.LoadEntry(addr, &entry)) {
    entry_addr = addr;
    DumpEntry(addr, entry, true);
    if (!rankings_addr && dumper.LoadRankings(entry.rankings_node, &rankings))
      rankings_addr = entry.rankings_node;
  }

  bool verbose = base::CommandLine::ForCurrentProcess()->HasSwitch("v");

  std::string hex_dump;
  if (!rankings_addr || verbose)
    dumper.HexDump(addr, &hex_dump);

  if (rankings_addr)
    DumpRankings(rankings_addr, rankings, true);

  if (entry_addr && verbose) {
    if (entry.long_key && CanDump(entry.long_key))
      dumper.HexDump(entry.long_key, &hex_dump);

    for (int i = 0; i < 4; i++) {
      if (entry.data_addr[i] && CanDump(entry.data_addr[i]))
        dumper.HexDump(entry.data_addr[i], &hex_dump);
    }
  }

  printf("%s\n", hex_dump.c_str());
  printf("Done.\n");
  return 0;
}

int DumpAllocation(const base::FilePath& file) {
  disk_cache::BlockFileHeader header;
  if (!ReadHeader(file, reinterpret_cast<char*>(&header), sizeof(header)))
    return -1;

  std::string out;
  net::ViewCacheHelper::HexDump(reinterpret_cast<char*>(&header.allocation_map),
                                sizeof(header.allocation_map), &out);
  printf("%s\n", out.c_str());
  return 0;
}
