// Copyright (c) 2013 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/simple/simple_synchronous_entry.h"

#include <algorithm>
#include <cstring>
#include <functional>
#include <limits>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/files/file_util.h"
#include "base/hash.h"
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/sha1.h"
#include "base/strings/stringprintf.h"
#include "base/timer/elapsed_timer.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/simple/simple_backend_version.h"
#include "net/disk_cache/simple/simple_histogram_macros.h"
#include "net/disk_cache/simple/simple_util.h"
#include "third_party/zlib/zlib.h"

using base::File;
using base::FilePath;
using base::Time;

namespace {

// Used in histograms, please only add entries at the end.
enum OpenEntryResult {
  OPEN_ENTRY_SUCCESS = 0,
  OPEN_ENTRY_PLATFORM_FILE_ERROR = 1,
  OPEN_ENTRY_CANT_READ_HEADER = 2,
  OPEN_ENTRY_BAD_MAGIC_NUMBER = 3,
  OPEN_ENTRY_BAD_VERSION = 4,
  OPEN_ENTRY_CANT_READ_KEY = 5,
  // OPEN_ENTRY_KEY_MISMATCH = 6, Deprecated.
  OPEN_ENTRY_KEY_HASH_MISMATCH = 7,
  OPEN_ENTRY_SPARSE_OPEN_FAILED = 8,
  OPEN_ENTRY_MAX = 9,
};

// Used in histograms, please only add entries at the end.
enum WriteResult {
  WRITE_RESULT_SUCCESS = 0,
  WRITE_RESULT_PRETRUNCATE_FAILURE,
  WRITE_RESULT_WRITE_FAILURE,
  WRITE_RESULT_TRUNCATE_FAILURE,
  WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED,
  WRITE_RESULT_LAZY_CREATE_FAILURE,
  WRITE_RESULT_LAZY_INITIALIZE_FAILURE,
  WRITE_RESULT_MAX,
};

// Used in histograms, please only add entries at the end.
enum CheckEOFResult {
  CHECK_EOF_RESULT_SUCCESS,
  CHECK_EOF_RESULT_READ_FAILURE,
  CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH,
  CHECK_EOF_RESULT_CRC_MISMATCH,
  CHECK_EOF_RESULT_MAX,
};

// Used in histograms, please only add entries at the end.
enum CloseResult {
  CLOSE_RESULT_SUCCESS,
  CLOSE_RESULT_WRITE_FAILURE,
};

void RecordSyncOpenResult(net::CacheType cache_type,
                          OpenEntryResult result,
                          bool had_index) {
  DCHECK_LT(result, OPEN_ENTRY_MAX);
  SIMPLE_CACHE_UMA(ENUMERATION,
                   "SyncOpenResult", cache_type, result, OPEN_ENTRY_MAX);
  if (had_index) {
    SIMPLE_CACHE_UMA(ENUMERATION,
                     "SyncOpenResult_WithIndex", cache_type,
                     result, OPEN_ENTRY_MAX);
  } else {
    SIMPLE_CACHE_UMA(ENUMERATION,
                     "SyncOpenResult_WithoutIndex", cache_type,
                     result, OPEN_ENTRY_MAX);
  }
}

void RecordWriteResult(net::CacheType cache_type, WriteResult result) {
  SIMPLE_CACHE_UMA(ENUMERATION,
                   "SyncWriteResult", cache_type, result, WRITE_RESULT_MAX);
}

void RecordCheckEOFResult(net::CacheType cache_type, CheckEOFResult result) {
  SIMPLE_CACHE_UMA(ENUMERATION,
                   "SyncCheckEOFResult", cache_type,
                   result, CHECK_EOF_RESULT_MAX);
}

void RecordCloseResult(net::CacheType cache_type, CloseResult result) {
  SIMPLE_CACHE_UMA(ENUMERATION,
                   "SyncCloseResult", cache_type, result, WRITE_RESULT_MAX);
}

bool CanOmitEmptyFile(int file_index) {
  DCHECK_GE(file_index, 0);
  DCHECK_LT(file_index, disk_cache::kSimpleEntryFileCount);
  return file_index == disk_cache::simple_util::GetFileIndexFromStreamIndex(2);
}

}  // namespace

namespace disk_cache {

using simple_util::GetEntryHashKey;
using simple_util::GetFilenameFromEntryHashAndFileIndex;
using simple_util::GetSparseFilenameFromEntryHash;
using simple_util::GetDataSizeFromKeyAndFileSize;
using simple_util::GetFileSizeFromKeyAndDataSize;
using simple_util::GetFileIndexFromStreamIndex;

SimpleEntryStat::SimpleEntryStat(base::Time last_used,
                                 base::Time last_modified,
                                 const int32 data_size[],
                                 const int32 sparse_data_size)
    : last_used_(last_used),
      last_modified_(last_modified),
      sparse_data_size_(sparse_data_size) {
  memcpy(data_size_, data_size, sizeof(data_size_));
}

int SimpleEntryStat::GetOffsetInFile(const std::string& key,
                                     int offset,
                                     int stream_index) const {
  const size_t headers_size = sizeof(SimpleFileHeader) + key.size();
  const size_t additional_offset =
      stream_index == 0 ? data_size_[1] + sizeof(SimpleFileEOF) : 0;
  return headers_size + offset + additional_offset;
}

int SimpleEntryStat::GetEOFOffsetInFile(const std::string& key,
                                        int stream_index) const {
  return GetOffsetInFile(key, data_size_[stream_index], stream_index);
}

int SimpleEntryStat::GetLastEOFOffsetInFile(const std::string& key,
                                            int stream_index) const {
  const int file_index = GetFileIndexFromStreamIndex(stream_index);
  const int eof_data_offset =
      file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF)
                      : data_size_[2];
  return GetOffsetInFile(key, eof_data_offset, stream_index);
}

int64 SimpleEntryStat::GetFileSize(const std::string& key,
                                   int file_index) const {
  const int32 total_data_size =
      file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF)
                      : data_size_[2];
  return GetFileSizeFromKeyAndDataSize(key, total_data_size);
}

SimpleEntryCreationResults::SimpleEntryCreationResults(
    SimpleEntryStat entry_stat)
    : sync_entry(NULL),
      entry_stat(entry_stat),
      stream_0_crc32(crc32(0, Z_NULL, 0)),
      result(net::OK) {
}

SimpleEntryCreationResults::~SimpleEntryCreationResults() {
}

