1// Copyright (c) 2006-2008 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#pragma once
8
9#include "net/disk_cache/storage_block.h"
10
11#include "base/logging.h"
12#include "net/disk_cache/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> T* StorageBlock<T>::Data() {
92  if (!data_)
93    AllocateData();
94  return data_;
95}
96
97template<typename T> bool StorageBlock<T>::HasData() const {
98  return (NULL != data_);
99}
100
101template<typename T> bool StorageBlock<T>::own_data() const {
102  return own_data_;
103}
104
105template<typename T> const Addr StorageBlock<T>::address() const {
106  return address_;
107}
108
109template<typename T> bool StorageBlock<T>::Load() {
110  if (file_) {
111    if (!data_)
112      AllocateData();
113
114    if (file_->Load(this)) {
115      modified_ = false;
116      return true;
117    }
118  }
119  LOG(WARNING) << "Failed data load.";
120  Trace("Failed data load.");
121  return false;
122}
123
124template<typename T> bool StorageBlock<T>::Store() {
125  if (file_ && data_) {
126    if (file_->Store(this)) {
127      modified_ = false;
128      return true;
129    }
130  }
131  LOG(ERROR) << "Failed data store.";
132  Trace("Failed data store.");
133  return false;
134}
135
136template<typename T> void StorageBlock<T>::AllocateData() {
137  DCHECK(!data_);
138  if (!extended_) {
139    data_ = new T;
140  } else {
141    void* buffer = new char[address_.num_blocks() * sizeof(*data_)];
142    data_ = new(buffer) T;
143  }
144  own_data_ = true;
145}
146
147template<typename T> void StorageBlock<T>::DeleteData() {
148  if (own_data_) {
149    if (!extended_) {
150      delete data_;
151    } else {
152      data_->~T();
153      delete[] reinterpret_cast<char*>(data_);
154    }
155    own_data_ = false;
156  }
157}
158
159}  // namespace disk_cache
160
161#endif  // NET_DISK_CACHE_STORAGE_BLOCK_INL_H_
162