// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef NET_DISK_CACHE_BLOCKFILE_STORAGE_BLOCK_INL_H_ #define NET_DISK_CACHE_BLOCKFILE_STORAGE_BLOCK_INL_H_ #include "net/disk_cache/blockfile/storage_block.h" #include #include #include #include "base/containers/span.h" #include "base/hash/hash.h" #include "base/logging.h" #include "base/notreached.h" namespace disk_cache { template StorageBlock::StorageBlock(MappedFile* file, Addr address) : file_(file), address_(address) { static_assert(std::is_trivial_v); // T is loaded as bytes from a file. DCHECK_NE(address.num_blocks(), 0); DCHECK(!address.is_initialized() || sizeof(T) == address.BlockSize()) << address.value(); } template StorageBlock::~StorageBlock() { if (modified_) Store(); DeleteData(); } template void StorageBlock::CopyFrom(StorageBlock* other) { DCHECK(!modified_); DCHECK(!other->modified_); Discard(); address_ = other->address_; file_ = other->file_; *Data() = *other->Data(); } template void* StorageBlock::buffer() const { return data_; } template size_t StorageBlock::size() const { return address_.num_blocks() * sizeof(T); } template int StorageBlock::offset() const { return address_.start_block() * address_.BlockSize(); } template bool StorageBlock::LazyInit(MappedFile* file, Addr address) { if (file_ || address_.is_initialized()) { NOTREACHED(); } file_ = file; address_.set_value(address.value()); DCHECK(sizeof(T) == address.BlockSize()); return true; } template void StorageBlock::SetData(T* other) { DCHECK(!modified_); DeleteData(); data_ = other; } template void StorageBlock::Discard() { if (!data_) return; if (!own_data_) { NOTREACHED(); } DeleteData(); data_ = nullptr; modified_ = false; } template void StorageBlock::StopSharingData() { if (!data_ || own_data_) return; DCHECK(!modified_); data_ = nullptr; } template void StorageBlock::set_modified() { DCHECK(data_); modified_ = true; } template void StorageBlock::clear_modified() { modified_ = false; } template T* StorageBlock::Data() { if (!data_) AllocateData(); return data_; } template bool StorageBlock::HasData() const { return (nullptr != data_); } template bool StorageBlock::VerifyHash() const { uint32_t hash = CalculateHash(); return (!data_->self_hash || data_->self_hash == hash); } template bool StorageBlock::own_data() const { return own_data_; } template const Addr StorageBlock::address() const { return address_; } template bool StorageBlock::Load() { if (file_) { if (!data_) AllocateData(); if (file_->Load(this)) { modified_ = false; return true; } } LOG(WARNING) << "Failed data load."; return false; } template bool StorageBlock::Store() { if (file_ && data_) { data_->self_hash = CalculateHash(); if (file_->Store(this)) { modified_ = false; return true; } } LOG(ERROR) << "Failed data store."; return false; } template bool StorageBlock::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."; return false; } template bool StorageBlock::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."; return false; } template void StorageBlock::AllocateData() { DCHECK(!data_); data_ = new T[address_.num_blocks()]; own_data_ = true; } template void StorageBlock::DeleteData() { if (own_data_) { data_.ClearAndDeleteArray(); own_data_ = false; } } template uint32_t StorageBlock::CalculateHash() const { base::span bytes = base::as_bytes(base::span_from_ref(*data_)); return base::PersistentHash(bytes.first(offsetof(T, self_hash))); } } // namespace disk_cache #endif // NET_DISK_CACHE_BLOCKFILE_STORAGE_BLOCK_INL_H_