SimpleSynchronousEntry::CRCRecord::CRCRecord() : index(-1),
                                                 has_crc32(false),
                                                 data_crc32(0) {
}

SimpleSynchronousEntry::CRCRecord::CRCRecord(int index_p,
                                             bool has_crc32_p,
                                             uint32 data_crc32_p)
    : index(index_p),
      has_crc32(has_crc32_p),
      data_crc32(data_crc32_p) {}

SimpleSynchronousEntry::EntryOperationData::EntryOperationData(int index_p,
                                                               int offset_p,
                                                               int buf_len_p)
    : index(index_p),
      offset(offset_p),
      buf_len(buf_len_p) {}

SimpleSynchronousEntry::EntryOperationData::EntryOperationData(int index_p,
                                                               int offset_p,
                                                               int buf_len_p,
                                                               bool truncate_p,
                                                               bool doomed_p)
    : index(index_p),
      offset(offset_p),
      buf_len(buf_len_p),
      truncate(truncate_p),
      doomed(doomed_p) {}

SimpleSynchronousEntry::EntryOperationData::EntryOperationData(
    int64 sparse_offset_p,
    int buf_len_p)
    : sparse_offset(sparse_offset_p),
      buf_len(buf_len_p) {}

// static
void SimpleSynchronousEntry::OpenEntry(
    net::CacheType cache_type,
    const FilePath& path,
    const uint64 entry_hash,
    bool had_index,
    SimpleEntryCreationResults *out_results) {
  base::ElapsedTimer open_time;
  SimpleSynchronousEntry* sync_entry =
      new SimpleSynchronousEntry(cache_type, path, "", entry_hash);
  out_results->result =
      sync_entry->InitializeForOpen(had_index,
                                    &out_results->entry_stat,
                                    &out_results->stream_0_data,
                                    &out_results->stream_0_crc32);
  if (out_results->result != net::OK) {
    sync_entry->Doom();
    delete sync_entry;
    out_results->sync_entry = NULL;
    out_results->stream_0_data = NULL;
    return;
  }
  UMA_HISTOGRAM_TIMES("SimpleCache.DiskOpenLatency", open_time.Elapsed());
  out_results->sync_entry = sync_entry;
}

// static
void SimpleSynchronousEntry::CreateEntry(
    net::CacheType cache_type,
    const FilePath& path,
    const std::string& key,
    const uint64 entry_hash,
    bool had_index,
    SimpleEntryCreationResults *out_results) {
  DCHECK_EQ(entry_hash, GetEntryHashKey(key));
  SimpleSynchronousEntry* sync_entry =
      new SimpleSynchronousEntry(cache_type, path, key, entry_hash);
  out_results->result = sync_entry->InitializeForCreate(
      had_index, &out_results->entry_stat);
  if (out_results->result != net::OK) {
    if (out_results->result != net::ERR_FILE_EXISTS)
      sync_entry->Doom();
    delete sync_entry;
    out_results->sync_entry = NULL;
    return;
  }
  out_results->sync_entry = sync_entry;
}

// static
int SimpleSynchronousEntry::DoomEntry(
    const FilePath& path,
    uint64 entry_hash) {
  const bool deleted_well = DeleteFilesForEntryHash(path, entry_hash);
  return deleted_well ? net::OK : net::ERR_FAILED;
}

// static
int SimpleSynchronousEntry::DoomEntrySet(
    const std::vector<uint64>* key_hashes,
    const FilePath& path) {
  const size_t did_delete_count = std::count_if(
      key_hashes->begin(), key_hashes->end(), std::bind1st(
          std::ptr_fun(SimpleSynchronousEntry::DeleteFilesForEntryHash), path));
  return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED;
}

void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op,
                                      net::IOBuffer* out_buf,
                                      uint32* out_crc32,
                                      SimpleEntryStat* entry_stat,
                                      int* out_result) const {
  DCHECK(initialized_);
  DCHECK_NE(0, in_entry_op.index);
  const int64 file_offset =
      entry_stat->GetOffsetInFile(key_, in_entry_op.offset, in_entry_op.index);
  int file_index = GetFileIndexFromStreamIndex(in_entry_op.index);
  // Zero-length reads and reads to the empty streams of omitted files should
  // be handled in the SimpleEntryImpl.
  DCHECK_GT(in_entry_op.buf_len, 0);
  DCHECK(!empty_file_omitted_[file_index]);
  File* file = const_cast<File*>(&files_[file_index]);
  int bytes_read =
      file->Read(file_offset, out_buf->data(), in_entry_op.buf_len);
  if (bytes_read > 0) {
    entry_stat->set_last_used(Time::Now());
    *out_crc32 = crc32(crc32(0L, Z_NULL, 0),
                       reinterpret_cast<const Bytef*>(out_buf->data()),
                       bytes_read);
  }
  if (bytes_read >= 0) {
    *out_result = bytes_read;
  } else {
    *out_result = net::ERR_CACHE_READ_FAILURE;
    Doom();
  }
}

