OLD | NEW |
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/io_buffer.h" | 10 #include "net/base/io_buffer.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 | 71 |
72 } // namespace | 72 } // namespace |
73 | 73 |
74 namespace disk_cache { | 74 namespace disk_cache { |
75 | 75 |
76 EntryImpl::EntryImpl(BackendImpl* backend, Addr address) | 76 EntryImpl::EntryImpl(BackendImpl* backend, Addr address) |
77 : entry_(NULL, Addr(0)), node_(NULL, Addr(0)) { | 77 : entry_(NULL, Addr(0)), node_(NULL, Addr(0)) { |
78 entry_.LazyInit(backend->File(address), address); | 78 entry_.LazyInit(backend->File(address), address); |
79 doomed_ = false; | 79 doomed_ = false; |
80 backend_ = backend; | 80 backend_ = backend; |
81 for (int i = 0; i < NUM_STREAMS; i++) | 81 for (int i = 0; i < NUM_STREAMS; i++) { |
82 unreported_size_[i] = 0; | 82 unreported_size_[i] = 0; |
| 83 need_file_[i] = false; |
| 84 } |
83 } | 85 } |
84 | 86 |
85 // When an entry is deleted from the cache, we clean up all the data associated | 87 // When an entry is deleted from the cache, we clean up all the data associated |
86 // with it for two reasons: to simplify the reuse of the block (we know that any | 88 // with it for two reasons: to simplify the reuse of the block (we know that any |
87 // unused block is filled with zeros), and to simplify the handling of write / | 89 // unused block is filled with zeros), and to simplify the handling of write / |
88 // read partial information from an entry (don't have to worry about returning | 90 // read partial information from an entry (don't have to worry about returning |
89 // data related to a previous cache entry because the range was not fully | 91 // data related to a previous cache entry because the range was not fully |
90 // written before). | 92 // written before). |
91 EntryImpl::~EntryImpl() { | 93 EntryImpl::~EntryImpl() { |
92 if (doomed_) { | 94 if (doomed_) { |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 } else { | 313 } else { |
312 // Nothing to truncate. | 314 // Nothing to truncate. |
313 truncate = false; | 315 truncate = false; |
314 } | 316 } |
315 } | 317 } |
316 | 318 |
317 UpdateRank(true); | 319 UpdateRank(true); |
318 | 320 |
319 backend_->OnEvent(Stats::WRITE_DATA); | 321 backend_->OnEvent(Stats::WRITE_DATA); |
320 | 322 |
321 if (user_buffers_[index].get()) { | 323 // If we have prepared the cache as an external file, we should never use |
| 324 // user_buffers_ and always write to file directly. |
| 325 if (!need_file_[index] && user_buffers_[index].get()) { |
322 // Complete the operation locally. | 326 // Complete the operation locally. |
323 if (!buf_len) | 327 if (!buf_len) |
324 return 0; | 328 return 0; |
325 | 329 |
326 DCHECK(kMaxBlockSize >= offset + buf_len); | 330 DCHECK(kMaxBlockSize >= offset + buf_len); |
327 memcpy(user_buffers_[index].get() + offset, buf->data(), buf_len); | 331 memcpy(user_buffers_[index].get() + offset, buf->data(), buf_len); |
328 stats.AddTime(Time::Now() - start); | 332 stats.AddTime(Time::Now() - start); |
329 return buf_len; | 333 return buf_len; |
330 } | 334 } |
331 | 335 |
(...skipping 26 matching lines...) Expand all Loading... |
358 return net::ERR_FAILED; | 362 return net::ERR_FAILED; |
359 } | 363 } |
360 | 364 |
361 if (io_callback && completed) | 365 if (io_callback && completed) |
362 io_callback->Discard(); | 366 io_callback->Discard(); |
363 | 367 |
364 stats.AddTime(Time::Now() - start); | 368 stats.AddTime(Time::Now() - start); |
365 return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING; | 369 return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING; |
366 } | 370 } |
367 | 371 |
| 372 base::PlatformFile EntryImpl::UseExternalFile(int index) { |
| 373 DCHECK(index >= 0 && index < NUM_STREAMS); |
| 374 |
| 375 Addr address(entry_.Data()->data_addr[index]); |
| 376 |
| 377 // We will not prepare the cache file since the entry is already initialized, |
| 378 // just return the platform file backing the cache. |
| 379 if (address.is_initialized()) |
| 380 return GetPlatformFile(index); |
| 381 |
| 382 if (!backend_->CreateExternalFile(&address)) |
| 383 return base::kInvalidPlatformFileValue; |
| 384 |
| 385 entry_.Data()->data_addr[index] = address.value(); |
| 386 entry_.Store(); |
| 387 |
| 388 // Set the flag for this stream so we never use user_buffer_. |
| 389 // TODO(hclam): do we need to save this information to EntryStore? |
| 390 need_file_[index] = true; |
| 391 |
| 392 return GetPlatformFile(index); |
| 393 } |
| 394 |
| 395 base::PlatformFile EntryImpl::GetPlatformFile(int index) { |
| 396 DCHECK(index >= 0 && index < NUM_STREAMS); |
| 397 |
| 398 Addr address(entry_.Data()->data_addr[index]); |
| 399 if (!address.is_initialized() || !address.is_separate_file()) |
| 400 return base::kInvalidPlatformFileValue; |
| 401 |
| 402 File* cache_file = GetExternalFile(address, index); |
| 403 if (!cache_file) |
| 404 return base::kInvalidPlatformFileValue; |
| 405 |
| 406 return cache_file->platform_file(); |
| 407 } |
| 408 |
368 uint32 EntryImpl::GetHash() { | 409 uint32 EntryImpl::GetHash() { |
369 return entry_.Data()->hash; | 410 return entry_.Data()->hash; |
370 } | 411 } |
371 | 412 |
372 bool EntryImpl::CreateEntry(Addr node_address, const std::string& key, | 413 bool EntryImpl::CreateEntry(Addr node_address, const std::string& key, |
373 uint32 hash) { | 414 uint32 hash) { |
374 Trace("Create entry In"); | 415 Trace("Create entry In"); |
375 EntryStore* entry_store = entry_.Data(); | 416 EntryStore* entry_store = entry_.Data(); |
376 RankingsNode* node = node_.Data(); | 417 RankingsNode* node = node_.Data(); |
377 memset(entry_store, 0, sizeof(EntryStore) * entry_.address().num_blocks()); | 418 memset(entry_store, 0, sizeof(EntryStore) * entry_.address().num_blocks()); |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 scoped_refptr<File> file(new File(kKeyFileIndex == index)); | 637 scoped_refptr<File> file(new File(kKeyFileIndex == index)); |
597 if (file->Init(backend_->GetFileName(address))) | 638 if (file->Init(backend_->GetFileName(address))) |
598 files_[index].swap(file); | 639 files_[index].swap(file); |
599 } | 640 } |
600 return files_[index].get(); | 641 return files_[index].get(); |
601 } | 642 } |
602 | 643 |
603 bool EntryImpl::PrepareTarget(int index, int offset, int buf_len, | 644 bool EntryImpl::PrepareTarget(int index, int offset, int buf_len, |
604 bool truncate) { | 645 bool truncate) { |
605 Addr address(entry_.Data()->data_addr[index]); | 646 Addr address(entry_.Data()->data_addr[index]); |
| 647 |
| 648 // If we are instructed to use an external file, we should never buffer when |
| 649 // writing. We are done with preparation of the target automatically, since |
| 650 // we have already created the external file for writing. |
| 651 if (need_file_[index]) { |
| 652 // Make sure the stream is initialized and is kept in an external file. |
| 653 DCHECK(address.is_initialized() && address.is_separate_file()); |
| 654 return true; |
| 655 } |
| 656 |
606 if (address.is_initialized() || user_buffers_[index].get()) | 657 if (address.is_initialized() || user_buffers_[index].get()) |
607 return GrowUserBuffer(index, offset, buf_len, truncate); | 658 return GrowUserBuffer(index, offset, buf_len, truncate); |
608 | 659 |
609 if (offset + buf_len > kMaxBlockSize) | 660 if (offset + buf_len > kMaxBlockSize) |
610 return CreateDataBlock(index, offset + buf_len); | 661 return CreateDataBlock(index, offset + buf_len); |
611 | 662 |
612 user_buffers_[index].reset(new char[kMaxBlockSize]); | 663 user_buffers_[index].reset(new char[kMaxBlockSize]); |
613 | 664 |
614 // Overwrite the parts of the buffer that are not going to be written | 665 // Overwrite the parts of the buffer that are not going to be written |
615 // by the current operation (and yes, let's assume that nothing is going | 666 // by the current operation (and yes, let's assume that nothing is going |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 Trace("%s 0x%p 0x%x 0x%x", msg, reinterpret_cast<void*>(this), | 829 Trace("%s 0x%p 0x%x 0x%x", msg, reinterpret_cast<void*>(this), |
779 entry_.address().value(), node_.address().value()); | 830 entry_.address().value(), node_.address().value()); |
780 | 831 |
781 Trace(" data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0], | 832 Trace(" data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0], |
782 entry_.Data()->data_addr[1], entry_.Data()->long_key); | 833 entry_.Data()->data_addr[1], entry_.Data()->long_key); |
783 | 834 |
784 Trace(" doomed: %d 0x%p 0x%x", doomed_, pointer, dirty); | 835 Trace(" doomed: %d 0x%p 0x%x", doomed_, pointer, dirty); |
785 } | 836 } |
786 | 837 |
787 } // namespace disk_cache | 838 } // namespace disk_cache |
OLD | NEW |