// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef NET_DISK_CACHE_STORAGE_BLOCK_INL_H_ #define NET_DISK_CACHE_STORAGE_BLOCK_INL_H_ #include "net/disk_cache/storage_block.h" #include "base/hash.h" #include "base/logging.h" #include "net/disk_cache/trace.h" namespace disk_cache { template<typename T> StorageBlock<T>::StorageBlock(MappedFile* file, Addr address) : data_(NULL), file_(file), address_(address), modified_(false), own_data_(false), extended_(false) { if (address.num_blocks() > 1) extended_ = true; DCHECK(!address.is_initialized() || sizeof(*data_) == address.BlockSize()); } template<typename T> StorageBlock<T>::~StorageBlock() { if (modified_) Store(); DeleteData(); } template<typename T> void* StorageBlock<T>::buffer() const { return data_; } template<typename T> size_t StorageBlock<T>::size() const { if (!extended_) return sizeof(*data_); return address_.num_blocks() * sizeof(*data_); } template<typename T> int StorageBlock<T>::offset() const { return address_.start_block() * address_.BlockSize(); } template<typename T> bool StorageBlock<T>::LazyInit(MappedFile* file, Addr address) { if (file_ || address_.is_initialized()) { NOTREACHED(); return false; } file_ = file; address_.set_value(address.value()); if (address.num_blocks() > 1) extended_ = true; DCHECK(sizeof(*data_) == address.BlockSize()); return true; } template<typename T> void StorageBlock<T>::SetData(T* other) { DCHECK(!modified_); DeleteData(); data_ = other; } template<typename T> void StorageBlock<T>::Discard() { if (!data_) return; if (!own_data_) { NOTREACHED(); return; } DeleteData(); data_ = NULL; modified_ = false; extended_ = false; } template<typename T> void StorageBlock<T>::StopSharingData() { if (!data_ || own_data_) return; DCHECK(!modified_); data_ = NULL; } template<typename T> void StorageBlock<T>::set_modified() { DCHECK(data_); modified_ = true; } template<typename T> void StorageBlock<T>::clear_modified() { modified_ = false; } template<typename T> T* StorageBlock<T>::Data() { if (!data_) AllocateData(); return data_; } template<typename T> bool StorageBlock<T>::HasData() const { return (NULL != data_); } template<typename T> bool StorageBlock<T>::VerifyHash() const { uint32 hash = CalculateHash(); return (!data_->self_hash || data_->self_hash == hash); } template<typename T> bool StorageBlock<T>::own_data() const { return own_data_; } template<typename T> const Addr StorageBlock<T>::address() const { return address_; } template<typename T> bool StorageBlock<T>::Load() { if (file_) { if (!data_) AllocateData(); if (file_->Load(this)) { modified_ = false; return true; } } LOG(WARNING) << "Failed data load."; Trace("Failed data load."); return false; } template<typename T> bool StorageBlock<T>::Store() { if (file_ && data_) { data_->self_hash = CalculateHash(); if (file_->Store(this)) { modified_ = false; return true; } } LOG(ERROR) << "Failed data store."; Trace("Failed data store."); return false; } template<typename T> bool StorageBlock<T>::Load(FileIOCallback* callback, bool* completed) { if (file_) { if (!data_) AllocateData(); if (file_->Load(this, callback, completed)) { modified_ = false; return true; } } LOG(WARNING) << "Failed data load."; Trace("Failed data load."); return false; } template<typename T> bool StorageBlock<T>::Store(FileIOCallback* callback, bool* completed) { if (file_ && data_) { data_->self_hash = CalculateHash(); if (file_->Store(this, callback, completed)) { modified_ = false; return true; } } LOG(ERROR) << "Failed data store."; Trace("Failed data store."); return false; } template<typename T> void StorageBlock<T>::AllocateData() { DCHECK(!data_); if (!extended_) { data_ = new T; } else { void* buffer = new char[address_.num_blocks() * sizeof(*data_)]; data_ = new(buffer) T; } own_data_ = true; } template<typename T> void StorageBlock<T>::DeleteData() { if (own_data_) { if (!extended_) { delete data_; } else { data_->~T(); delete[] reinterpret_cast<char*>(data_); } own_data_ = false; } } template<typename T> uint32 StorageBlock<T>::CalculateHash() const { return base::Hash(reinterpret_cast<char*>(data_), offsetof(T, self_hash)); } } // namespace disk_cache #endif // NET_DISK_CACHE_STORAGE_BLOCK_INL_H_