1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <algorithm> 6 7 #include "base/logging.h" 8 #include "net/disk_cache/flash/format.h" 9 #include "net/disk_cache/flash/segment.h" 10 #include "net/disk_cache/flash/storage.h" 11 12 namespace disk_cache { 13 14 Segment::Segment(int32 index, bool read_only, Storage* storage) 15 : index_(index), 16 num_users_(0), 17 read_only_(read_only), 18 init_(false), 19 storage_(storage), 20 offset_(index * kFlashSegmentSize), 21 summary_offset_(offset_ + kFlashSegmentSize - kFlashSummarySize), 22 write_offset_(offset_) { 23 DCHECK(storage); 24 DCHECK(storage->size() % kFlashSegmentSize == 0); 25 } 26 27 Segment::~Segment() { 28 DCHECK(!init_ || read_only_); 29 if (num_users_ != 0) 30 LOG(WARNING) << "Users exist, but we don't care? " << num_users_; 31 } 32 33 bool Segment::HaveOffset(int32 offset) const { 34 DCHECK(init_); 35 return std::binary_search(offsets_.begin(), offsets_.end(), offset); 36 } 37 38 void Segment::AddUser() { 39 DCHECK(init_); 40 ++num_users_; 41 } 42 43 void Segment::ReleaseUser() { 44 DCHECK(init_); 45 --num_users_; 46 } 47 48 bool Segment::HasNoUsers() const { 49 DCHECK(init_); 50 return num_users_ == 0; 51 } 52 53 bool Segment::Init() { 54 DCHECK(!init_); 55 56 if (offset_ < 0 || offset_ + kFlashSegmentSize > storage_->size()) 57 return false; 58 59 if (!read_only_) { 60 init_ = true; 61 return true; 62 } 63 64 int32 summary[kFlashMaxEntryCount + 1]; 65 if (!storage_->Read(summary, kFlashSummarySize, summary_offset_)) 66 return false; 67 68 size_t entry_count = summary[0]; 69 DCHECK_LE(entry_count, kFlashMaxEntryCount); 70 71 std::vector<int32> tmp(summary + 1, summary + 1 + entry_count); 72 offsets_.swap(tmp); 73 init_ = true; 74 return true; 75 } 76 77 bool Segment::WriteData(const void* buffer, int32 size) { 78 DCHECK(init_ && !read_only_); 79 DCHECK(write_offset_ + size <= summary_offset_); 80 if (!storage_->Write(buffer, size, write_offset_)) 81 return false; 82 write_offset_ += size; 83 return true; 84 } 85 86 void Segment::StoreOffset(int32 offset) { 87 DCHECK(init_ && !read_only_); 88 DCHECK(offsets_.size() < kFlashMaxEntryCount); 89 offsets_.push_back(offset); 90 } 91 92 bool Segment::ReadData(void* buffer, int32 size, int32 offset) const { 93 DCHECK(init_); 94 DCHECK(offset >= offset_ && offset + size <= offset_ + kFlashSegmentSize); 95 return storage_->Read(buffer, size, offset); 96 } 97 98 bool Segment::Close() { 99 DCHECK(init_); 100 if (read_only_) 101 return true; 102 103 DCHECK(offsets_.size() <= kFlashMaxEntryCount); 104 105 int32 summary[kFlashMaxEntryCount + 1]; 106 memset(summary, 0, kFlashSummarySize); 107 summary[0] = offsets_.size(); 108 std::copy(offsets_.begin(), offsets_.end(), summary + 1); 109 if (!storage_->Write(summary, kFlashSummarySize, summary_offset_)) 110 return false; 111 112 read_only_ = true; 113 return true; 114 } 115 116 bool Segment::CanHold(int32 size) const { 117 DCHECK(init_); 118 return offsets_.size() < kFlashMaxEntryCount && 119 write_offset_ + size <= summary_offset_; 120 } 121 122 } // namespace disk_cache 123