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 <type_traits>
14
15 #include "base/containers/span.h"
16 #include "base/hash/hash.h"
17 #include "base/logging.h"
18 #include "base/notreached.h"
19
20 namespace disk_cache {
21
22 template <typename T>
StorageBlock(MappedFile * file,Addr address)23 StorageBlock<T>::StorageBlock(MappedFile* file, Addr address)
24 : file_(file), address_(address) {
25 static_assert(std::is_trivial_v<T>); // T is loaded as bytes from a file.
26 DCHECK_NE(address.num_blocks(), 0);
27 DCHECK(!address.is_initialized() || sizeof(T) == address.BlockSize())
28 << address.value();
29 }
30
~StorageBlock()31 template<typename T> StorageBlock<T>::~StorageBlock() {
32 if (modified_)
33 Store();
34 DeleteData();
35 }
36
37 template <typename T>
CopyFrom(StorageBlock<T> * other)38 void StorageBlock<T>::CopyFrom(StorageBlock<T>* other) {
39 DCHECK(!modified_);
40 DCHECK(!other->modified_);
41 Discard();
42 address_ = other->address_;
43 file_ = other->file_;
44 *Data() = *other->Data();
45 }
46
buffer()47 template<typename T> void* StorageBlock<T>::buffer() const {
48 return data_;
49 }
50
size()51 template<typename T> size_t StorageBlock<T>::size() const {
52 return address_.num_blocks() * sizeof(T);
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 }
64 file_ = file;
65 address_.set_value(address.value());
66 DCHECK(sizeof(T) == address.BlockSize());
67 return true;
68 }
69
SetData(T * other)70 template<typename T> void StorageBlock<T>::SetData(T* other) {
71 DCHECK(!modified_);
72 DeleteData();
73 data_ = other;
74 }
75
Discard()76 template<typename T> void StorageBlock<T>::Discard() {
77 if (!data_)
78 return;
79 if (!own_data_) {
80 NOTREACHED();
81 }
82 DeleteData();
83 data_ = nullptr;
84 modified_ = false;
85 }
86
StopSharingData()87 template<typename T> void StorageBlock<T>::StopSharingData() {
88 if (!data_ || own_data_)
89 return;
90 DCHECK(!modified_);
91 data_ = nullptr;
92 }
93
set_modified()94 template<typename T> void StorageBlock<T>::set_modified() {
95 DCHECK(data_);
96 modified_ = true;
97 }
98
clear_modified()99 template<typename T> void StorageBlock<T>::clear_modified() {
100 modified_ = false;
101 }
102
Data()103 template<typename T> T* StorageBlock<T>::Data() {
104 if (!data_)
105 AllocateData();
106 return data_;
107 }
108
HasData()109 template<typename T> bool StorageBlock<T>::HasData() const {
110 return (nullptr != data_);
111 }
112
VerifyHash()113 template<typename T> bool StorageBlock<T>::VerifyHash() const {
114 uint32_t hash = CalculateHash();
115 return (!data_->self_hash || data_->self_hash == hash);
116 }
117
own_data()118 template<typename T> bool StorageBlock<T>::own_data() const {
119 return own_data_;
120 }
121
address()122 template<typename T> const Addr StorageBlock<T>::address() const {
123 return address_;
124 }
125
Load()126 template<typename T> bool StorageBlock<T>::Load() {
127 if (file_) {
128 if (!data_)
129 AllocateData();
130
131 if (file_->Load(this)) {
132 modified_ = false;
133 return true;
134 }
135 }
136 LOG(WARNING) << "Failed data load.";
137 return false;
138 }
139
Store()140 template<typename T> bool StorageBlock<T>::Store() {
141 if (file_ && data_) {
142 data_->self_hash = CalculateHash();
143 if (file_->Store(this)) {
144 modified_ = false;
145 return true;
146 }
147 }
148 LOG(ERROR) << "Failed data store.";
149 return false;
150 }
151
Load(FileIOCallback * callback,bool * completed)152 template<typename T> bool StorageBlock<T>::Load(FileIOCallback* callback,
153 bool* completed) {
154 if (file_) {
155 if (!data_)
156 AllocateData();
157
158 if (file_->Load(this, callback, completed)) {
159 modified_ = false;
160 return true;
161 }
162 }
163 LOG(WARNING) << "Failed data load.";
164 return false;
165 }
166
Store(FileIOCallback * callback,bool * completed)167 template<typename T> bool StorageBlock<T>::Store(FileIOCallback* callback,
168 bool* completed) {
169 if (file_ && data_) {
170 data_->self_hash = CalculateHash();
171 if (file_->Store(this, callback, completed)) {
172 modified_ = false;
173 return true;
174 }
175 }
176 LOG(ERROR) << "Failed data store.";
177 return false;
178 }
179
AllocateData()180 template<typename T> void StorageBlock<T>::AllocateData() {
181 DCHECK(!data_);
182 data_ = new T[address_.num_blocks()];
183 own_data_ = true;
184 }
185
DeleteData()186 template<typename T> void StorageBlock<T>::DeleteData() {
187 if (own_data_) {
188 data_.ClearAndDeleteArray();
189 own_data_ = false;
190 }
191 }
192
193 template <typename T>
CalculateHash()194 uint32_t StorageBlock<T>::CalculateHash() const {
195 base::span<const uint8_t> bytes = base::as_bytes(base::span_from_ref(*data_));
196 return base::PersistentHash(bytes.first(offsetof(T, self_hash)));
197 }
198
199 } // namespace disk_cache
200
201 #endif // NET_DISK_CACHE_BLOCKFILE_STORAGE_BLOCK_INL_H_
202