1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef NET_DISK_CACHE_BLOCKFILE_STORAGE_BLOCK_INL_H_
6 #define NET_DISK_CACHE_BLOCKFILE_STORAGE_BLOCK_INL_H_
7
8 #include "net/disk_cache/blockfile/storage_block.h"
9
10 #include <stddef.h>
11 #include <stdint.h>
12
13 #include "base/hash/hash.h"
14 #include "base/logging.h"
15 #include "base/notreached.h"
16
17 namespace disk_cache {
18
19 template <typename T>
StorageBlock(MappedFile * file,Addr address)20 StorageBlock<T>::StorageBlock(MappedFile* file, Addr address)
21 : file_(file), address_(address) {
22 if (address.num_blocks() > 1)
23 extended_ = true;
24 DCHECK(!address.is_initialized() || sizeof(*data_) == address.BlockSize())
25 << address.value();
26 }
27
~StorageBlock()28 template<typename T> StorageBlock<T>::~StorageBlock() {
29 if (modified_)
30 Store();
31 DeleteData();
32 }
33
34 template <typename T>
CopyFrom(StorageBlock<T> * other)35 void StorageBlock<T>::CopyFrom(StorageBlock<T>* other) {
36 DCHECK(!modified_);
37 DCHECK(!other->modified_);
38 Discard();
39 *Data() = *other->Data();
40 file_ = other->file_;
41 address_ = other->address_;
42 extended_ = other->extended_;
43 }
44
buffer()45 template<typename T> void* StorageBlock<T>::buffer() const {
46 return data_;
47 }
48
size()49 template<typename T> size_t StorageBlock<T>::size() const {
50 if (!extended_)
51 return sizeof(*data_);
52 return address_.num_blocks() * sizeof(*data_);
53 }
54
offset()55 template<typename T> int StorageBlock<T>::offset() const {
56 return address_.start_block() * address_.BlockSize();
57 }
58
LazyInit(MappedFile * file,Addr address)59 template<typename T> bool StorageBlock<T>::LazyInit(MappedFile* file,
60 Addr address) {
61 if (file_ || address_.is_initialized()) {
62 NOTREACHED();
63 return false;
64 }
65 file_ = file;
66 address_.set_value(address.value());
67 if (address.num_blocks() > 1)
68 extended_ = true;
69
70 DCHECK(sizeof(*data_) == address.BlockSize());
71 return true;
72 }
73
SetData(T * other)74 template<typename T> void StorageBlock<T>::SetData(T* other) {
75 DCHECK(!modified_);
76 DeleteData();
77 data_ = other;
78 }
79
Discard()80 template<typename T> void StorageBlock<T>::Discard() {
81 if (!data_)
82 return;
83 if (!own_data_) {
84 NOTREACHED();
85 return;
86 }
87 DeleteData();
88 data_ = nullptr;
89 modified_ = false;
90 extended_ = false;
91 }
92
StopSharingData()93 template<typename T> void StorageBlock<T>::StopSharingData() {
94 if (!data_ || own_data_)
95 return;
96 DCHECK(!modified_);
97 data_ = nullptr;
98 }
99
set_modified()100 template<typename T> void StorageBlock<T>::set_modified() {
101 DCHECK(data_);
102 modified_ = true;
103 }
104
clear_modified()105 template<typename T> void StorageBlock<T>::clear_modified() {
106 modified_ = false;
107 }
108
Data()109 template<typename T> T* StorageBlock<T>::Data() {
110 if (!data_)
111 AllocateData();
112 return data_;
113 }
114
HasData()115 template<typename T> bool StorageBlock<T>::HasData() const {
116 return (nullptr != data_);
117 }
118
VerifyHash()119 template<typename T> bool StorageBlock<T>::VerifyHash() const {
120 uint32_t hash = CalculateHash();
121 return (!data_->self_hash || data_->self_hash == hash);
122 }
123
own_data()124 template<typename T> bool StorageBlock<T>::own_data() const {
125 return own_data_;
126 }
127
address()128 template<typename T> const Addr StorageBlock<T>::address() const {
129 return address_;
130 }
131
Load()132 template<typename T> bool StorageBlock<T>::Load() {
133 if (file_) {
134 if (!data_)
135 AllocateData();
136
137 if (file_->Load(this)) {
138 modified_ = false;
139 return true;
140 }
141 }
142 LOG(WARNING) << "Failed data load.";
143 return false;
144 }
145
Store()146 template<typename T> bool StorageBlock<T>::Store() {
147 if (file_ && data_) {
148 data_->self_hash = CalculateHash();
149 if (file_->Store(this)) {
150 modified_ = false;
151 return true;
152 }
153 }
154 LOG(ERROR) << "Failed data store.";
155 return false;
156 }
157
Load(FileIOCallback * callback,bool * completed)158 template<typename T> bool StorageBlock<T>::Load(FileIOCallback* callback,
159 bool* completed) {
160 if (file_) {
161 if (!data_)
162 AllocateData();
163
164 if (file_->Load(this, callback, completed)) {
165 modified_ = false;
166 return true;
167 }
168 }
169 LOG(WARNING) << "Failed data load.";
170 return false;
171 }
172
Store(FileIOCallback * callback,bool * completed)173 template<typename T> bool StorageBlock<T>::Store(FileIOCallback* callback,
174 bool* completed) {
175 if (file_ && data_) {
176 data_->self_hash = CalculateHash();
177 if (file_->Store(this, callback, completed)) {
178 modified_ = false;
179 return true;
180 }
181 }
182 LOG(ERROR) << "Failed data store.";
183 return false;
184 }
185
AllocateData()186 template<typename T> void StorageBlock<T>::AllocateData() {
187 DCHECK(!data_);
188 if (!extended_) {
189 data_ = new T;
190 } else {
191 void* buffer = new char[address_.num_blocks() * sizeof(*data_)];
192 data_ = new(buffer) T;
193 }
194 own_data_ = true;
195 }
196
DeleteData()197 template<typename T> void StorageBlock<T>::DeleteData() {
198 if (own_data_) {
199 if (!extended_) {
200 data_.ClearAndDelete();
201 } else {
202 data_->~T();
203 delete[] reinterpret_cast<char*>(data_.ExtractAsDangling().get());
204 }
205 own_data_ = false;
206 }
207 }
208
209 template <typename T>
CalculateHash()210 uint32_t StorageBlock<T>::CalculateHash() const {
211 return base::PersistentHash(data_, offsetof(T, self_hash));
212 }
213
214 } // namespace disk_cache
215
216 #endif // NET_DISK_CACHE_BLOCKFILE_STORAGE_BLOCK_INL_H_
217