storage_block-inl.h revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifndef NET_DISK_CACHE_BLOCKFILE_STORAGE_BLOCK_INL_H_
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define NET_DISK_CACHE_BLOCKFILE_STORAGE_BLOCK_INL_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/storage_block.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/hash.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/trace.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace disk_cache {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> StorageBlock<T>::StorageBlock(MappedFile* file,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   Addr address)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : data_(NULL), file_(file), address_(address), modified_(false),
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      own_data_(false), extended_(false) {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address.num_blocks() > 1)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extended_ = true;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!address.is_initialized() || sizeof(*data_) == address.BlockSize());
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> StorageBlock<T>::~StorageBlock() {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modified_)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Store();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteData();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> void* StorageBlock<T>::buffer() const {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data_;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> size_t StorageBlock<T>::size() const {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extended_)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sizeof(*data_);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return address_.num_blocks() * sizeof(*data_);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> int StorageBlock<T>::offset() const {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return address_.start_block() * address_.BlockSize();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> bool StorageBlock<T>::LazyInit(MappedFile* file,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    Addr address) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_ || address_.is_initialized()) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_ = file;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  address_.set_value(address.value());
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address.num_blocks() > 1)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extended_ = true;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(sizeof(*data_) == address.BlockSize());
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> void StorageBlock<T>::SetData(T* other) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!modified_);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteData();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_ = other;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> void  StorageBlock<T>::Discard() {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data_)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!own_data_) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteData();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_ = NULL;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  modified_ = false;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extended_ = false;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> void  StorageBlock<T>::StopSharingData() {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data_ || own_data_)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!modified_);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_ = NULL;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> void StorageBlock<T>::set_modified() {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data_);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  modified_ = true;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> void StorageBlock<T>::clear_modified() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  modified_ = false;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> T* StorageBlock<T>::Data() {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data_)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AllocateData();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> bool StorageBlock<T>::HasData() const {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (NULL != data_);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> bool StorageBlock<T>::VerifyHash() const {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 hash = CalculateHash();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (!data_->self_hash || data_->self_hash == hash);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> bool StorageBlock<T>::own_data() const {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return own_data_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> const Addr StorageBlock<T>::address() const {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return address_;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> bool StorageBlock<T>::Load() {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!data_)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AllocateData();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_->Load(this)) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      modified_ = false;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(WARNING) << "Failed data load.";
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Trace("Failed data load.");
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> bool StorageBlock<T>::Store() {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_ && data_) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_->self_hash = CalculateHash();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_->Store(this)) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      modified_ = false;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(ERROR) << "Failed data store.";
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Trace("Failed data store.");
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<typename T> bool StorageBlock<T>::Load(FileIOCallback* callback,
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                                bool* completed) {
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (file_) {
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!data_)
15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      AllocateData();
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (file_->Load(this, callback, completed)) {
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      modified_ = false;
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return true;
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LOG(WARNING) << "Failed data load.";
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Trace("Failed data load.");
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return false;
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)template<typename T> bool StorageBlock<T>::Store(FileIOCallback* callback,
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                                 bool* completed) {
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (file_ && data_) {
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    data_->self_hash = CalculateHash();
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (file_->Store(this, callback, completed)) {
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      modified_ = false;
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return true;
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LOG(ERROR) << "Failed data store.";
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Trace("Failed data store.");
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return false;
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> void StorageBlock<T>::AllocateData() {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!data_);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extended_) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_ = new T;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* buffer = new char[address_.num_blocks() * sizeof(*data_)];
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_ = new(buffer) T;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  own_data_ = true;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> void StorageBlock<T>::DeleteData() {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (own_data_) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!extended_) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete data_;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_->~T();
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete[] reinterpret_cast<char*>(data_);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    own_data_ = false;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> uint32 StorageBlock<T>::CalculateHash() const {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::Hash(reinterpret_cast<char*>(data_), offsetof(T, self_hash));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace disk_cache
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  // NET_DISK_CACHE_BLOCKFILE_STORAGE_BLOCK_INL_H_
206