Index: net/disk_cache/entry_impl.cc |
diff --git a/net/disk_cache/entry_impl.cc b/net/disk_cache/entry_impl.cc |
index b64073ae6589cbefe3af886f21afa55b13fcd66d..9db5647b2962e389d335bd0fb4b14f29cba7f504 100644 |
--- a/net/disk_cache/entry_impl.cc |
+++ b/net/disk_cache/entry_impl.cc |
@@ -78,8 +78,10 @@ EntryImpl::EntryImpl(BackendImpl* backend, Addr address) |
entry_.LazyInit(backend->File(address), address); |
doomed_ = false; |
backend_ = backend; |
- for (int i = 0; i < NUM_STREAMS; i++) |
+ for (int i = 0; i < NUM_STREAMS; i++) { |
unreported_size_[i] = 0; |
+ need_file_[i] = false; |
+ } |
} |
// When an entry is deleted from the cache, we clean up all the data associated |
@@ -318,7 +320,9 @@ int EntryImpl::WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, |
backend_->OnEvent(Stats::WRITE_DATA); |
- if (user_buffers_[index].get()) { |
+ // If we have prepared the cache as an external file, we should never use |
+ // user_buffers_ and always write to file directly. |
+ if (!need_file_[index] && user_buffers_[index].get()) { |
// Complete the operation locally. |
if (!buf_len) |
return 0; |
@@ -365,6 +369,43 @@ int EntryImpl::WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, |
return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING; |
} |
+base::PlatformFile EntryImpl::UseExternalFile(int index) { |
+ DCHECK(index >= 0 && index < NUM_STREAMS); |
+ |
+ Addr address(entry_.Data()->data_addr[index]); |
+ |
+ // We will not prepare the cache file since the entry is already initialized, |
+ // just return the platform file backing the cache. |
+ if (address.is_initialized()) |
+ return GetPlatformFile(index); |
+ |
+ if (!backend_->CreateExternalFile(&address)) |
+ return base::kInvalidPlatformFileValue; |
+ |
+ entry_.Data()->data_addr[index] = address.value(); |
+ entry_.Store(); |
+ |
+ // Set the flag for this stream so we never use user_buffer_. |
+ // TODO(hclam): do we need to save this information to EntryStore? |
+ need_file_[index] = true; |
+ |
+ return GetPlatformFile(index); |
+} |
+ |
+base::PlatformFile EntryImpl::GetPlatformFile(int index) { |
+ DCHECK(index >= 0 && index < NUM_STREAMS); |
+ |
+ Addr address(entry_.Data()->data_addr[index]); |
+ if (!address.is_initialized() || !address.is_separate_file()) |
+ return base::kInvalidPlatformFileValue; |
+ |
+ File* cache_file = GetExternalFile(address, index); |
+ if (!cache_file) |
+ return base::kInvalidPlatformFileValue; |
+ |
+ return cache_file->platform_file(); |
+} |
+ |
uint32 EntryImpl::GetHash() { |
return entry_.Data()->hash; |
} |
@@ -603,6 +644,16 @@ File* EntryImpl::GetExternalFile(Addr address, int index) { |
bool EntryImpl::PrepareTarget(int index, int offset, int buf_len, |
bool truncate) { |
Addr address(entry_.Data()->data_addr[index]); |
+ |
+ // If we are instructed to use an external file, we should never buffer when |
+ // writing. We are done with preparation of the target automatically, since |
+ // we have already created the external file for writing. |
+ if (need_file_[index]) { |
+ // Make sure the stream is initialized and is kept in an external file. |
+ DCHECK(address.is_initialized() && address.is_separate_file()); |
+ return true; |
+ } |
+ |
if (address.is_initialized() || user_buffers_[index].get()) |
return GrowUserBuffer(index, offset, buf_len, truncate); |