void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op,
                                       net::IOBuffer* in_buf,
                                       SimpleEntryStat* out_entry_stat,
                                       int* out_result) {
  DCHECK(initialized_);
  DCHECK_NE(0, in_entry_op.index);
  int index = in_entry_op.index;
  int file_index = GetFileIndexFromStreamIndex(index);
  int offset = in_entry_op.offset;
  int buf_len = in_entry_op.buf_len;
  bool truncate = in_entry_op.truncate;
  bool doomed = in_entry_op.doomed;
  const int64 file_offset = out_entry_stat->GetOffsetInFile(
      key_, in_entry_op.offset, in_entry_op.index);
  bool extending_by_write = offset + buf_len > out_entry_stat->data_size(index);

  if (empty_file_omitted_[file_index]) {
    // Don't create a new file if the entry has been doomed, to avoid it being
    // mixed up with a newly-created entry with the same key.
    if (doomed) {
      DLOG(WARNING) << "Rejecting write to lazily omitted stream "
                    << in_entry_op.index << " of doomed cache entry.";
      RecordWriteResult(cache_type_, WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED);
      *out_result = net::ERR_CACHE_WRITE_FAILURE;
      return;
    }
    File::Error error;
    if (!MaybeCreateFile(file_index, FILE_REQUIRED, &error)) {
      RecordWriteResult(cache_type_, WRITE_RESULT_LAZY_CREATE_FAILURE);
      Doom();
      *out_result = net::ERR_CACHE_WRITE_FAILURE;
      return;
    }
    CreateEntryResult result;
    if (!InitializeCreatedFile(file_index, &result)) {
      RecordWriteResult(cache_type_, WRITE_RESULT_LAZY_INITIALIZE_FAILURE);
      Doom();
      *out_result = net::ERR_CACHE_WRITE_FAILURE;
      return;
    }
  }
  DCHECK(!empty_file_omitted_[file_index]);

  if (extending_by_write) {
    // The EOF record and the eventual stream afterward need to be zeroed out.
    const int64 file_eof_offset =
        out_entry_stat->GetEOFOffsetInFile(key_, index);
    if (!files_[file_index].SetLength(file_eof_offset)) {
      RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE);
      Doom();
      *out_result = net::ERR_CACHE_WRITE_FAILURE;
      return;
    }
  }
  if (buf_len > 0) {
    if (files_[file_index].Write(file_offset, in_buf->data(), buf_len) !=
        buf_len) {
      RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE);
      Doom();
      *out_result = net::ERR_CACHE_WRITE_FAILURE;
      return;
    }
  }
  if (!truncate && (buf_len > 0 || !extending_by_write)) {
    out_entry_stat->set_data_size(
        index, std::max(out_entry_stat->data_size(index), offset + buf_len));
  } else {
    out_entry_stat->set_data_size(index, offset + buf_len);
    int file_eof_offset = out_entry_stat->GetLastEOFOffsetInFile(key_, index);
    if (!files_[file_index].SetLength(file_eof_offset)) {
      RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE);
      Doom();
      *out_result = net::ERR_CACHE_WRITE_FAILURE;
      return;
    }
  }

  RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS);
  base::Time modification_time = Time::Now();
  out_entry_stat->set_last_used(modification_time);
  out_entry_stat->set_last_modified(modification_time);
  *out_result = buf_len;
}

void SimpleSynchronousEntry::ReadSparseData(
    const EntryOperationData& in_entry_op,
    net::IOBuffer* out_buf,
    base::Time* out_last_used,
    int* out_result) {
  DCHECK(initialized_);
  int64 offset = in_entry_op.sparse_offset;
  int buf_len = in_entry_op.buf_len;

  char* buf = out_buf->data();
  int read_so_far = 0;

  // Find the first sparse range at or after the requested offset.
  SparseRangeIterator it = sparse_ranges_.lower_bound(offset);

  if (it != sparse_ranges_.begin()) {
    // Hop back one range and read the one overlapping with the start.
    --it;
    SparseRange* found_range = &it->second;
    DCHECK_EQ(it->first, found_range->offset);
    if (found_range->offset + found_range->length > offset) {
      DCHECK_GE(found_range->length, 0);
      DCHECK_LE(found_range->length, kint32max);
      DCHECK_GE(offset - found_range->offset, 0);
      DCHECK_LE(offset - found_range->offset, kint32max);
      int net_offset = static_cast<int>(offset - found_range->offset);
      int range_len_after_offset =
          static_cast<int>(found_range->length - net_offset);
      DCHECK_GE(range_len_after_offset, 0);

      int len_to_read = std::min(buf_len, range_len_after_offset);
      if (!ReadSparseRange(found_range, net_offset, len_to_read, buf)) {
        *out_result = net::ERR_CACHE_READ_FAILURE;
        return;
      }
      read_so_far += len_to_read;
    }
    ++it;
  }

  // Keep reading until the buffer is full or there is not another contiguous
  // range.
  while (read_so_far < buf_len &&
         it != sparse_ranges_.end() &&
         it->second.offset == offset + read_so_far) {
    SparseRange* found_range = &it->second;
    DCHECK_EQ(it->first, found_range->offset);
    int range_len = base::saturated_cast<int>(found_range->length);
    int len_to_read = std::min(buf_len - read_so_far, range_len);
    if (!ReadSparseRange(found_range, 0, len_to_read, buf + read_so_far)) {
      *out_result = net::ERR_CACHE_READ_FAILURE;
      return;
    }
    read_so_far += len_to_read;
    ++it;
  }

  *out_result = read_so_far;
}

void SimpleSynchronousEntry::WriteSparseData(
    const EntryOperationData& in_entry_op,
    net::IOBuffer* in_buf,
    uint64 max_sparse_data_size,
    SimpleEntryStat* out_entry_stat,
    int* out_result) {
  DCHECK(initialized_);
  int64 offset = in_entry_op.sparse_offset;
  int buf_len = in_entry_op.buf_len;

  const char* buf = in_buf->data();
  int written_so_far = 0;
  int appended_so_far = 0;

  if (!sparse_file_open() && !CreateSparseFile()) {
    *out_result = net::ERR_CACHE_WRITE_FAILURE;
    return;
  }

  uint64 sparse_data_size = out_entry_stat->sparse_data_size();
  // This is a pessimistic estimate; it assumes the entire buffer is going to
  // be appended as a new range, not written over existing ranges.
  if (sparse_data_size + buf_len > max_sparse_data_size) {
    DVLOG(1) << "Truncating sparse data file (" << sparse_data_size << " + "
             << buf_len << " > " << max_sparse_data_size << ")";
    TruncateSparseFile();
  }

  SparseRangeIterator it = sparse_ranges_.lower_bound(offset);

  if (it != sparse_ranges_.begin()) {
    --it;
    SparseRange* found_range = &it->second;
    if (found_range->offset + found_range->length > offset) {
      DCHECK_GE(found_range->length, 0);
      DCHECK_LE(found_range->length, kint32max);
      DCHECK_GE(offset - found_range->offset, 0);
      DCHECK_LE(offset - found_range->offset, kint32max);
      int net_offset = static_cast<int>(offset - found_range->offset);
      int range_len_after_offset =
          static_cast<int>(found_range->length - net_offset);
      DCHECK_GE(range_len_after_offset, 0);

      int len_to_write = std::min(buf_len, range_len_after_offset);
      if (!WriteSparseRange(found_range, net_offset, len_to_write, buf)) {
        *out_result = net::ERR_CACHE_WRITE_FAILURE;
        return;
      }
      written_so_far += len_to_write;
    }
    ++it;
  }

  while (written_so_far < buf_len &&
         it != sparse_ranges_.end() &&
         it->second.offset < offset + buf_len) {
    SparseRange* found_range = &it->second;
    if (offset + written_so_far < found_range->offset) {
      int len_to_append =
          static_cast<int>(found_range->offset - (offset + written_so_far));
      if (!AppendSparseRange(offset + written_so_far,
                             len_to_append,
                             buf + written_so_far)) {
        *out_result = net::ERR_CACHE_WRITE_FAILURE;
        return;
      }
      written_so_far += len_to_append;
      appended_so_far += len_to_append;
    }
    int range_len = base::saturated_cast<int>(found_range->length);
    int len_to_write = std::min(buf_len - written_so_far, range_len);
    if (!WriteSparseRange(found_range,
                          0,
                          len_to_write,
                          buf + written_so_far)) {
      *out_result = net::ERR_CACHE_WRITE_FAILURE;
      return;
    }
    written_so_far += len_to_write;
    ++it;
  }

  if (written_so_far < buf_len) {
    int len_to_append = buf_len - written_so_far;
    if (!AppendSparseRange(offset + written_so_far,
                           len_to_append,
                           buf + written_so_far)) {
      *out_result = net::ERR_CACHE_WRITE_FAILURE;
      return;
    }
    written_so_far += len_to_append;
    appended_so_far += len_to_append;
  }

  DCHECK_EQ(buf_len, written_so_far);

  base::Time modification_time = Time::Now();
  out_entry_stat->set_last_used(modification_time);
  out_entry_stat->set_last_modified(modification_time);
  int32 old_sparse_data_size = out_entry_stat->sparse_data_size();
  out_entry_stat->set_sparse_data_size(old_sparse_data_size + appended_so_far);
  *out_result = written_so_far;
}

