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