blob: 2f7713b6930d87cf1184b51af5f1a4991fcbeb2c [file] [log] [blame]
[email protected]c34e9a7a2011-05-11 12:06:571// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
5#include "net/disk_cache/mem_backend_impl.h"
6
[email protected]56d01f62009-03-12 22:41:547#include "base/logging.h"
[email protected]b4f71a8d2008-09-17 15:32:038#include "base/sys_info.h"
[email protected]3cf35d9e2009-11-05 23:27:419#include "net/base/net_errors.h"
[email protected]408d35f52008-08-13 18:30:2210#include "net/disk_cache/cache_util.h"
initial.commit586acc5fe2008-07-26 22:42:5211#include "net/disk_cache/mem_entry_impl.h"
12
[email protected]e1acf6f2008-10-27 20:43:3313using base::Time;
14
initial.commit586acc5fe2008-07-26 22:42:5215namespace {
16
17const int kDefaultCacheSize = 10 * 1024 * 1024;
18const int kCleanUpMargin = 1024 * 1024;
19
20int LowWaterAdjust(int high_water) {
21 if (high_water < kCleanUpMargin)
22 return 0;
23
24 return high_water - kCleanUpMargin;
25}
26
27} // namespace
28
29namespace disk_cache {
30
[email protected]9eb8cdf2011-03-17 18:53:0231MemBackendImpl::MemBackendImpl(net::NetLog* net_log)
32 : max_size_(0), current_size_(0), net_log_(net_log) {}
[email protected]4b3c95dd2011-01-07 23:02:1133
34MemBackendImpl::~MemBackendImpl() {
35 EntryMap::iterator it = entries_.begin();
36 while (it != entries_.end()) {
37 it->second->Doom();
38 it = entries_.begin();
39 }
40 DCHECK(!current_size_);
41}
42
[email protected]ec44a9a2010-06-15 19:31:5143// Static.
[email protected]9eb8cdf2011-03-17 18:53:0244Backend* MemBackendImpl::CreateBackend(int max_bytes, net::NetLog* net_log) {
45 MemBackendImpl* cache = new MemBackendImpl(net_log);
initial.commit586acc5fe2008-07-26 22:42:5246 cache->SetMaxSize(max_bytes);
47 if (cache->Init())
48 return cache;
49
50 delete cache;
51 LOG(ERROR) << "Unable to create cache";
52 return NULL;
53}
54
initial.commit586acc5fe2008-07-26 22:42:5255bool MemBackendImpl::Init() {
56 if (max_size_)
57 return true;
58
[email protected]b4f71a8d2008-09-17 15:32:0359 int64 total_memory = base::SysInfo::AmountOfPhysicalMemory();
[email protected]408d35f52008-08-13 18:30:2260
[email protected]02ee34a2008-09-20 01:16:2361 if (total_memory <= 0) {
initial.commit586acc5fe2008-07-26 22:42:5262 max_size_ = kDefaultCacheSize;
63 return true;
64 }
65
66 // We want to use up to 2% of the computer's memory, with a limit of 50 MB,
67 // reached on systemd with more than 2.5 GB of RAM.
[email protected]408d35f52008-08-13 18:30:2268 total_memory = total_memory * 2 / 100;
69 if (total_memory > kDefaultCacheSize * 5)
initial.commit586acc5fe2008-07-26 22:42:5270 max_size_ = kDefaultCacheSize * 5;
71 else
[email protected]408d35f52008-08-13 18:30:2272 max_size_ = static_cast<int32>(total_memory);
initial.commit586acc5fe2008-07-26 22:42:5273
74 return true;
75}
76
initial.commit586acc5fe2008-07-26 22:42:5277bool MemBackendImpl::SetMaxSize(int max_bytes) {
78 COMPILE_ASSERT(sizeof(max_bytes) == sizeof(max_size_), unsupported_int_model);
79 if (max_bytes < 0)
80 return false;
81
82 // Zero size means use the default.
83 if (!max_bytes)
84 return true;
85
86 max_size_ = max_bytes;
87 return true;
88}
89
[email protected]4b3c95dd2011-01-07 23:02:1190void MemBackendImpl::InternalDoomEntry(MemEntryImpl* entry) {
91 // Only parent entries can be passed into this method.
92 DCHECK(entry->type() == MemEntryImpl::kParentEntry);
93
94 rankings_.Remove(entry);
95 EntryMap::iterator it = entries_.find(entry->GetKey());
96 if (it != entries_.end())
97 entries_.erase(it);
98 else
99 NOTREACHED();
100
101 entry->InternalDoom();
102}
103
104void MemBackendImpl::UpdateRank(MemEntryImpl* node) {
105 rankings_.UpdateRank(node);
106}
107
108void MemBackendImpl::ModifyStorageSize(int32 old_size, int32 new_size) {
109 if (old_size >= new_size)
110 SubstractStorageSize(old_size - new_size);
111 else
112 AddStorageSize(new_size - old_size);
113}
114
115int MemBackendImpl::MaxFileSize() const {
116 return max_size_ / 8;
117}
118
119void MemBackendImpl::InsertIntoRankingList(MemEntryImpl* entry) {
120 rankings_.Insert(entry);
121}
122
123void MemBackendImpl::RemoveFromRankingList(MemEntryImpl* entry) {
124 rankings_.Remove(entry);
125}
126
initial.commit586acc5fe2008-07-26 22:42:52127int32 MemBackendImpl::GetEntryCount() const {
128 return static_cast<int32>(entries_.size());
129}
130
[email protected]4b3c95dd2011-01-07 23:02:11131int MemBackendImpl::OpenEntry(const std::string& key, Entry** entry,
132 CompletionCallback* callback) {
133 if (OpenEntry(key, entry))
134 return net::OK;
135
136 return net::ERR_FAILED;
137}
138
139int MemBackendImpl::CreateEntry(const std::string& key, Entry** entry,
140 CompletionCallback* callback) {
141 if (CreateEntry(key, entry))
142 return net::OK;
143
144 return net::ERR_FAILED;
145}
146
147int MemBackendImpl::DoomEntry(const std::string& key,
148 CompletionCallback* callback) {
149 if (DoomEntry(key))
150 return net::OK;
151
152 return net::ERR_FAILED;
153}
154
155int MemBackendImpl::DoomAllEntries(CompletionCallback* callback) {
156 if (DoomAllEntries())
157 return net::OK;
158
159 return net::ERR_FAILED;
160}
161
162int MemBackendImpl::DoomEntriesBetween(const base::Time initial_time,
163 const base::Time end_time,
164 CompletionCallback* callback) {
165 if (DoomEntriesBetween(initial_time, end_time))
166 return net::OK;
167
168 return net::ERR_FAILED;
169}
170
171int MemBackendImpl::DoomEntriesSince(const base::Time initial_time,
172 CompletionCallback* callback) {
173 if (DoomEntriesSince(initial_time))
174 return net::OK;
175
176 return net::ERR_FAILED;
177}
178
179int MemBackendImpl::OpenNextEntry(void** iter, Entry** next_entry,
180 CompletionCallback* callback) {
181 if (OpenNextEntry(iter, next_entry))
182 return net::OK;
183
184 return net::ERR_FAILED;
185}
186
187void MemBackendImpl::EndEnumeration(void** iter) {
188 *iter = NULL;
189}
190
[email protected]70435962011-08-02 20:13:28191void MemBackendImpl::OnExternalCacheHit(const std::string& key) {
192 EntryMap::iterator it = entries_.find(key);
193 if (it != entries_.end()) {
194 UpdateRank(it->second);
195 }
196}
197
initial.commit586acc5fe2008-07-26 22:42:52198bool MemBackendImpl::OpenEntry(const std::string& key, Entry** entry) {
199 EntryMap::iterator it = entries_.find(key);
200 if (it == entries_.end())
201 return false;
202
203 it->second->Open();
204
205 *entry = it->second;
206 return true;
207}
208
209bool MemBackendImpl::CreateEntry(const std::string& key, Entry** entry) {
210 EntryMap::iterator it = entries_.find(key);
211 if (it != entries_.end())
212 return false;
213
214 MemEntryImpl* cache_entry = new MemEntryImpl(this);
[email protected]9eb8cdf2011-03-17 18:53:02215 if (!cache_entry->CreateEntry(key, net_log_)) {
initial.commit586acc5fe2008-07-26 22:42:52216 delete entry;
217 return false;
218 }
219
220 rankings_.Insert(cache_entry);
221 entries_[key] = cache_entry;
222
223 *entry = cache_entry;
224 return true;
225}
226
227bool MemBackendImpl::DoomEntry(const std::string& key) {
228 Entry* entry;
229 if (!OpenEntry(key, &entry))
230 return false;
231
232 entry->Doom();
233 entry->Close();
234 return true;
235}
236
initial.commit586acc5fe2008-07-26 22:42:52237bool MemBackendImpl::DoomAllEntries() {
238 TrimCache(true);
239 return true;
240}
241
242bool MemBackendImpl::DoomEntriesBetween(const Time initial_time,
243 const Time end_time) {
244 if (end_time.is_null())
245 return DoomEntriesSince(initial_time);
246
247 DCHECK(end_time >= initial_time);
248
249 MemEntryImpl* next = rankings_.GetNext(NULL);
250
251 // rankings_ is ordered by last used, this will descend through the cache
252 // and start dooming items before the end_time, and will stop once it reaches
253 // an item used before the initial time.
254 while (next) {
255 MemEntryImpl* node = next;
256 next = rankings_.GetNext(next);
257
258 if (node->GetLastUsed() < initial_time)
259 break;
260
[email protected]658c1732009-06-15 20:41:30261 if (node->GetLastUsed() < end_time)
initial.commit586acc5fe2008-07-26 22:42:52262 node->Doom();
initial.commit586acc5fe2008-07-26 22:42:52263 }
264
265 return true;
266}
267
initial.commit586acc5fe2008-07-26 22:42:52268bool MemBackendImpl::DoomEntriesSince(const Time initial_time) {
269 for (;;) {
[email protected]658c1732009-06-15 20:41:30270 // Get the entry in the front.
271 Entry* entry = rankings_.GetNext(NULL);
initial.commit586acc5fe2008-07-26 22:42:52272
[email protected]658c1732009-06-15 20:41:30273 // Break the loop when there are no more entries or the entry is too old.
274 if (!entry || entry->GetLastUsed() < initial_time)
initial.commit586acc5fe2008-07-26 22:42:52275 return true;
initial.commit586acc5fe2008-07-26 22:42:52276 entry->Doom();
initial.commit586acc5fe2008-07-26 22:42:52277 }
278}
279
280bool MemBackendImpl::OpenNextEntry(void** iter, Entry** next_entry) {
281 MemEntryImpl* current = reinterpret_cast<MemEntryImpl*>(*iter);
282 MemEntryImpl* node = rankings_.GetNext(current);
[email protected]658c1732009-06-15 20:41:30283 // We should never return a child entry so iterate until we hit a parent
284 // entry.
285 while (node && node->type() != MemEntryImpl::kParentEntry) {
286 node = rankings_.GetNext(node);
287 }
initial.commit586acc5fe2008-07-26 22:42:52288 *next_entry = node;
289 *iter = node;
290
291 if (node)
292 node->Open();
293
294 return NULL != node;
295}
296
initial.commit586acc5fe2008-07-26 22:42:52297void MemBackendImpl::TrimCache(bool empty) {
298 MemEntryImpl* next = rankings_.GetPrev(NULL);
299
300 DCHECK(next);
301
302 int target_size = empty ? 0 : LowWaterAdjust(max_size_);
303 while (current_size_ > target_size && next) {
304 MemEntryImpl* node = next;
305 next = rankings_.GetPrev(next);
306 if (!node->InUse() || empty) {
307 node->Doom();
308 }
309 }
310
311 return;
312}
313
314void MemBackendImpl::AddStorageSize(int32 bytes) {
315 current_size_ += bytes;
[email protected]c34e9a7a2011-05-11 12:06:57316 DCHECK_GE(current_size_, 0);
initial.commit586acc5fe2008-07-26 22:42:52317
318 if (current_size_ > max_size_)
319 TrimCache(false);
320}
321
322void MemBackendImpl::SubstractStorageSize(int32 bytes) {
323 current_size_ -= bytes;
[email protected]c34e9a7a2011-05-11 12:06:57324 DCHECK_GE(current_size_, 0);
initial.commit586acc5fe2008-07-26 22:42:52325}
326
initial.commit586acc5fe2008-07-26 22:42:52327} // namespace disk_cache