15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/disk_cache/flash/format.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/disk_cache/flash/segment.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/disk_cache/flash/storage.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace disk_cache {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Segment::Segment(int32 index, bool read_only, Storage* storage)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : index_(index),
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      num_users_(0),
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      read_only_(read_only),
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      init_(false),
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      storage_(storage),
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      offset_(index * kFlashSegmentSize),
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      summary_offset_(offset_ + kFlashSegmentSize - kFlashSummarySize),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      write_offset_(offset_) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(storage);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(storage->size() % kFlashSegmentSize == 0);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Segment::~Segment() {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!init_ || read_only_);
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (num_users_ != 0)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Users exist, but we don't care? " << num_users_;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Segment::HaveOffset(int32 offset) const {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return std::binary_search(offsets_.begin(), offsets_.end(), offset);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Segment::AddUser() {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ++num_users_;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Segment::ReleaseUser() {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_);
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  --num_users_;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Segment::HasNoUsers() const {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_);
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return num_users_ == 0;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Segment::Init() {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!init_);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (offset_ < 0 || offset_ + kFlashSegmentSize > storage_->size())
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!read_only_) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    init_ = true;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 summary[kFlashMaxEntryCount + 1];
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!storage_->Read(summary, kFlashSummarySize, summary_offset_))
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t entry_count = summary[0];
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(entry_count, kFlashMaxEntryCount);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int32> tmp(summary + 1, summary + 1 + entry_count);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  offsets_.swap(tmp);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_ = true;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Segment::WriteData(const void* buffer, int32 size) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(init_ && !read_only_);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(write_offset_ + size <= summary_offset_);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!storage_->Write(buffer, size, write_offset_))
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_offset_ += size;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Segment::StoreOffset(int32 offset) {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_ && !read_only_);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(offsets_.size() < kFlashMaxEntryCount);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  offsets_.push_back(offset);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Segment::ReadData(void* buffer, int32 size, int32 offset) const {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(offset >= offset_ && offset + size <= offset_ + kFlashSegmentSize);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return storage_->Read(buffer, size, offset);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Segment::Close() {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(init_);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_only_)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(offsets_.size() <= kFlashMaxEntryCount);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 summary[kFlashMaxEntryCount + 1];
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(summary, 0, kFlashSummarySize);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  summary[0] = offsets_.size();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::copy(offsets_.begin(), offsets_.end(), summary + 1);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!storage_->Write(summary, kFlashSummarySize, summary_offset_))
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_only_ = true;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Segment::CanHold(int32 size) const {
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(init_);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return offsets_.size() < kFlashMaxEntryCount &&
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      write_offset_ + size <= summary_offset_;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace disk_cache
123