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_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 "base/hash.h" 11#include "base/logging.h" 12#include "net/disk_cache/blockfile/trace.h" 13 14namespace disk_cache { 15 16template<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 25template<typename T> StorageBlock<T>::~StorageBlock() { 26 if (modified_) 27 Store(); 28 DeleteData(); 29} 30 31template<typename T> void* StorageBlock<T>::buffer() const { 32 return data_; 33} 34 35template<typename T> size_t StorageBlock<T>::size() const { 36 if (!extended_) 37 return sizeof(*data_); 38 return address_.num_blocks() * sizeof(*data_); 39} 40 41template<typename T> int StorageBlock<T>::offset() const { 42 return address_.start_block() * address_.BlockSize(); 43} 44 45template<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 60template<typename T> void StorageBlock<T>::SetData(T* other) { 61 DCHECK(!modified_); 62 DeleteData(); 63 data_ = other; 64} 65 66template<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 79template<typename T> void StorageBlock<T>::StopSharingData() { 80 if (!data_ || own_data_) 81 return; 82 DCHECK(!modified_); 83 data_ = NULL; 84} 85 86template<typename T> void StorageBlock<T>::set_modified() { 87 DCHECK(data_); 88 modified_ = true; 89} 90 91template<typename T> void StorageBlock<T>::clear_modified() { 92 modified_ = false; 93} 94 95template<typename T> T* StorageBlock<T>::Data() { 96 if (!data_) 97 AllocateData(); 98 return data_; 99} 100 101template<typename T> bool StorageBlock<T>::HasData() const { 102 return (NULL != data_); 103} 104 105template<typename T> bool StorageBlock<T>::VerifyHash() const { 106 uint32 hash = CalculateHash(); 107 return (!data_->self_hash || data_->self_hash == hash); 108} 109 110template<typename T> bool StorageBlock<T>::own_data() const { 111 return own_data_; 112} 113 114template<typename T> const Addr StorageBlock<T>::address() const { 115 return address_; 116} 117 118template<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 133template<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 146template<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 162template<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 176template<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 187template<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 199template<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_BLOCKFILE_STORAGE_BLOCK_INL_H_ 206