void SimpleSynchronousEntry::GetAvailableRange(
    const EntryOperationData& in_entry_op,
    int64* out_start,
    int* out_result) {
  DCHECK(initialized_);
  int64 offset = in_entry_op.sparse_offset;
  int len = in_entry_op.buf_len;

  SparseRangeIterator it = sparse_ranges_.lower_bound(offset);

  int64 start = offset;
  int64 avail_so_far = 0;

  if (it != sparse_ranges_.end() && it->second.offset < offset + len)
    start = it->second.offset;

  if ((it == sparse_ranges_.end() || it->second.offset > offset) &&
      it != sparse_ranges_.begin()) {
    --it;
    if (it->second.offset + it->second.length > offset) {
      start = offset;
      avail_so_far = (it->second.offset + it->second.length) - offset;
    }
    ++it;
  }

  while (start + avail_so_far < offset + len &&
         it != sparse_ranges_.end() &&
         it->second.offset == start + avail_so_far) {
    avail_so_far += it->second.length;
    ++it;
  }

  int64 len_from_start = len - (start - offset);
  *out_start = start;
  *out_result = static_cast<int>(std::min(avail_so_far, len_from_start));
}

void SimpleSynchronousEntry::CheckEOFRecord(int index,
                                            const SimpleEntryStat& entry_stat,
                                            uint32 expected_crc32,
                                            int* out_result) const {
  DCHECK(initialized_);
  uint32 crc32;
  bool has_crc32;
  int stream_size;
  *out_result =
      GetEOFRecordData(index, entry_stat, &has_crc32, &crc32, &stream_size);
  if (*out_result != net::OK) {
    Doom();
    return;
  }
  if (has_crc32 && crc32 != expected_crc32) {
    DVLOG(1) << "EOF record had bad crc.";
    *out_result = net::ERR_CACHE_CHECKSUM_MISMATCH;
    RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
    Doom();
    return;
  }
  RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
}

void SimpleSynchronousEntry::Close(
    const SimpleEntryStat& entry_stat,
    scoped_ptr<std::vector<CRCRecord> > crc32s_to_write,
    net::GrowableIOBuffer* stream_0_data) {
  DCHECK(stream_0_data);
  // Write stream 0 data.
  int stream_0_offset = entry_stat.GetOffsetInFile(key_, 0, 0);
  if (files_[0].Write(stream_0_offset, stream_0_data->data(),
                      entry_stat.data_size(0)) !=
      entry_stat.data_size(0)) {
    RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
    DVLOG(1) << "Could not write stream 0 data.";
    Doom();
  }

  for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin();
       it != crc32s_to_write->end(); ++it) {
    const int stream_index = it->index;
    const int file_index = GetFileIndexFromStreamIndex(stream_index);
    if (empty_file_omitted_[file_index])
      continue;

    SimpleFileEOF eof_record;
    eof_record.stream_size = entry_stat.data_size(stream_index);
    eof_record.final_magic_number = kSimpleFinalMagicNumber;
    eof_record.flags = 0;
    if (it->has_crc32)
      eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32;
    eof_record.data_crc32 = it->data_crc32;
    int eof_offset = entry_stat.GetEOFOffsetInFile(key_, stream_index);
    // If stream 0 changed size, the file needs to be resized, otherwise the
    // next open will yield wrong stream sizes. On stream 1 and stream 2 proper
    // resizing of the file is handled in SimpleSynchronousEntry::WriteData().
    if (stream_index == 0 &&
        !files_[file_index].SetLength(eof_offset)) {
      RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
      DVLOG(1) << "Could not truncate stream 0 file.";
      Doom();
      break;
    }
    if (files_[file_index].Write(eof_offset,
                                 reinterpret_cast<const char*>(&eof_record),
                                 sizeof(eof_record)) !=
        sizeof(eof_record)) {
      RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
      DVLOG(1) << "Could not write eof record.";
      Doom();
      break;
    }
  }
  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
    if (empty_file_omitted_[i])
      continue;

    files_[i].Close();
    const int64 file_size = entry_stat.GetFileSize(key_, i);
    SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
                     "LastClusterSize", cache_type_,
                     file_size % 4096, 0, 4097, 50);
    const int64 cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0;
    SIMPLE_CACHE_UMA(PERCENTAGE,
                     "LastClusterLossPercent", cache_type_,
                     static_cast<base::HistogramBase::Sample>(
                         cluster_loss * 100 / (cluster_loss + file_size)));
  }

  if (sparse_file_open())
    sparse_file_.Close();

  if (files_created_) {
    const int stream2_file_index = GetFileIndexFromStreamIndex(2);
    SIMPLE_CACHE_UMA(BOOLEAN, "EntryCreatedAndStream2Omitted", cache_type_,
                     empty_file_omitted_[stream2_file_index]);
  }
  RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS);
  have_open_files_ = false;
  delete this;
}

SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type,
                                               const FilePath& path,
                                               const std::string& key,
                                               const uint64 entry_hash)
    : cache_type_(cache_type),
      path_(path),
      entry_hash_(entry_hash),
      key_(key),
      have_open_files_(false),
      initialized_(false) {
  for (int i = 0; i < kSimpleEntryFileCount; ++i)
    empty_file_omitted_[i] = false;
}

