| 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 | 74 |
| 75 namespace disk_cache { | 75 namespace disk_cache { |
| 76 | 76 |
| 77 EntryImpl::EntryImpl(BackendImpl* backend, Addr address) | 77 EntryImpl::EntryImpl(BackendImpl* backend, Addr address) |
| 78 : entry_(NULL, Addr(0)), node_(NULL, Addr(0)) { | 78 : entry_(NULL, Addr(0)), node_(NULL, Addr(0)) { |
| 79 entry_.LazyInit(backend->File(address), address); | 79 entry_.LazyInit(backend->File(address), address); |
| 80 doomed_ = false; | 80 doomed_ = false; |
| 81 backend_ = backend; | 81 backend_ = backend; |
| 82 for (int i = 0; i < NUM_STREAMS; i++) { | 82 for (int i = 0; i < NUM_STREAMS; i++) { |
| 83 unreported_size_[i] = 0; | 83 unreported_size_[i] = 0; |
| 84 need_file_[i] = false; | |
| 85 } | 84 } |
| 86 } | 85 } |
| 87 | 86 |
| 88 // 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 |
| 89 // 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 |
| 90 // 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 / |
| 91 // 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 |
| 92 // 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 |
| 93 // written before). | 92 // written before). |
| 94 EntryImpl::~EntryImpl() { | 93 EntryImpl::~EntryImpl() { |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 } else { | 295 } else { |
| 297 // Nothing to truncate. | 296 // Nothing to truncate. |
| 298 truncate = false; | 297 truncate = false; |
| 299 } | 298 } |
| 300 } | 299 } |
| 301 | 300 |
| 302 UpdateRank(true); | 301 UpdateRank(true); |
| 303 | 302 |
| 304 backend_->OnEvent(Stats::WRITE_DATA); | 303 backend_->OnEvent(Stats::WRITE_DATA); |
| 305 | 304 |
| 306 // If we have prepared the cache as an external file, we should never use | 305 if (user_buffers_[index].get()) { |
| 307 // user_buffers_ and always write to file directly. | |
| 308 if (!need_file_[index] && user_buffers_[index].get()) { | |
| 309 // Complete the operation locally. | 306 // Complete the operation locally. |
| 310 if (!buf_len) | 307 if (!buf_len) |
| 311 return 0; | 308 return 0; |
| 312 | 309 |
| 313 DCHECK(kMaxBlockSize >= offset + buf_len); | 310 DCHECK(kMaxBlockSize >= offset + buf_len); |
| 314 memcpy(user_buffers_[index].get() + offset, buf->data(), buf_len); | 311 memcpy(user_buffers_[index].get() + offset, buf->data(), buf_len); |
| 315 if (backend_->cache_type() == net::DISK_CACHE) | 312 if (backend_->cache_type() == net::DISK_CACHE) |
| 316 stats.AddTime(Time::Now() - start); | 313 stats.AddTime(Time::Now() - start); |
| 317 return buf_len; | 314 return buf_len; |
| 318 } | 315 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 347 } | 344 } |
| 348 | 345 |
| 349 if (io_callback && completed) | 346 if (io_callback && completed) |
| 350 io_callback->Discard(); | 347 io_callback->Discard(); |
| 351 | 348 |
| 352 if (backend_->cache_type() == net::DISK_CACHE) | 349 if (backend_->cache_type() == net::DISK_CACHE) |
| 353 stats.AddTime(Time::Now() - start); | 350 stats.AddTime(Time::Now() - start); |
| 354 return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING; | 351 return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING; |
| 355 } | 352 } |
| 356 | 353 |
| 357 base::PlatformFile EntryImpl::UseExternalFile(int index) { | |
| 358 DCHECK(index >= 0 && index < NUM_STREAMS); | |
| 359 | |
| 360 Addr address(entry_.Data()->data_addr[index]); | |
| 361 | |
| 362 // We will not prepare the cache file since the entry is already initialized, | |
| 363 // just return the platform file backing the cache. | |
| 364 if (address.is_initialized()) | |
| 365 return GetPlatformFile(index); | |
| 366 | |
| 367 if (!backend_->CreateExternalFile(&address)) | |
| 368 return base::kInvalidPlatformFileValue; | |
| 369 | |
| 370 entry_.Data()->data_addr[index] = address.value(); | |
| 371 entry_.Store(); | |
| 372 | |
| 373 // Set the flag for this stream so we never use user_buffer_. | |
| 374 // TODO(hclam): do we need to save this information to EntryStore? | |
| 375 need_file_[index] = true; | |
| 376 | |
| 377 return GetPlatformFile(index); | |
| 378 } | |
| 379 | |
| 380 base::PlatformFile EntryImpl::GetPlatformFile(int index) { | |
| 381 DCHECK(index >= 0 && index < NUM_STREAMS); | |
| 382 | |
| 383 Addr address(entry_.Data()->data_addr[index]); | |
| 384 if (!address.is_initialized() || !address.is_separate_file()) | |
| 385 return base::kInvalidPlatformFileValue; | |
| 386 | |
| 387 return base::CreatePlatformFile(backend_->GetFileName(address), | |
| 388 base::PLATFORM_FILE_OPEN | | |
| 389 base::PLATFORM_FILE_READ | | |
| 390 base::PLATFORM_FILE_ASYNC, | |
| 391 NULL); | |
| 392 } | |
| 393 | |
| 394 uint32 EntryImpl::GetHash() { | 354 uint32 EntryImpl::GetHash() { |
| 395 return entry_.Data()->hash; | 355 return entry_.Data()->hash; |
| 396 } | 356 } |
| 397 | 357 |
| 398 bool EntryImpl::CreateEntry(Addr node_address, const std::string& key, | 358 bool EntryImpl::CreateEntry(Addr node_address, const std::string& key, |
| 399 uint32 hash) { | 359 uint32 hash) { |
| 400 Trace("Create entry In"); | 360 Trace("Create entry In"); |
| 401 EntryStore* entry_store = entry_.Data(); | 361 EntryStore* entry_store = entry_.Data(); |
| 402 RankingsNode* node = node_.Data(); | 362 RankingsNode* node = node_.Data(); |
| 403 memset(entry_store, 0, sizeof(EntryStore) * entry_.address().num_blocks()); | 363 memset(entry_store, 0, sizeof(EntryStore) * entry_.address().num_blocks()); |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 if (file->Init(backend_->GetFileName(address))) | 628 if (file->Init(backend_->GetFileName(address))) |
| 669 files_[index].swap(file); | 629 files_[index].swap(file); |
| 670 } | 630 } |
| 671 return files_[index].get(); | 631 return files_[index].get(); |
| 672 } | 632 } |
| 673 | 633 |
| 674 bool EntryImpl::PrepareTarget(int index, int offset, int buf_len, | 634 bool EntryImpl::PrepareTarget(int index, int offset, int buf_len, |
| 675 bool truncate) { | 635 bool truncate) { |
| 676 Addr address(entry_.Data()->data_addr[index]); | 636 Addr address(entry_.Data()->data_addr[index]); |
| 677 | 637 |
| 678 // If we are instructed to use an external file, we should never buffer when | |
| 679 // writing. We are done with preparation of the target automatically, since | |
| 680 // we have already created the external file for writing. | |
| 681 if (need_file_[index]) { | |
| 682 // Make sure the stream is initialized and is kept in an external file. | |
| 683 DCHECK(address.is_initialized() && address.is_separate_file()); | |
| 684 return true; | |
| 685 } | |
| 686 | |
| 687 if (address.is_initialized() || user_buffers_[index].get()) | 638 if (address.is_initialized() || user_buffers_[index].get()) |
| 688 return GrowUserBuffer(index, offset, buf_len, truncate); | 639 return GrowUserBuffer(index, offset, buf_len, truncate); |
| 689 | 640 |
| 690 if (offset + buf_len > kMaxBlockSize) | 641 if (offset + buf_len > kMaxBlockSize) |
| 691 return CreateDataBlock(index, offset + buf_len); | 642 return CreateDataBlock(index, offset + buf_len); |
| 692 | 643 |
| 693 user_buffers_[index].reset(new char[kMaxBlockSize]); | 644 user_buffers_[index].reset(new char[kMaxBlockSize]); |
| 694 | 645 |
| 695 // Overwrite the parts of the buffer that are not going to be written | 646 // Overwrite the parts of the buffer that are not going to be written |
| 696 // by the current operation (and yes, let's assume that nothing is going | 647 // 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... |
| 859 Trace("%s 0x%p 0x%x 0x%x", msg, reinterpret_cast<void*>(this), | 810 Trace("%s 0x%p 0x%x 0x%x", msg, reinterpret_cast<void*>(this), |
| 860 entry_.address().value(), node_.address().value()); | 811 entry_.address().value(), node_.address().value()); |
| 861 | 812 |
| 862 Trace(" data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0], | 813 Trace(" data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0], |
| 863 entry_.Data()->data_addr[1], entry_.Data()->long_key); | 814 entry_.Data()->data_addr[1], entry_.Data()->long_key); |
| 864 | 815 |
| 865 Trace(" doomed: %d 0x%p 0x%x", doomed_, pointer, dirty); | 816 Trace(" doomed: %d 0x%p 0x%x", doomed_, pointer, dirty); |
| 866 } | 817 } |
| 867 | 818 |
| 868 } // namespace disk_cache | 819 } // namespace disk_cache |
| OLD | NEW |