xref: /aosp_15_r20/external/cronet/net/disk_cache/blockfile/storage_block-inl.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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     return false;
64   }
65   file_ = file;
66   address_.set_value(address.value());
67   DCHECK(sizeof(T) == address.BlockSize());
68   return true;
69 }
70 
SetData(T * other)71 template<typename T> void StorageBlock<T>::SetData(T* other) {
72   DCHECK(!modified_);
73   DeleteData();
74   data_ = other;
75 }
76 
Discard()77 template<typename T> void  StorageBlock<T>::Discard() {
78   if (!data_)
79     return;
80   if (!own_data_) {
81     NOTREACHED();
82     return;
83   }
84   DeleteData();
85   data_ = nullptr;
86   modified_ = false;
87 }
88 
StopSharingData()89 template<typename T> void  StorageBlock<T>::StopSharingData() {
90   if (!data_ || own_data_)
91     return;
92   DCHECK(!modified_);
93   data_ = nullptr;
94 }
95 
set_modified()96 template<typename T> void StorageBlock<T>::set_modified() {
97   DCHECK(data_);
98   modified_ = true;
99 }
100 
clear_modified()101 template<typename T> void StorageBlock<T>::clear_modified() {
102   modified_ = false;
103 }
104 
Data()105 template<typename T> T* StorageBlock<T>::Data() {
106   if (!data_)
107     AllocateData();
108   return data_;
109 }
110 
HasData()111 template<typename T> bool StorageBlock<T>::HasData() const {
112   return (nullptr != data_);
113 }
114 
VerifyHash()115 template<typename T> bool StorageBlock<T>::VerifyHash() const {
116   uint32_t hash = CalculateHash();
117   return (!data_->self_hash || data_->self_hash == hash);
118 }
119 
own_data()120 template<typename T> bool StorageBlock<T>::own_data() const {
121   return own_data_;
122 }
123 
address()124 template<typename T> const Addr StorageBlock<T>::address() const {
125   return address_;
126 }
127 
Load()128 template<typename T> bool StorageBlock<T>::Load() {
129   if (file_) {
130     if (!data_)
131       AllocateData();
132 
133     if (file_->Load(this)) {
134       modified_ = false;
135       return true;
136     }
137   }
138   LOG(WARNING) << "Failed data load.";
139   return false;
140 }
141 
Store()142 template<typename T> bool StorageBlock<T>::Store() {
143   if (file_ && data_) {
144     data_->self_hash = CalculateHash();
145     if (file_->Store(this)) {
146       modified_ = false;
147       return true;
148     }
149   }
150   LOG(ERROR) << "Failed data store.";
151   return false;
152 }
153 
Load(FileIOCallback * callback,bool * completed)154 template<typename T> bool StorageBlock<T>::Load(FileIOCallback* callback,
155                                                 bool* completed) {
156   if (file_) {
157     if (!data_)
158       AllocateData();
159 
160     if (file_->Load(this, callback, completed)) {
161       modified_ = false;
162       return true;
163     }
164   }
165   LOG(WARNING) << "Failed data load.";
166   return false;
167 }
168 
Store(FileIOCallback * callback,bool * completed)169 template<typename T> bool StorageBlock<T>::Store(FileIOCallback* callback,
170                                                  bool* completed) {
171   if (file_ && data_) {
172     data_->self_hash = CalculateHash();
173     if (file_->Store(this, callback, completed)) {
174       modified_ = false;
175       return true;
176     }
177   }
178   LOG(ERROR) << "Failed data store.";
179   return false;
180 }
181 
AllocateData()182 template<typename T> void StorageBlock<T>::AllocateData() {
183   DCHECK(!data_);
184   data_ = new T[address_.num_blocks()];
185   own_data_ = true;
186 }
187 
DeleteData()188 template<typename T> void StorageBlock<T>::DeleteData() {
189   if (own_data_) {
190     data_.ClearAndDeleteArray();
191     own_data_ = false;
192   }
193 }
194 
195 template <typename T>
CalculateHash()196 uint32_t StorageBlock<T>::CalculateHash() const {
197   base::span<const uint8_t> bytes = base::as_bytes(base::span_from_ref(*data_));
198   return base::PersistentHash(bytes.first(offsetof(T, self_hash)));
199 }
200 
201 }  // namespace disk_cache
202 
203 #endif  // NET_DISK_CACHE_BLOCKFILE_STORAGE_BLOCK_INL_H_
204