SimpleSynchronousEntry::~SimpleSynchronousEntry() {
  DCHECK(!(have_open_files_ && initialized_));
  if (have_open_files_)
    CloseFiles();
}

bool SimpleSynchronousEntry::MaybeOpenFile(
    int file_index,
    File::Error* out_error) {
  DCHECK(out_error);

  FilePath filename = GetFilenameFromFileIndex(file_index);
  int flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE |
              File::FLAG_SHARE_DELETE;
  files_[file_index].Initialize(filename, flags);
  *out_error = files_[file_index].error_details();

  if (CanOmitEmptyFile(file_index) && !files_[file_index].IsValid() &&
      *out_error == File::FILE_ERROR_NOT_FOUND) {
    empty_file_omitted_[file_index] = true;
    return true;
  }

  return files_[file_index].IsValid();
}

bool SimpleSynchronousEntry::MaybeCreateFile(
    int file_index,
    FileRequired file_required,
    File::Error* out_error) {
  DCHECK(out_error);

  if (CanOmitEmptyFile(file_index) && file_required == FILE_NOT_REQUIRED) {
    empty_file_omitted_[file_index] = true;
    return true;
  }

  FilePath filename = GetFilenameFromFileIndex(file_index);
  int flags = File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE |
              File::FLAG_SHARE_DELETE;
  files_[file_index].Initialize(filename, flags);
  *out_error = files_[file_index].error_details();

  empty_file_omitted_[file_index] = false;

  return files_[file_index].IsValid();
}

bool SimpleSynchronousEntry::OpenFiles(
    bool had_index,
    SimpleEntryStat* out_entry_stat) {
  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
    File::Error error;
    if (!MaybeOpenFile(i, &error)) {
      // TODO(ttuttle,gavinp): Remove one each of these triplets of histograms.
      // We can calculate the third as the sum or difference of the other two.
      RecordSyncOpenResult(
          cache_type_, OPEN_ENTRY_PLATFORM_FILE_ERROR, had_index);
      SIMPLE_CACHE_UMA(ENUMERATION,
                       "SyncOpenPlatformFileError", cache_type_,
                       -error, -base::File::FILE_ERROR_MAX);
      if (had_index) {
        SIMPLE_CACHE_UMA(ENUMERATION,
                         "SyncOpenPlatformFileError_WithIndex", cache_type_,
                         -error, -base::File::FILE_ERROR_MAX);
      } else {
        SIMPLE_CACHE_UMA(ENUMERATION,
                         "SyncOpenPlatformFileError_WithoutIndex",
                         cache_type_,
                         -error, -base::File::FILE_ERROR_MAX);
      }
      while (--i >= 0)
        CloseFile(i);
      return false;
    }
  }

  have_open_files_ = true;

  base::TimeDelta entry_age = base::Time::Now() - base::Time::UnixEpoch();
  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
    if (empty_file_omitted_[i]) {
      out_entry_stat->set_data_size(i + 1, 0);
      continue;
    }

    File::Info file_info;
    bool success = files_[i].GetInfo(&file_info);
    base::Time file_last_modified;
    if (!success) {
      DLOG(WARNING) << "Could not get platform file info.";
      continue;
    }
    out_entry_stat->set_last_used(file_info.last_accessed);
    if (simple_util::GetMTime(path_, &file_last_modified))
      out_entry_stat->set_last_modified(file_last_modified);
    else
      out_entry_stat->set_last_modified(file_info.last_modified);

    base::TimeDelta stream_age =
        base::Time::Now() - out_entry_stat->last_modified();
    if (stream_age < entry_age)
      entry_age = stream_age;

    // Two things prevent from knowing the right values for |data_size|:
    // 1) The key is not known, hence its length is unknown.
    // 2) Stream 0 and stream 1 are in the same file, and the exact size for
    // each will only be known when reading the EOF record for stream 0.
    //
    // The size for file 0 and 1 is temporarily kept in
    // |data_size(1)| and |data_size(2)| respectively. Reading the key in
    // InitializeForOpen yields the data size for each file. In the case of
    // file hash_1, this is the total size of stream 2, and is assigned to
    // data_size(2). In the case of file 0, it is the combined size of stream
    // 0, stream 1 and one EOF record. The exact distribution of sizes between
    // stream 1 and stream 0 is only determined after reading the EOF record
    // for stream 0 in ReadAndValidateStream0.
    out_entry_stat->set_data_size(i + 1, static_cast<int>(file_info.size));
  }
  SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
                   "SyncOpenEntryAge", cache_type_,
                   entry_age.InHours(), 1, 1000, 50);

  files_created_ = false;

  return true;
}

bool SimpleSynchronousEntry::CreateFiles(
    bool had_index,
    SimpleEntryStat* out_entry_stat) {
  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
    File::Error error;
    if (!MaybeCreateFile(i, FILE_NOT_REQUIRED, &error)) {
      // TODO(ttuttle,gavinp): Remove one each of these triplets of histograms.
      // We can calculate the third as the sum or difference of the other two.
      RecordSyncCreateResult(CREATE_ENTRY_PLATFORM_FILE_ERROR, had_index);
      SIMPLE_CACHE_UMA(ENUMERATION,
                       "SyncCreatePlatformFileError", cache_type_,
                       -error, -base::File::FILE_ERROR_MAX);
      if (had_index) {
        SIMPLE_CACHE_UMA(ENUMERATION,
                         "SyncCreatePlatformFileError_WithIndex", cache_type_,
                         -error, -base::File::FILE_ERROR_MAX);
      } else {
        SIMPLE_CACHE_UMA(ENUMERATION,
                         "SyncCreatePlatformFileError_WithoutIndex",
                         cache_type_,
                         -error, -base::File::FILE_ERROR_MAX);
      }
      while (--i >= 0)
        CloseFile(i);
      return false;
    }
  }

  have_open_files_ = true;

  base::Time creation_time = Time::Now();
  out_entry_stat->set_last_modified(creation_time);
  out_entry_stat->set_last_used(creation_time);
  for (int i = 0; i < kSimpleEntryStreamCount; ++i)
      out_entry_stat->set_data_size(i, 0);

  files_created_ = true;

  return true;
}

void SimpleSynchronousEntry::CloseFile(int index) {
  if (empty_file_omitted_[index]) {
    empty_file_omitted_[index] = false;
  } else {
    DCHECK(files_[index].IsValid());
    files_[index].Close();
  }

  if (sparse_file_open())
    CloseSparseFile();
}

