// 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 <algorithm> #include "base/logging.h" #include "net/disk_cache/flash/format.h" #include "net/disk_cache/flash/segment.h" #include "net/disk_cache/flash/storage.h" namespace disk_cache { Segment::Segment(int32 index, bool read_only, Storage* storage) : index_(index), num_users_(0), read_only_(read_only), init_(false), storage_(storage), offset_(index * kFlashSegmentSize), summary_offset_(offset_ + kFlashSegmentSize - kFlashSummarySize), write_offset_(offset_) { DCHECK(storage); DCHECK(storage->size() % kFlashSegmentSize == 0); } Segment::~Segment() { DCHECK(!init_ || read_only_); if (num_users_ != 0) LOG(WARNING) << "Users exist, but we don't care? " << num_users_; } bool Segment::HaveOffset(int32 offset) const { DCHECK(init_); return std::binary_search(offsets_.begin(), offsets_.end(), offset); } void Segment::AddUser() { DCHECK(init_); ++num_users_; } void Segment::ReleaseUser() { DCHECK(init_); --num_users_; } bool Segment::HasNoUsers() const { DCHECK(init_); return num_users_ == 0; } bool Segment::Init() { DCHECK(!init_); if (offset_ < 0 || offset_ + kFlashSegmentSize > storage_->size()) return false; if (!read_only_) { init_ = true; return true; } int32 summary[kFlashMaxEntryCount + 1]; if (!storage_->Read(summary, kFlashSummarySize, summary_offset_)) return false; size_t entry_count = summary[0]; DCHECK_LE(entry_count, kFlashMaxEntryCount); std::vector<int32> tmp(summary + 1, summary + 1 + entry_count); offsets_.swap(tmp); init_ = true; return true; } bool Segment::WriteData(const void* buffer, int32 size) { DCHECK(init_ && !read_only_); DCHECK(write_offset_ + size <= summary_offset_); if (!storage_->Write(buffer, size, write_offset_)) return false; write_offset_ += size; return true; } void Segment::StoreOffset(int32 offset) { DCHECK(init_ && !read_only_); DCHECK(offsets_.size() < kFlashMaxEntryCount); offsets_.push_back(offset); } bool Segment::ReadData(void* buffer, int32 size, int32 offset) const { DCHECK(init_); DCHECK(offset >= offset_ && offset + size <= offset_ + kFlashSegmentSize); return storage_->Read(buffer, size, offset); } bool Segment::Close() { DCHECK(init_); if (read_only_) return true; DCHECK(offsets_.size() <= kFlashMaxEntryCount); int32 summary[kFlashMaxEntryCount + 1]; memset(summary, 0, kFlashSummarySize); summary[0] = offsets_.size(); std::copy(offsets_.begin(), offsets_.end(), summary + 1); if (!storage_->Write(summary, kFlashSummarySize, summary_offset_)) return false; read_only_ = true; return true; } bool Segment::CanHold(int32 size) const { DCHECK(init_); return offsets_.size() < kFlashMaxEntryCount && write_offset_ + size <= summary_offset_; } } // namespace disk_cache