12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h"
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/disk_cache/flash/format.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/disk_cache/flash/log_store.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/disk_cache/flash/log_store_entry.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace disk_cache {
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogStoreEntry::LogStoreEntry(LogStore* store)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : store_(store), id_(-1), init_(false), closed_(false), deleted_(false) {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(store);
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogStoreEntry::LogStoreEntry(LogStore* store, int32 id)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : store_(store), id_(id), init_(false), closed_(false), deleted_(false) {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(store);
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogStoreEntry::~LogStoreEntry() {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!init_ || closed_);
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LogStoreEntry::Init() {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!init_);
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsNew()) {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    init_ = true;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 stream_sizes[kFlashLogStoreEntryNumStreams];
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  COMPILE_ASSERT(sizeof(stream_sizes) == kFlashLogStoreEntryHeaderSize,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 invalid_log_store_entry_header_size);
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!store_->OpenEntry(id_) ||
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !store_->ReadData(id_, stream_sizes, kFlashLogStoreEntryHeaderSize, 0)) {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0, offset = kFlashLogStoreEntryHeaderSize;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < kFlashLogStoreEntryNumStreams; ++i) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    streams_[i].offset = offset;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    streams_[i].size = stream_sizes[i];
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    offset += stream_sizes[i];
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  init_ = true;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LogStoreEntry::Close() {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_ && !closed_);
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsNew()) {
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    closed_ = deleted_ ? true : Save();
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    store_->CloseEntry(id_);
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (deleted_)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      store_->DeleteEntry(id_, Size());
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    closed_ = true;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return closed_;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 LogStoreEntry::id() const {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return id_;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 LogStoreEntry::GetDataSize(int index) const {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return InvalidStream(index) ? 0 : streams_[index].size;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int LogStoreEntry::ReadData(int index, int offset, net::IOBuffer* buf,
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            int buf_len) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (InvalidStream(index))
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return net::ERR_INVALID_ARGUMENT;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int stream_size = streams_[index].size;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (offset >= stream_size || offset < 0 || buf_len == 0)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (offset + buf_len > stream_size)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buf_len = stream_size - offset;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IsNew()) {
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    offset += streams_[index].offset;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (store_->ReadData(id_, buf->data(), buf_len, offset))
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return buf_len;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return net::ERR_FAILED;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memcpy(buf->data(), &streams_[index].write_buffer[offset], buf_len);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return buf_len;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int LogStoreEntry::WriteData(int index, int offset, net::IOBuffer* buf,
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int buf_len) {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_ && !closed_);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (InvalidStream(index))
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return net::ERR_INVALID_ARGUMENT;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(offset >= 0 && buf_len >= 0);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Stream& stream = streams_[index];
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t new_size = static_cast<size_t>(offset + buf_len);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (new_size) {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(agayev): Currently, only append and overwrite is supported.  Add
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // support for arbitrary writes.
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!offset || offset == stream.size);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (stream.write_buffer.size() < new_size)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream.write_buffer.resize(new_size);
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    memcpy(&streams_[index].write_buffer[offset], buf->data(), buf_len);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream.size = new_size;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return buf_len;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LogStoreEntry::Delete() {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_ && !closed_);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  deleted_ = true;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool LogStoreEntry::IsNew() const {
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return id_ == -1;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LogStoreEntry::InvalidStream(int stream_index) const {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return stream_index < 0 || stream_index >= kFlashLogStoreEntryNumStreams;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 LogStoreEntry::Size() const {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 size = kFlashLogStoreEntryHeaderSize;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < kFlashLogStoreEntryNumStreams; ++i)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size += streams_[i].size;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(size > 0 && size <= kFlashSegmentFreeSpace);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return size;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LogStoreEntry::Save() {
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(init_ && !closed_ && !deleted_ && IsNew());
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 stream_sizes[kFlashLogStoreEntryNumStreams];
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  COMPILE_ASSERT(sizeof(stream_sizes) == kFlashLogStoreEntryHeaderSize,
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 invalid_log_store_entry_header_size);
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < kFlashLogStoreEntryNumStreams; ++i)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    stream_sizes[i] = streams_[i].size;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!store_->CreateEntry(Size(), &id_))
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!store_->WriteData(stream_sizes, kFlashLogStoreEntryHeaderSize))
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < kFlashLogStoreEntryNumStreams; ++i) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (streams_[i].size > 0 &&
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        !store_->WriteData(&streams_[i].write_buffer[0], streams_[i].size)) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  store_->CloseEntry(id_);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogStoreEntry::Stream::Stream() : offset(0), size(0) {
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogStoreEntry::Stream::~Stream() {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace disk_cache
172