void SimpleSynchronousEntry::CloseFiles() {
  for (int i = 0; i < kSimpleEntryFileCount; ++i)
    CloseFile(i);
}

int SimpleSynchronousEntry::InitializeForOpen(
    bool had_index,
    SimpleEntryStat* out_entry_stat,
    scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
    uint32* out_stream_0_crc32) {
  DCHECK(!initialized_);
  if (!OpenFiles(had_index, out_entry_stat)) {
    DLOG(WARNING) << "Could not open platform files for entry.";
    return net::ERR_FAILED;
  }
  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
    if (empty_file_omitted_[i])
      continue;

    SimpleFileHeader header;
    int header_read_result =
        files_[i].Read(0, reinterpret_cast<char*>(&header), sizeof(header));
    if (header_read_result != sizeof(header)) {
      DLOG(WARNING) << "Cannot read header from entry.";
      RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_HEADER, had_index);
      return net::ERR_FAILED;
    }

    if (header.initial_magic_number != kSimpleInitialMagicNumber) {
      // TODO(gavinp): This seems very bad; for now we log at WARNING, but we
      // should give consideration to not saturating the log with these if that
      // becomes a problem.
      DLOG(WARNING) << "Magic number did not match.";
      RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_MAGIC_NUMBER, had_index);
      return net::ERR_FAILED;
    }

    if (header.version != kSimpleEntryVersionOnDisk) {
      DLOG(WARNING) << "Unreadable version.";
      RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_VERSION, had_index);
      return net::ERR_FAILED;
    }

    scoped_ptr<char[]> key(new char[header.key_length]);
    int key_read_result = files_[i].Read(sizeof(header), key.get(),
                                         header.key_length);
    if (key_read_result != implicit_cast<int>(header.key_length)) {
      DLOG(WARNING) << "Cannot read key from entry.";
      RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_KEY, had_index);
      return net::ERR_FAILED;
    }

    key_ = std::string(key.get(), header.key_length);
    if (i == 0) {
      // File size for stream 0 has been stored temporarily in data_size[1].
      int total_data_size =
          GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size(1));
      int ret_value_stream_0 = ReadAndValidateStream0(
          total_data_size, out_entry_stat, stream_0_data, out_stream_0_crc32);
      if (ret_value_stream_0 != net::OK)
        return ret_value_stream_0;
    } else {
      out_entry_stat->set_data_size(
          2, GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size(2)));
      if (out_entry_stat->data_size(2) < 0) {
        DLOG(WARNING) << "Stream 2 file is too small.";
        return net::ERR_FAILED;
      }
    }

    if (base::Hash(key.get(), header.key_length) != header.key_hash) {
      DLOG(WARNING) << "Hash mismatch on key.";
      RecordSyncOpenResult(
          cache_type_, OPEN_ENTRY_KEY_HASH_MISMATCH, had_index);
      return net::ERR_FAILED;
    }
  }

  int32 sparse_data_size = 0;
  if (!OpenSparseFileIfExists(&sparse_data_size)) {
    RecordSyncOpenResult(
        cache_type_, OPEN_ENTRY_SPARSE_OPEN_FAILED, had_index);
    return net::ERR_FAILED;
  }
  out_entry_stat->set_sparse_data_size(sparse_data_size);

  bool removed_stream2 = false;
  const int stream2_file_index = GetFileIndexFromStreamIndex(2);
  DCHECK(CanOmitEmptyFile(stream2_file_index));
  if (!empty_file_omitted_[stream2_file_index] &&
      out_entry_stat->data_size(2) == 0) {
    DVLOG(1) << "Removing empty stream 2 file.";
    CloseFile(stream2_file_index);
    DeleteFileForEntryHash(path_, entry_hash_, stream2_file_index);
    empty_file_omitted_[stream2_file_index] = true;
    removed_stream2 = true;
  }

  SIMPLE_CACHE_UMA(BOOLEAN, "EntryOpenedAndStream2Removed", cache_type_,
                   removed_stream2);

  RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index);
  initialized_ = true;
  return net::OK;
}

bool SimpleSynchronousEntry::InitializeCreatedFile(
    int file_index,
    CreateEntryResult* out_result) {
  SimpleFileHeader header;
  header.initial_magic_number = kSimpleInitialMagicNumber;
  header.version = kSimpleEntryVersionOnDisk;

  header.key_length = key_.size();
  header.key_hash = base::Hash(key_);

  int bytes_written = files_[file_index].Write(
      0, reinterpret_cast<char*>(&header), sizeof(header));
  if (bytes_written != sizeof(header)) {
    *out_result = CREATE_ENTRY_CANT_WRITE_HEADER;
    return false;
  }

  bytes_written = files_[file_index].Write(sizeof(header), key_.data(),
                                           key_.size());
  if (bytes_written != implicit_cast<int>(key_.size())) {
    *out_result = CREATE_ENTRY_CANT_WRITE_KEY;
    return false;
  }

  return true;
}

int SimpleSynchronousEntry::InitializeForCreate(
    bool had_index,
    SimpleEntryStat* out_entry_stat) {
  DCHECK(!initialized_);
  if (!CreateFiles(had_index, out_entry_stat)) {
    DLOG(WARNING) << "Could not create platform files.";
    return net::ERR_FILE_EXISTS;
  }
  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
    if (empty_file_omitted_[i])
      continue;

    CreateEntryResult result;
    if (!InitializeCreatedFile(i, &result)) {
      RecordSyncCreateResult(result, had_index);
      return net::ERR_FAILED;
    }
  }
  RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index);
  initialized_ = true;
  return net::OK;
}

