Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(401)

Side by Side Diff: net/disk_cache/entry_impl.cc

Issue 12880: Disk cache: Add support for an extra data stream for each cache entry.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/disk_cache/entry_impl.h" 5 #include "net/disk_cache/entry_impl.h"
6 6
7 #include "base/histogram.h" 7 #include "base/histogram.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "net/base/net_errors.h" 10 #include "net/base/net_errors.h"
11 #include "net/disk_cache/backend_impl.h" 11 #include "net/disk_cache/backend_impl.h"
12 #include "net/disk_cache/cache_util.h" 12 #include "net/disk_cache/cache_util.h"
13 13
14 using base::Time; 14 using base::Time;
15 using base::TimeDelta; 15 using base::TimeDelta;
16 16
17 namespace { 17 namespace {
18 18
19 // Index for the file used to store the key, if any (files_[kKeyFileIndex]).
20 const int kKeyFileIndex = 3;
21
19 // This class implements FileIOCallback to buffer the callback from a file IO 22 // This class implements FileIOCallback to buffer the callback from a file IO
20 // operation from the actual net class. 23 // operation from the actual net class.
21 class SyncCallback: public disk_cache::FileIOCallback { 24 class SyncCallback: public disk_cache::FileIOCallback {
22 public: 25 public:
23 SyncCallback(disk_cache::EntryImpl* entry, 26 SyncCallback(disk_cache::EntryImpl* entry,
24 net::CompletionCallback* callback ) 27 net::CompletionCallback* callback )
25 : entry_(entry), callback_(callback) { 28 : entry_(entry), callback_(callback) {
26 entry->AddRef(); 29 entry->AddRef();
27 entry->IncrementIoCount(); 30 entry->IncrementIoCount();
28 } 31 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 68
66 } // namespace 69 } // namespace
67 70
68 namespace disk_cache { 71 namespace disk_cache {
69 72
70 EntryImpl::EntryImpl(BackendImpl* backend, Addr address) 73 EntryImpl::EntryImpl(BackendImpl* backend, Addr address)
71 : entry_(NULL, Addr(0)), node_(NULL, Addr(0)) { 74 : entry_(NULL, Addr(0)), node_(NULL, Addr(0)) {
72 entry_.LazyInit(backend->File(address), address); 75 entry_.LazyInit(backend->File(address), address);
73 doomed_ = false; 76 doomed_ = false;
74 backend_ = backend; 77 backend_ = backend;
75 unreported_size_[0] = unreported_size_[1] = 0; 78 for (int i = 0; i < NUM_STREAMS; i++)
79 unreported_size_[i] = 0;
76 } 80 }
77 81
78 // When an entry is deleted from the cache, we clean up all the data associated 82 // When an entry is deleted from the cache, we clean up all the data associated
79 // with it for two reasons: to simplify the reuse of the block (we know that any 83 // with it for two reasons: to simplify the reuse of the block (we know that any
80 // unused block is filled with zeros), and to simplify the handling of write / 84 // unused block is filled with zeros), and to simplify the handling of write /
81 // read partial information from an entry (don't have to worry about returning 85 // read partial information from an entry (don't have to worry about returning
82 // data related to a previous cache entry because the range was not fully 86 // data related to a previous cache entry because the range was not fully
83 // written before). 87 // written before).
84 EntryImpl::~EntryImpl() { 88 EntryImpl::~EntryImpl() {
85 if (doomed_) { 89 if (doomed_) {
86 UMA_HISTOGRAM_COUNTS(L"DiskCache.DeleteHeader", GetDataSize(0)); 90 UMA_HISTOGRAM_COUNTS(L"DiskCache.DeleteHeader", GetDataSize(0));
87 UMA_HISTOGRAM_COUNTS(L"DiskCache.DeleteData", GetDataSize(1)); 91 UMA_HISTOGRAM_COUNTS(L"DiskCache.DeleteData", GetDataSize(1));
88 for (int index = 0; index < kKeyFileIndex; index++) { 92 for (int index = 0; index < NUM_STREAMS; index++) {
89 Addr address(entry_.Data()->data_addr[index]); 93 Addr address(entry_.Data()->data_addr[index]);
90 if (address.is_initialized()) { 94 if (address.is_initialized()) {
91 DeleteData(address, index); 95 DeleteData(address, index);
92 backend_->ModifyStorageSize(entry_.Data()->data_size[index] - 96 backend_->ModifyStorageSize(entry_.Data()->data_size[index] -
93 unreported_size_[index], 0); 97 unreported_size_[index], 0);
94 } 98 }
95 } 99 }
96 Addr address(entry_.Data()->long_key); 100 Addr address(entry_.Data()->long_key);
97 DeleteData(address, kKeyFileIndex); 101 DeleteData(address, kKeyFileIndex);
98 backend_->ModifyStorageSize(entry_.Data()->key_len, 0); 102 backend_->ModifyStorageSize(entry_.Data()->key_len, 0);
99 103
100 memset(node_.buffer(), 0, node_.size()); 104 memset(node_.buffer(), 0, node_.size());
101 memset(entry_.buffer(), 0, entry_.size()); 105 memset(entry_.buffer(), 0, entry_.size());
102 node_.Store(); 106 node_.Store();
103 entry_.Store(); 107 entry_.Store();
104 108
105 backend_->DeleteBlock(node_.address(), false); 109 backend_->DeleteBlock(node_.address(), false);
106 backend_->DeleteBlock(entry_.address(), false); 110 backend_->DeleteBlock(entry_.address(), false);
107 } else { 111 } else {
108 bool ret = true; 112 bool ret = true;
109 for (int index = 0; index < kKeyFileIndex; index++) { 113 for (int index = 0; index < NUM_STREAMS; index++) {
110 if (user_buffers_[index].get()) { 114 if (user_buffers_[index].get()) {
111 if (!(ret = Flush(index, entry_.Data()->data_size[index], false))) 115 if (!(ret = Flush(index, entry_.Data()->data_size[index], false)))
112 LOG(ERROR) << "Failed to save user data"; 116 LOG(ERROR) << "Failed to save user data";
113 } else if (unreported_size_[index]) { 117 } else if (unreported_size_[index]) {
114 backend_->ModifyStorageSize( 118 backend_->ModifyStorageSize(
115 entry_.Data()->data_size[index] - unreported_size_[index], 119 entry_.Data()->data_size[index] - unreported_size_[index],
116 entry_.Data()->data_size[index]); 120 entry_.Data()->data_size[index]);
117 } 121 }
118 } 122 }
119 if (node_.HasData() && this == node_.Data()->pointer) { 123 if (node_.HasData() && this == node_.Data()->pointer) {
(...skipping 27 matching lines...) Expand all
147 151
148 void EntryImpl::Close() { 152 void EntryImpl::Close() {
149 Release(); 153 Release();
150 } 154 }
151 155
152 std::string EntryImpl::GetKey() const { 156 std::string EntryImpl::GetKey() const {
153 CacheEntryBlock* entry = const_cast<CacheEntryBlock*>(&entry_); 157 CacheEntryBlock* entry = const_cast<CacheEntryBlock*>(&entry_);
154 if (entry->Data()->key_len > kMaxInternalKeyLength) { 158 if (entry->Data()->key_len > kMaxInternalKeyLength) {
155 Addr address(entry->Data()->long_key); 159 Addr address(entry->Data()->long_key);
156 DCHECK(address.is_initialized()); 160 DCHECK(address.is_initialized());
161 COMPILE_ASSERT(NUM_STREAMS == kKeyFileIndex, invalid_key_index);
157 File* file = const_cast<EntryImpl*>(this)->GetBackingFile(address, 162 File* file = const_cast<EntryImpl*>(this)->GetBackingFile(address,
158 kKeyFileIndex); 163 kKeyFileIndex);
159 164
160 size_t offset = 0; 165 size_t offset = 0;
161 if (address.is_block_file()) 166 if (address.is_block_file())
162 offset = address.start_block() * address.BlockSize() + kBlockHeaderSize; 167 offset = address.start_block() * address.BlockSize() + kBlockHeaderSize;
163 168
164 std::string key; 169 std::string key;
165 if (!file || !file->Read(WriteInto(&key, entry->Data()->key_len + 1), 170 if (!file || !file->Read(WriteInto(&key, entry->Data()->key_len + 1),
166 entry->Data()->key_len + 1, offset)) 171 entry->Data()->key_len + 1, offset))
167 key.clear(); 172 key.clear();
168 return key; 173 return key;
169 } else { 174 } else {
170 return std::string(entry->Data()->key); 175 return std::string(entry->Data()->key);
171 } 176 }
172 } 177 }
173 178
174 Time EntryImpl::GetLastUsed() const { 179 Time EntryImpl::GetLastUsed() const {
175 CacheRankingsBlock* node = const_cast<CacheRankingsBlock*>(&node_); 180 CacheRankingsBlock* node = const_cast<CacheRankingsBlock*>(&node_);
176 return Time::FromInternalValue(node->Data()->last_used); 181 return Time::FromInternalValue(node->Data()->last_used);
177 } 182 }
178 183
179 Time EntryImpl::GetLastModified() const { 184 Time EntryImpl::GetLastModified() const {
180 CacheRankingsBlock* node = const_cast<CacheRankingsBlock*>(&node_); 185 CacheRankingsBlock* node = const_cast<CacheRankingsBlock*>(&node_);
181 return Time::FromInternalValue(node->Data()->last_modified); 186 return Time::FromInternalValue(node->Data()->last_modified);
182 } 187 }
183 188
184 int32 EntryImpl::GetDataSize(int index) const { 189 int32 EntryImpl::GetDataSize(int index) const {
185 if (index < 0 || index > 1) 190 if (index < 0 || index >= NUM_STREAMS)
186 return 0; 191 return 0;
187 192
188 CacheEntryBlock* entry = const_cast<CacheEntryBlock*>(&entry_); 193 CacheEntryBlock* entry = const_cast<CacheEntryBlock*>(&entry_);
189 return entry->Data()->data_size[index]; 194 return entry->Data()->data_size[index];
190 } 195 }
191 196
192 int EntryImpl::ReadData(int index, int offset, char* buf, int buf_len, 197 int EntryImpl::ReadData(int index, int offset, char* buf, int buf_len,
193 net::CompletionCallback* completion_callback) { 198 net::CompletionCallback* completion_callback) {
194 DCHECK(node_.Data()->dirty); 199 DCHECK(node_.Data()->dirty);
195 if (index < 0 || index > 1) 200 if (index < 0 || index >= NUM_STREAMS)
196 return net::ERR_INVALID_ARGUMENT; 201 return net::ERR_INVALID_ARGUMENT;
197 202
198 int entry_size = entry_.Data()->data_size[index]; 203 int entry_size = entry_.Data()->data_size[index];
199 if (offset >= entry_size || offset < 0 || !buf_len) 204 if (offset >= entry_size || offset < 0 || !buf_len)
200 return 0; 205 return 0;
201 206
202 if (buf_len < 0) 207 if (buf_len < 0)
203 return net::ERR_INVALID_ARGUMENT; 208 return net::ERR_INVALID_ARGUMENT;
204 209
205 Time start = Time::Now(); 210 Time start = Time::Now();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 io_callback->Discard(); 256 io_callback->Discard();
252 257
253 stats.AddTime(Time::Now() - start); 258 stats.AddTime(Time::Now() - start);
254 return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING; 259 return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING;
255 } 260 }
256 261
257 int EntryImpl::WriteData(int index, int offset, const char* buf, int buf_len, 262 int EntryImpl::WriteData(int index, int offset, const char* buf, int buf_len,
258 net::CompletionCallback* completion_callback, 263 net::CompletionCallback* completion_callback,
259 bool truncate) { 264 bool truncate) {
260 DCHECK(node_.Data()->dirty); 265 DCHECK(node_.Data()->dirty);
261 if (index < 0 || index > 1) 266 if (index < 0 || index >= NUM_STREAMS)
262 return net::ERR_INVALID_ARGUMENT; 267 return net::ERR_INVALID_ARGUMENT;
263 268
264 if (offset < 0 || buf_len < 0) 269 if (offset < 0 || buf_len < 0)
265 return net::ERR_INVALID_ARGUMENT; 270 return net::ERR_INVALID_ARGUMENT;
266 271
267 int max_file_size = backend_->MaxFileSize(); 272 int max_file_size = backend_->MaxFileSize();
268 273
269 // offset of buf_len could be negative numbers. 274 // offset of buf_len could be negative numbers.
270 if (offset > max_file_size || buf_len > max_file_size || 275 if (offset > max_file_size || buf_len > max_file_size ||
271 offset + buf_len > max_file_size) { 276 offset + buf_len > max_file_size) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 memset(entry_store, 0, sizeof(EntryStore) * entry_.address().num_blocks()); 370 memset(entry_store, 0, sizeof(EntryStore) * entry_.address().num_blocks());
366 memset(node, 0, sizeof(RankingsNode)); 371 memset(node, 0, sizeof(RankingsNode));
367 if (!node_.LazyInit(backend_->File(node_address), node_address)) 372 if (!node_.LazyInit(backend_->File(node_address), node_address))
368 return false; 373 return false;
369 374
370 entry_store->rankings_node = node_address.value(); 375 entry_store->rankings_node = node_address.value();
371 node->contents = entry_.address().value(); 376 node->contents = entry_.address().value();
372 node->pointer = this; 377 node->pointer = this;
373 378
374 entry_store->hash = hash; 379 entry_store->hash = hash;
380 entry_store->creation_time = Time::Now().ToInternalValue();
375 entry_store->key_len = static_cast<int32>(key.size()); 381 entry_store->key_len = static_cast<int32>(key.size());
376 if (entry_store->key_len > kMaxInternalKeyLength) { 382 if (entry_store->key_len > kMaxInternalKeyLength) {
377 Addr address(0); 383 Addr address(0);
378 if (!CreateBlock(entry_store->key_len + 1, &address)) 384 if (!CreateBlock(entry_store->key_len + 1, &address))
379 return false; 385 return false;
380 386
381 entry_store->long_key = address.value(); 387 entry_store->long_key = address.value();
382 File* file = GetBackingFile(address, kKeyFileIndex); 388 File* file = GetBackingFile(address, kKeyFileIndex);
383 389
384 size_t offset = 0; 390 size_t offset = 0;
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 } 506 }
501 507
502 void EntryImpl::SetTimes(base::Time last_used, base::Time last_modified) { 508 void EntryImpl::SetTimes(base::Time last_used, base::Time last_modified) {
503 node_.Data()->last_used = last_used.ToInternalValue(); 509 node_.Data()->last_used = last_used.ToInternalValue();
504 node_.Data()->last_modified = last_modified.ToInternalValue(); 510 node_.Data()->last_modified = last_modified.ToInternalValue();
505 node_.set_modified(); 511 node_.set_modified();
506 } 512 }
507 513
508 bool EntryImpl::CreateDataBlock(int index, int size) { 514 bool EntryImpl::CreateDataBlock(int index, int size) {
509 Addr address(entry_.Data()->data_addr[index]); 515 Addr address(entry_.Data()->data_addr[index]);
510 DCHECK(0 == index || 1 == index); 516 DCHECK(index >= 0 && index < NUM_STREAMS);
511 517
512 if (!CreateBlock(size, &address)) 518 if (!CreateBlock(size, &address))
513 return false; 519 return false;
514 520
515 entry_.Data()->data_addr[index] = address.value(); 521 entry_.Data()->data_addr[index] = address.value();
516 entry_.Store(); 522 entry_.Store();
517 return true; 523 return true;
518 } 524 }
519 525
520 bool EntryImpl::CreateBlock(int size, Addr* address) { 526 bool EntryImpl::CreateBlock(int size, Addr* address) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 File* EntryImpl::GetBackingFile(Addr address, int index) { 576 File* EntryImpl::GetBackingFile(Addr address, int index) {
571 File* file; 577 File* file;
572 if (address.is_separate_file()) 578 if (address.is_separate_file())
573 file = GetExternalFile(address, index); 579 file = GetExternalFile(address, index);
574 else 580 else
575 file = backend_->File(address); 581 file = backend_->File(address);
576 return file; 582 return file;
577 } 583 }
578 584
579 File* EntryImpl::GetExternalFile(Addr address, int index) { 585 File* EntryImpl::GetExternalFile(Addr address, int index) {
580 DCHECK(index >= 0 && index <= 2); 586 DCHECK(index >= 0 && index <= kKeyFileIndex);
581 if (!files_[index].get()) { 587 if (!files_[index].get()) {
582 // For a key file, use mixed mode IO. 588 // For a key file, use mixed mode IO.
583 scoped_refptr<File> file(new File(2 == index)); 589 scoped_refptr<File> file(new File(kKeyFileIndex == index));
584 if (file->Init(backend_->GetFileName(address))) 590 if (file->Init(backend_->GetFileName(address)))
585 files_[index].swap(file); 591 files_[index].swap(file);
586 } 592 }
587 return files_[index].get(); 593 return files_[index].get();
588 } 594 }
589 595
590 bool EntryImpl::PrepareTarget(int index, int offset, int buf_len, 596 bool EntryImpl::PrepareTarget(int index, int offset, int buf_len,
591 bool truncate) { 597 bool truncate) {
592 Addr address(entry_.Data()->data_addr[index]); 598 Addr address(entry_.Data()->data_addr[index]);
593 if (address.is_initialized() || user_buffers_[index].get()) 599 if (address.is_initialized() || user_buffers_[index].get())
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
766 entry_.address().value(), node_.address().value()); 772 entry_.address().value(), node_.address().value());
767 773
768 Trace(" data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0], 774 Trace(" data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0],
769 entry_.Data()->data_addr[1], entry_.Data()->long_key); 775 entry_.Data()->data_addr[1], entry_.Data()->long_key);
770 776
771 Trace(" doomed: %d 0x%p 0x%x", doomed_, pointer, dirty); 777 Trace(" doomed: %d 0x%p 0x%x", doomed_, pointer, dirty);
772 } 778 }
773 779
774 } // namespace disk_cache 780 } // namespace disk_cache
775 781
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698