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 |