int SimpleSynchronousEntry::ReadAndValidateStream0(
    int total_data_size,
    SimpleEntryStat* out_entry_stat,
    scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
    uint32* out_stream_0_crc32) const {
  // Temporarily assign all the data size to stream 1 in order to read the
  // EOF record for stream 0, which contains the size of stream 0.
  out_entry_stat->set_data_size(0, 0);
  out_entry_stat->set_data_size(1, total_data_size - sizeof(SimpleFileEOF));

  bool has_crc32;
  uint32 read_crc32;
  int stream_0_size;
  int ret_value_crc32 = GetEOFRecordData(
      0, *out_entry_stat, &has_crc32, &read_crc32, &stream_0_size);
  if (ret_value_crc32 != net::OK)
    return ret_value_crc32;

  if (stream_0_size > out_entry_stat->data_size(1))
    return net::ERR_FAILED;

  // These are the real values of data size.
  out_entry_stat->set_data_size(0, stream_0_size);
  out_entry_stat->set_data_size(
      1, out_entry_stat->data_size(1) - stream_0_size);

  // Put stream 0 data in memory.
  *stream_0_data = new net::GrowableIOBuffer();
  (*stream_0_data)->SetCapacity(stream_0_size);
  int file_offset = out_entry_stat->GetOffsetInFile(key_, 0, 0);
  File* file = const_cast<File*>(&files_[0]);
  int bytes_read =
      file->Read(file_offset, (*stream_0_data)->data(), stream_0_size);
  if (bytes_read != stream_0_size)
    return net::ERR_FAILED;

  // Check the CRC32.
  uint32 expected_crc32 =
      stream_0_size == 0
          ? crc32(0, Z_NULL, 0)
          : crc32(crc32(0, Z_NULL, 0),
                  reinterpret_cast<const Bytef*>((*stream_0_data)->data()),
                  stream_0_size);
  if (has_crc32 && read_crc32 != expected_crc32) {
    DVLOG(1) << "EOF record had bad crc.";
    RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
    return net::ERR_FAILED;
  }
  *out_stream_0_crc32 = expected_crc32;
  RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
  return net::OK;
}

int SimpleSynchronousEntry::GetEOFRecordData(int index,
                                             const SimpleEntryStat& entry_stat,
                                             bool* out_has_crc32,
                                             uint32* out_crc32,
                                             int* out_data_size) const {
  SimpleFileEOF eof_record;
  int file_offset = entry_stat.GetEOFOffsetInFile(key_, index);
  int file_index = GetFileIndexFromStreamIndex(index);
  File* file = const_cast<File*>(&files_[file_index]);
  if (file->Read(file_offset, reinterpret_cast<char*>(&eof_record),
                 sizeof(eof_record)) !=
      sizeof(eof_record)) {
    RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE);
    return net::ERR_CACHE_CHECKSUM_READ_FAILURE;
  }

  if (eof_record.final_magic_number != kSimpleFinalMagicNumber) {
    RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH);
    DVLOG(1) << "EOF record had bad magic number.";
    return net::ERR_CACHE_CHECKSUM_READ_FAILURE;
  }

  *out_has_crc32 = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) ==
                   SimpleFileEOF::FLAG_HAS_CRC32;
  *out_crc32 = eof_record.data_crc32;
  *out_data_size = eof_record.stream_size;
  SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, *out_has_crc32);
  return net::OK;
}

void SimpleSynchronousEntry::Doom() const {
  DeleteFilesForEntryHash(path_, entry_hash_);
}

// static
bool SimpleSynchronousEntry::DeleteFileForEntryHash(
    const FilePath& path,
    const uint64 entry_hash,
    const int file_index) {
  FilePath to_delete = path.AppendASCII(
      GetFilenameFromEntryHashAndFileIndex(entry_hash, file_index));
  return simple_util::SimpleCacheDeleteFile(to_delete);
}

// static
bool SimpleSynchronousEntry::DeleteFilesForEntryHash(
    const FilePath& path,
    const uint64 entry_hash) {
  bool result = true;
  for (int i = 0; i < kSimpleEntryFileCount; ++i) {
    if (!DeleteFileForEntryHash(path, entry_hash, i) && !CanOmitEmptyFile(i))
      result = false;
  }
  FilePath to_delete = path.AppendASCII(
      GetSparseFilenameFromEntryHash(entry_hash));
  simple_util::SimpleCacheDeleteFile(to_delete);
  return result;
}

void SimpleSynchronousEntry::RecordSyncCreateResult(CreateEntryResult result,
                                                    bool had_index) {
  DCHECK_LT(result, CREATE_ENTRY_MAX);
  SIMPLE_CACHE_UMA(ENUMERATION,
                   "SyncCreateResult", cache_type_, result, CREATE_ENTRY_MAX);
  if (had_index) {
    SIMPLE_CACHE_UMA(ENUMERATION,
                     "SyncCreateResult_WithIndex", cache_type_,
                     result, CREATE_ENTRY_MAX);
  } else {
    SIMPLE_CACHE_UMA(ENUMERATION,
                     "SyncCreateResult_WithoutIndex", cache_type_,
                     result, CREATE_ENTRY_MAX);
  }
}

FilePath SimpleSynchronousEntry::GetFilenameFromFileIndex(int file_index) {
  return path_.AppendASCII(
      GetFilenameFromEntryHashAndFileIndex(entry_hash_, file_index));
}

bool SimpleSynchronousEntry::OpenSparseFileIfExists(
    int32* out_sparse_data_size) {
  DCHECK(!sparse_file_open());

  FilePath filename = path_.AppendASCII(
      GetSparseFilenameFromEntryHash(entry_hash_));
  int flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE |
              File::FLAG_SHARE_DELETE;
  sparse_file_.Initialize(filename, flags);
  if (sparse_file_.IsValid())
    return ScanSparseFile(out_sparse_data_size);

  return sparse_file_.error_details() == File::FILE_ERROR_NOT_FOUND;
}

bool SimpleSynchronousEntry::CreateSparseFile() {
  DCHECK(!sparse_file_open());

  FilePath filename = path_.AppendASCII(
      GetSparseFilenameFromEntryHash(entry_hash_));
  int flags = File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE |
              File::FLAG_SHARE_DELETE;
  sparse_file_.Initialize(filename, flags);
  if (!sparse_file_.IsValid())
    return false;

  return InitializeSparseFile();
}

void SimpleSynchronousEntry::CloseSparseFile() {
  DCHECK(sparse_file_open());
  sparse_file_.Close();
}

bool SimpleSynchronousEntry::TruncateSparseFile() {
  DCHECK(sparse_file_open());

  int64 header_and_key_length = sizeof(SimpleFileHeader) + key_.size();
  if (!sparse_file_.SetLength(header_and_key_length)) {
    DLOG(WARNING) << "Could not truncate sparse file";
    return false;
  }

  sparse_ranges_.clear();

  return true;
}

