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