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