| 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/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  Loading... | 
|   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  Loading... | 
|  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  Loading... | 
|  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  Loading... | 
|  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  Loading... | 
|  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  Loading... | 
|  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  Loading... | 
|  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  | 
| OLD | NEW |