// 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.

#include "net/disk_cache/blockfile/block_bitmaps_v3.h"

#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "net/disk_cache/blockfile/disk_format_base.h"
#include "net/disk_cache/blockfile/trace.h"

using base::TimeTicks;

namespace disk_cache {

BlockBitmaps::BlockBitmaps() {
}

BlockBitmaps::~BlockBitmaps() {
}

void BlockBitmaps::Init(const BlockFilesBitmaps& bitmaps) {
  bitmaps_ = bitmaps;
}

bool BlockBitmaps::CreateBlock(FileType block_type,
                               int block_count,
                               Addr* block_address) {
  DCHECK_NE(block_type, EXTERNAL);
  DCHECK_NE(block_type, RANKINGS);
  if (block_count < 1 || block_count > kMaxNumBlocks)
    return false;

  int header_num = HeaderNumberForNewBlock(block_type, block_count);
  if (header_num < 0)
    return false;

  int index;
  if (!bitmaps_[header_num].CreateMapBlock(block_count, &index))
    return false;

  if (!index && (block_type == BLOCK_ENTRIES || block_type == BLOCK_EVICTED) &&
      !bitmaps_[header_num].CreateMapBlock(block_count, &index)) {
    // index 0 for entries is a reserved value.
    return false;
  }

  Addr address(block_type, block_count, bitmaps_[header_num].FileId(), index);
  block_address->set_value(address.value());
  Trace("CreateBlock 0x%x", address.value());
  return true;
}

void BlockBitmaps::DeleteBlock(Addr address) {
  if (!address.is_initialized() || address.is_separate_file())
    return;

  int header_num = GetHeaderNumber(address);
  if (header_num < 0)
    return;

  Trace("DeleteBlock 0x%x", address.value());
  bitmaps_[header_num].DeleteMapBlock(address.start_block(),
                                      address.num_blocks());
}

void BlockBitmaps::Clear() {
  bitmaps_.clear();
}

void BlockBitmaps::ReportStats() {
  int used_blocks[kFirstAdditionalBlockFile];
  int load[kFirstAdditionalBlockFile];
  for (int16 i = 0; i < kFirstAdditionalBlockFile; i++) {
    GetFileStats(i, &used_blocks[i], &load[i]);
  }
  UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_0", used_blocks[0]);
  UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_1", used_blocks[1]);
  UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_2", used_blocks[2]);
  UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_3", used_blocks[3]);

  UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_0", load[0], 101);
  UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_1", load[1], 101);
  UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_2", load[2], 101);
  UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_3", load[3], 101);
}

bool BlockBitmaps::IsValid(Addr address) {
#ifdef NDEBUG
  return true;
#else
  if (!address.is_initialized() || address.is_separate_file())
    return false;

  int header_num = GetHeaderNumber(address);
  if (header_num < 0)
    return false;

  bool rv = bitmaps_[header_num].UsedMapBlock(address.start_block(),
                                              address.num_blocks());
  DCHECK(rv);
  return rv;
#endif
}

int BlockBitmaps::GetHeaderNumber(Addr address) {
  DCHECK_GE(bitmaps_.size(), kFirstAdditionalBlockFileV3);
  DCHECK(address.is_block_file() || !address.is_initialized());
  if (!address.is_initialized())
    return -1;

  int file_index = address.FileNumber();
  if (static_cast<unsigned int>(file_index) >= bitmaps_.size())
    return -1;

  return file_index;
}

int BlockBitmaps::HeaderNumberForNewBlock(FileType block_type,
                                          int block_count) {
  DCHECK_GT(block_type, 0);
  int header_num = block_type - 1;
  bool found = true;

  TimeTicks start = TimeTicks::Now();
  while (bitmaps_[header_num].NeedToGrowBlockFile(block_count)) {
    header_num = bitmaps_[header_num].NextFileId();
    if (!header_num) {
      found = false;
      break;
    }
  }

  if (!found) {
    // Restart the search, looking for any file with space. We know that all
    // files of this type are low on free blocks, but we cannot grow any file
    // at this time.
    header_num = block_type - 1;
    do {
      if (bitmaps_[header_num].CanAllocate(block_count)) {
        found = true;  // Make sure file 0 is not mistaken with a failure.
        break;
      }
      header_num = bitmaps_[header_num].NextFileId();
    } while (header_num);

    if (!found)
      header_num = -1;
  }

  LOCAL_HISTOGRAM_TIMES("DiskCache.GetFileForNewBlock",
                        TimeTicks::Now() - start);
  return header_num;
}

// We are interested in the total number of blocks used by this file type, and
// the max number of blocks that we can store (reported as the percentage of
// used blocks). In order to find out the number of used blocks, we have to
// substract the empty blocks from the total blocks for each file in the chain.
void BlockBitmaps::GetFileStats(int index, int* used_count, int* load) {
  int max_blocks = 0;
  *used_count = 0;
  *load = 0;
  do {
    int capacity = bitmaps_[index].Capacity();
    int used = capacity - bitmaps_[index].EmptyBlocks();
    DCHECK_GE(used, 0);

    max_blocks += capacity;
    *used_count += used;

    index = bitmaps_[index].NextFileId();
  } while (index);

  if (max_blocks)
    *load = *used_count * 100 / max_blocks;
}

}  // namespace disk_cache
