| 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" | |
| 11 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
| 12 #include "net/disk_cache/backend_impl.h" | 11 #include "net/disk_cache/backend_impl.h" |
| 13 #include "net/disk_cache/cache_util.h" | 12 #include "net/disk_cache/cache_util.h" |
| 14 | 13 |
| 15 using base::Time; | 14 using base::Time; |
| 16 using base::TimeDelta; | 15 using base::TimeDelta; |
| 17 | 16 |
| 18 namespace { | 17 namespace { |
| 19 | 18 |
| 20 // Index for the file used to store the key, if any (files_[kKeyFileIndex]). | 19 // Index for the file used to store the key, if any (files_[kKeyFileIndex]). |
| 21 const int kKeyFileIndex = 3; | 20 const int kKeyFileIndex = 3; |
| 22 | 21 |
| 23 // 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 |
| 24 // operation from the actual net class. | 23 // operation from the actual net class. |
| 25 class SyncCallback: public disk_cache::FileIOCallback { | 24 class SyncCallback: public disk_cache::FileIOCallback { |
| 26 public: | 25 public: |
| 27 SyncCallback(disk_cache::EntryImpl* entry, net::IOBuffer* buffer, | 26 SyncCallback(disk_cache::EntryImpl* entry, |
| 28 net::CompletionCallback* callback ) | 27 net::CompletionCallback* callback ) |
| 29 : entry_(entry), callback_(callback), buf_(buffer) { | 28 : entry_(entry), callback_(callback) { |
| 30 entry->AddRef(); | 29 entry->AddRef(); |
| 31 entry->IncrementIoCount(); | 30 entry->IncrementIoCount(); |
| 32 } | 31 } |
| 33 ~SyncCallback() {} | 32 ~SyncCallback() {} |
| 34 | 33 |
| 35 virtual void OnFileIOComplete(int bytes_copied); | 34 virtual void OnFileIOComplete(int bytes_copied); |
| 36 void Discard(); | 35 void Discard(); |
| 37 private: | 36 private: |
| 38 disk_cache::EntryImpl* entry_; | 37 disk_cache::EntryImpl* entry_; |
| 39 net::CompletionCallback* callback_; | 38 net::CompletionCallback* callback_; |
| 40 scoped_refptr<net::IOBuffer> buf_; | |
| 41 | 39 |
| 42 DISALLOW_EVIL_CONSTRUCTORS(SyncCallback); | 40 DISALLOW_EVIL_CONSTRUCTORS(SyncCallback); |
| 43 }; | 41 }; |
| 44 | 42 |
| 45 void SyncCallback::OnFileIOComplete(int bytes_copied) { | 43 void SyncCallback::OnFileIOComplete(int bytes_copied) { |
| 46 entry_->DecrementIoCount(); | 44 entry_->DecrementIoCount(); |
| 47 entry_->Release(); | 45 entry_->Release(); |
| 48 if (callback_) | 46 if (callback_) |
| 49 callback_->Run(bytes_copied); | 47 callback_->Run(bytes_copied); |
| 50 delete this; | 48 delete this; |
| 51 } | 49 } |
| 52 | 50 |
| 53 void SyncCallback::Discard() { | 51 void SyncCallback::Discard() { |
| 54 callback_ = NULL; | 52 callback_ = NULL; |
| 55 buf_ = NULL; | |
| 56 OnFileIOComplete(0); | 53 OnFileIOComplete(0); |
| 57 } | 54 } |
| 58 | 55 |
| 59 // Clears buffer before offset and after valid_len, knowing that the size of | 56 // Clears buffer before offset and after valid_len, knowing that the size of |
| 60 // buffer is kMaxBlockSize. | 57 // buffer is kMaxBlockSize. |
| 61 void ClearInvalidData(char* buffer, int offset, int valid_len) { | 58 void ClearInvalidData(char* buffer, int offset, int valid_len) { |
| 62 DCHECK(offset >= 0); | 59 DCHECK(offset >= 0); |
| 63 DCHECK(valid_len >= 0); | 60 DCHECK(valid_len >= 0); |
| 64 DCHECK(disk_cache::kMaxBlockSize >= offset + valid_len); | 61 DCHECK(disk_cache::kMaxBlockSize >= offset + valid_len); |
| 65 if (offset) | 62 if (offset) |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 } | 187 } |
| 191 | 188 |
| 192 int32 EntryImpl::GetDataSize(int index) const { | 189 int32 EntryImpl::GetDataSize(int index) const { |
| 193 if (index < 0 || index >= NUM_STREAMS) | 190 if (index < 0 || index >= NUM_STREAMS) |
| 194 return 0; | 191 return 0; |
| 195 | 192 |
| 196 CacheEntryBlock* entry = const_cast<CacheEntryBlock*>(&entry_); | 193 CacheEntryBlock* entry = const_cast<CacheEntryBlock*>(&entry_); |
| 197 return entry->Data()->data_size[index]; | 194 return entry->Data()->data_size[index]; |
| 198 } | 195 } |
| 199 | 196 |
| 200 int EntryImpl::ReadData(int index, int offset, net::IOBuffer* buf, int buf_len, | 197 int EntryImpl::ReadData(int index, int offset, char* buf, int buf_len, |
| 201 net::CompletionCallback* completion_callback) { | 198 net::CompletionCallback* completion_callback) { |
| 202 DCHECK(node_.Data()->dirty); | 199 DCHECK(node_.Data()->dirty); |
| 203 if (index < 0 || index >= NUM_STREAMS) | 200 if (index < 0 || index >= NUM_STREAMS) |
| 204 return net::ERR_INVALID_ARGUMENT; | 201 return net::ERR_INVALID_ARGUMENT; |
| 205 | 202 |
| 206 int entry_size = entry_.Data()->data_size[index]; | 203 int entry_size = entry_.Data()->data_size[index]; |
| 207 if (offset >= entry_size || offset < 0 || !buf_len) | 204 if (offset >= entry_size || offset < 0 || !buf_len) |
| 208 return 0; | 205 return 0; |
| 209 | 206 |
| 210 if (buf_len < 0) | 207 if (buf_len < 0) |
| 211 return net::ERR_INVALID_ARGUMENT; | 208 return net::ERR_INVALID_ARGUMENT; |
| 212 | 209 |
| 213 Time start = Time::Now(); | 210 Time start = Time::Now(); |
| 214 static Histogram stats(L"DiskCache.ReadTime", TimeDelta::FromMilliseconds(1), | 211 static Histogram stats(L"DiskCache.ReadTime", TimeDelta::FromMilliseconds(1), |
| 215 TimeDelta::FromSeconds(10), 50); | 212 TimeDelta::FromSeconds(10), 50); |
| 216 stats.SetFlags(kUmaTargetedHistogramFlag); | 213 stats.SetFlags(kUmaTargetedHistogramFlag); |
| 217 | 214 |
| 218 if (offset + buf_len > entry_size) | 215 if (offset + buf_len > entry_size) |
| 219 buf_len = entry_size - offset; | 216 buf_len = entry_size - offset; |
| 220 | 217 |
| 221 UpdateRank(false); | 218 UpdateRank(false); |
| 222 | 219 |
| 223 backend_->OnEvent(Stats::READ_DATA); | 220 backend_->OnEvent(Stats::READ_DATA); |
| 224 | 221 |
| 225 if (user_buffers_[index].get()) { | 222 if (user_buffers_[index].get()) { |
| 226 // Complete the operation locally. | 223 // Complete the operation locally. |
| 227 DCHECK(kMaxBlockSize >= offset + buf_len); | 224 DCHECK(kMaxBlockSize >= offset + buf_len); |
| 228 memcpy(buf->data() , user_buffers_[index].get() + offset, buf_len); | 225 memcpy(buf , user_buffers_[index].get() + offset, buf_len); |
| 229 stats.AddTime(Time::Now() - start); | 226 stats.AddTime(Time::Now() - start); |
| 230 return buf_len; | 227 return buf_len; |
| 231 } | 228 } |
| 232 | 229 |
| 233 Addr address(entry_.Data()->data_addr[index]); | 230 Addr address(entry_.Data()->data_addr[index]); |
| 234 DCHECK(address.is_initialized()); | 231 DCHECK(address.is_initialized()); |
| 235 if (!address.is_initialized()) | 232 if (!address.is_initialized()) |
| 236 return net::ERR_FAILED; | 233 return net::ERR_FAILED; |
| 237 | 234 |
| 238 File* file = GetBackingFile(address, index); | 235 File* file = GetBackingFile(address, index); |
| 239 if (!file) | 236 if (!file) |
| 240 return net::ERR_FAILED; | 237 return net::ERR_FAILED; |
| 241 | 238 |
| 242 size_t file_offset = offset; | 239 size_t file_offset = offset; |
| 243 if (address.is_block_file()) | 240 if (address.is_block_file()) |
| 244 file_offset += address.start_block() * address.BlockSize() + | 241 file_offset += address.start_block() * address.BlockSize() + |
| 245 kBlockHeaderSize; | 242 kBlockHeaderSize; |
| 246 | 243 |
| 247 SyncCallback* io_callback = NULL; | 244 SyncCallback* io_callback = NULL; |
| 248 if (completion_callback) | 245 if (completion_callback) |
| 249 io_callback = new SyncCallback(this, buf, completion_callback); | 246 io_callback = new SyncCallback(this, completion_callback); |
| 250 | 247 |
| 251 bool completed; | 248 bool completed; |
| 252 if (!file->Read(buf->data(), buf_len, file_offset, io_callback, &completed)) { | 249 if (!file->Read(buf, buf_len, file_offset, io_callback, &completed)) { |
| 253 if (io_callback) | 250 if (io_callback) |
| 254 io_callback->Discard(); | 251 io_callback->Discard(); |
| 255 return net::ERR_FAILED; | 252 return net::ERR_FAILED; |
| 256 } | 253 } |
| 257 | 254 |
| 258 if (io_callback && completed) | 255 if (io_callback && completed) |
| 259 io_callback->Discard(); | 256 io_callback->Discard(); |
| 260 | 257 |
| 261 stats.AddTime(Time::Now() - start); | 258 stats.AddTime(Time::Now() - start); |
| 262 return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING; | 259 return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING; |
| 263 } | 260 } |
| 264 | 261 |
| 265 int EntryImpl::WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, | 262 int EntryImpl::WriteData(int index, int offset, const char* buf, int buf_len, |
| 266 net::CompletionCallback* completion_callback, | 263 net::CompletionCallback* completion_callback, |
| 267 bool truncate) { | 264 bool truncate) { |
| 268 DCHECK(node_.Data()->dirty); | 265 DCHECK(node_.Data()->dirty); |
| 269 if (index < 0 || index >= NUM_STREAMS) | 266 if (index < 0 || index >= NUM_STREAMS) |
| 270 return net::ERR_INVALID_ARGUMENT; | 267 return net::ERR_INVALID_ARGUMENT; |
| 271 | 268 |
| 272 if (offset < 0 || buf_len < 0) | 269 if (offset < 0 || buf_len < 0) |
| 273 return net::ERR_INVALID_ARGUMENT; | 270 return net::ERR_INVALID_ARGUMENT; |
| 274 | 271 |
| 275 int max_file_size = backend_->MaxFileSize(); | 272 int max_file_size = backend_->MaxFileSize(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 } | 311 } |
| 315 } | 312 } |
| 316 | 313 |
| 317 UpdateRank(true); | 314 UpdateRank(true); |
| 318 | 315 |
| 319 backend_->OnEvent(Stats::WRITE_DATA); | 316 backend_->OnEvent(Stats::WRITE_DATA); |
| 320 | 317 |
| 321 if (user_buffers_[index].get()) { | 318 if (user_buffers_[index].get()) { |
| 322 // Complete the operation locally. | 319 // Complete the operation locally. |
| 323 DCHECK(kMaxBlockSize >= offset + buf_len); | 320 DCHECK(kMaxBlockSize >= offset + buf_len); |
| 324 memcpy(user_buffers_[index].get() + offset, buf->data(), buf_len); | 321 memcpy(user_buffers_[index].get() + offset, buf, buf_len); |
| 325 stats.AddTime(Time::Now() - start); | 322 stats.AddTime(Time::Now() - start); |
| 326 return buf_len; | 323 return buf_len; |
| 327 } | 324 } |
| 328 | 325 |
| 329 Addr address(entry_.Data()->data_addr[index]); | 326 Addr address(entry_.Data()->data_addr[index]); |
| 330 File* file = GetBackingFile(address, index); | 327 File* file = GetBackingFile(address, index); |
| 331 if (!file) | 328 if (!file) |
| 332 return net::ERR_FAILED; | 329 return net::ERR_FAILED; |
| 333 | 330 |
| 334 size_t file_offset = offset; | 331 size_t file_offset = offset; |
| 335 if (address.is_block_file()) { | 332 if (address.is_block_file()) { |
| 336 file_offset += address.start_block() * address.BlockSize() + | 333 file_offset += address.start_block() * address.BlockSize() + |
| 337 kBlockHeaderSize; | 334 kBlockHeaderSize; |
| 338 } else if (truncate) { | 335 } else if (truncate) { |
| 339 if (!file->SetLength(offset + buf_len)) | 336 if (!file->SetLength(offset + buf_len)) |
| 340 return net::ERR_FAILED; | 337 return net::ERR_FAILED; |
| 341 } | 338 } |
| 342 | 339 |
| 343 if (!buf_len) | 340 if (!buf_len) |
| 344 return 0; | 341 return 0; |
| 345 | 342 |
| 346 SyncCallback* io_callback = NULL; | 343 SyncCallback* io_callback = NULL; |
| 347 if (completion_callback) | 344 if (completion_callback) |
| 348 io_callback = new SyncCallback(this, buf, completion_callback); | 345 io_callback = new SyncCallback(this, completion_callback); |
| 349 | 346 |
| 350 bool completed; | 347 bool completed; |
| 351 if (!file->Write(buf->data(), buf_len, file_offset, io_callback, | 348 if (!file->Write(buf, buf_len, file_offset, io_callback, &completed)) { |
| 352 &completed)) { | |
| 353 if (io_callback) | 349 if (io_callback) |
| 354 io_callback->Discard(); | 350 io_callback->Discard(); |
| 355 return net::ERR_FAILED; | 351 return net::ERR_FAILED; |
| 356 } | 352 } |
| 357 | 353 |
| 358 if (io_callback && completed) | 354 if (io_callback && completed) |
| 359 io_callback->Discard(); | 355 io_callback->Discard(); |
| 360 | 356 |
| 361 stats.AddTime(Time::Now() - start); | 357 stats.AddTime(Time::Now() - start); |
| 362 return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING; | 358 return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING; |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 entry_.address().value(), node_.address().value()); | 772 entry_.address().value(), node_.address().value()); |
| 777 | 773 |
| 778 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], |
| 779 entry_.Data()->data_addr[1], entry_.Data()->long_key); | 775 entry_.Data()->data_addr[1], entry_.Data()->long_key); |
| 780 | 776 |
| 781 Trace(" doomed: %d 0x%p 0x%x", doomed_, pointer, dirty); | 777 Trace(" doomed: %d 0x%p 0x%x", doomed_, pointer, dirty); |
| 782 } | 778 } |
| 783 | 779 |
| 784 } // namespace disk_cache | 780 } // namespace disk_cache |
| 785 | 781 |
| OLD | NEW |