bool SimpleSynchronousEntry::InitializeSparseFile() {
  DCHECK(sparse_file_open());

  SimpleFileHeader header;
  header.initial_magic_number = kSimpleInitialMagicNumber;
  header.version = kSimpleVersion;
  header.key_length = key_.size();
  header.key_hash = base::Hash(key_);

  int header_write_result =
      sparse_file_.Write(0, reinterpret_cast<char*>(&header), sizeof(header));
  if (header_write_result != sizeof(header)) {
    DLOG(WARNING) << "Could not write sparse file header";
    return false;
  }

  int key_write_result = sparse_file_.Write(sizeof(header), key_.data(),
                                            key_.size());
  if (key_write_result != implicit_cast<int>(key_.size())) {
    DLOG(WARNING) << "Could not write sparse file key";
    return false;
  }

  sparse_ranges_.clear();
  sparse_tail_offset_ = sizeof(header) + key_.size();

  return true;
}

bool SimpleSynchronousEntry::ScanSparseFile(int32* out_sparse_data_size) {
  DCHECK(sparse_file_open());

  int64 sparse_data_size = 0;

  SimpleFileHeader header;
  int header_read_result =
      sparse_file_.Read(0, reinterpret_cast<char*>(&header), sizeof(header));
  if (header_read_result != sizeof(header)) {
    DLOG(WARNING) << "Could not read header from sparse file.";
    return false;
  }

  if (header.initial_magic_number != kSimpleInitialMagicNumber) {
    DLOG(WARNING) << "Sparse file magic number did not match.";
    return false;
  }

  if (header.version != kSimpleVersion) {
    DLOG(WARNING) << "Sparse file unreadable version.";
    return false;
  }

  sparse_ranges_.clear();

  int64 range_header_offset = sizeof(header) + key_.size();
  while (1) {
    SimpleFileSparseRangeHeader range_header;
    int range_header_read_result =
        sparse_file_.Read(range_header_offset,
                          reinterpret_cast<char*>(&range_header),
                          sizeof(range_header));
    if (range_header_read_result == 0)
      break;
    if (range_header_read_result != sizeof(range_header)) {
      DLOG(WARNING) << "Could not read sparse range header.";
      return false;
    }

    if (range_header.sparse_range_magic_number !=
        kSimpleSparseRangeMagicNumber) {
      DLOG(WARNING) << "Invalid sparse range header magic number.";
      return false;
    }

    SparseRange range;
    range.offset = range_header.offset;
    range.length = range_header.length;
    range.data_crc32 = range_header.data_crc32;
    range.file_offset = range_header_offset + sizeof(range_header);
    sparse_ranges_.insert(std::make_pair(range.offset, range));

    range_header_offset += sizeof(range_header) + range.length;

    DCHECK_GE(sparse_data_size + range.length, sparse_data_size);
    sparse_data_size += range.length;
  }

  *out_sparse_data_size = static_cast<int32>(sparse_data_size);
  sparse_tail_offset_ = range_header_offset;

  return true;
}

bool SimpleSynchronousEntry::ReadSparseRange(const SparseRange* range,
                                             int offset, int len, char* buf) {
  DCHECK(range);
  DCHECK(buf);
  DCHECK_LE(offset, range->length);
  DCHECK_LE(offset + len, range->length);

  int bytes_read = sparse_file_.Read(range->file_offset + offset, buf, len);
  if (bytes_read < len) {
    DLOG(WARNING) << "Could not read sparse range.";
    return false;
  }

  // If we read the whole range and we have a crc32, check it.
  if (offset == 0 && len == range->length && range->data_crc32 != 0) {
    uint32 actual_crc32 = crc32(crc32(0L, Z_NULL, 0),
                                reinterpret_cast<const Bytef*>(buf),
                                len);
    if (actual_crc32 != range->data_crc32) {
      DLOG(WARNING) << "Sparse range crc32 mismatch.";
      return false;
    }
  }
  // TODO(ttuttle): Incremental crc32 calculation?

  return true;
}

bool SimpleSynchronousEntry::WriteSparseRange(SparseRange* range,
                                              int offset, int len,
                                              const char* buf) {
  DCHECK(range);
  DCHECK(buf);
  DCHECK_LE(offset, range->length);
  DCHECK_LE(offset + len, range->length);

  uint32 new_crc32 = 0;
  if (offset == 0 && len == range->length) {
    new_crc32 = crc32(crc32(0L, Z_NULL, 0),
                      reinterpret_cast<const Bytef*>(buf),
                      len);
  }

  if (new_crc32 != range->data_crc32) {
    range->data_crc32 = new_crc32;

    SimpleFileSparseRangeHeader header;
    header.sparse_range_magic_number = kSimpleSparseRangeMagicNumber;
    header.offset = range->offset;
    header.length = range->length;
    header.data_crc32 = range->data_crc32;

    int bytes_written = sparse_file_.Write(range->file_offset - sizeof(header),
                                           reinterpret_cast<char*>(&header),
                                           sizeof(header));
    if (bytes_written != implicit_cast<int>(sizeof(header))) {
      DLOG(WARNING) << "Could not rewrite sparse range header.";
      return false;
    }
  }

  int bytes_written = sparse_file_.Write(range->file_offset + offset, buf, len);
  if (bytes_written < len) {
    DLOG(WARNING) << "Could not write sparse range.";
    return false;
  }

  return true;
}

bool SimpleSynchronousEntry::AppendSparseRange(int64 offset,
                                               int len,
                                               const char* buf) {
  DCHECK_GE(offset, 0);
  DCHECK_GT(len, 0);
  DCHECK(buf);

  uint32 data_crc32 = crc32(crc32(0L, Z_NULL, 0),
                            reinterpret_cast<const Bytef*>(buf),
                            len);

  SimpleFileSparseRangeHeader header;
  header.sparse_range_magic_number = kSimpleSparseRangeMagicNumber;
  header.offset = offset;
  header.length = len;
  header.data_crc32 = data_crc32;

  int bytes_written = sparse_file_.Write(sparse_tail_offset_,
                                         reinterpret_cast<char*>(&header),
                                         sizeof(header));
  if (bytes_written != implicit_cast<int>(sizeof(header))) {
    DLOG(WARNING) << "Could not append sparse range header.";
    return false;
  }
  sparse_tail_offset_ += bytes_written;

  bytes_written = sparse_file_.Write(sparse_tail_offset_, buf, len);
  if (bytes_written < len) {
    DLOG(WARNING) << "Could not append sparse range data.";
    return false;
  }
  int64 data_file_offset = sparse_tail_offset_;
  sparse_tail_offset_ += bytes_written;

  SparseRange range;
  range.offset = offset;
  range.length = len;
  range.data_crc32 = data_crc32;
  range.file_offset = data_file_offset;
  sparse_ranges_.insert(std::make_pair(offset, range));

  return true;
}

}  // namespace disk_cache
