diff options
-rw-r--r-- | net/disk_cache/backend_impl.cc | 3 | ||||
-rw-r--r-- | net/disk_cache/backend_impl.h | 3 | ||||
-rw-r--r-- | net/disk_cache/entry_impl.cc | 30 | ||||
-rw-r--r-- | net/disk_cache/entry_impl.h | 5 | ||||
-rw-r--r-- | net/disk_cache/entry_unittest.cc | 80 |
5 files changed, 103 insertions, 18 deletions
diff --git a/net/disk_cache/backend_impl.cc b/net/disk_cache/backend_impl.cc index 4a4f7ea..fbc1e6a 100644 --- a/net/disk_cache/backend_impl.cc +++ b/net/disk_cache/backend_impl.cc @@ -1088,6 +1088,9 @@ void BackendImpl::TooMuchStorageRequested(int32 size) { bool BackendImpl::IsAllocAllowed(int current_size, int new_size) { DCHECK_GT(new_size, current_size); + if (user_flags_ & kNoBuffering) + return false; + int to_add = new_size - current_size; if (buffer_bytes_ + to_add > MaxBuffersSize()) return false; diff --git a/net/disk_cache/backend_impl.h b/net/disk_cache/backend_impl.h index c4a1bab..a8880d1 100644 --- a/net/disk_cache/backend_impl.h +++ b/net/disk_cache/backend_impl.h @@ -29,7 +29,8 @@ enum BackendFlags { kUpgradeMode = 1 << 3, // This is the upgrade tool (dump). kNewEviction = 1 << 4, // Use of new eviction was specified. kNoRandom = 1 << 5, // Don't add randomness to the behavior. - kNoLoadProtection = 1 << 6 // Don't act conservatively under load. + kNoLoadProtection = 1 << 6, // Don't act conservatively under load. + kNoBuffering = 1 << 7 // Disable extended IO buffering. }; // This class implements the Backend interface. An object of this diff --git a/net/disk_cache/entry_impl.cc b/net/disk_cache/entry_impl.cc index 8d9fab6..c8ee9b0 100644 --- a/net/disk_cache/entry_impl.cc +++ b/net/disk_cache/entry_impl.cc @@ -242,6 +242,7 @@ void EntryImpl::UserBuffer::Reset() { grow_allowed_ = true; std::vector<char> tmp; buffer_.swap(tmp); + buffer_.reserve(kMaxBlockSize); } offset_ = 0; buffer_.clear(); @@ -302,7 +303,7 @@ EntryImpl::~EntryImpl() { bool ret = true; for (int index = 0; index < kNumStreams; index++) { if (user_buffers_[index].get()) { - if (!(ret = Flush(index))) + if (!(ret = Flush(index, 0))) LOG(ERROR) << "Failed to save user data"; } if (unreported_size_[index]) { @@ -519,9 +520,11 @@ int EntryImpl::ReadDataImpl(int index, int offset, net::IOBuffer* buf, return net::ERR_FAILED; size_t file_offset = offset; - if (address.is_block_file()) + if (address.is_block_file()) { + DCHECK_LE(offset + buf_len, kMaxBlockSize); file_offset += address.start_block() * address.BlockSize() + kBlockHeaderSize; + } SyncCallback* io_callback = NULL; if (callback) @@ -601,6 +604,7 @@ int EntryImpl::WriteDataImpl(int index, int offset, net::IOBuffer* buf, size_t file_offset = offset; if (address.is_block_file()) { + DCHECK_LE(offset + buf_len, kMaxBlockSize); file_offset += address.start_block() * address.BlockSize() + kBlockHeaderSize; } else if (truncate || (extending && !buf_len)) { @@ -1070,7 +1074,7 @@ bool EntryImpl::HandleTruncation(int index, int offset, int buf_len) { if (offset > user_buffers_[index]->Start()) user_buffers_[index]->Truncate(new_size); UpdateSize(index, current_size, new_size); - if (!Flush(index)) + if (!Flush(index, 0)) return false; user_buffers_[index].reset(); } @@ -1139,13 +1143,13 @@ bool EntryImpl::PrepareBuffer(int index, int offset, int buf_len) { Addr address(entry_.Data()->data_addr[index]); if (address.is_initialized() && address.is_separate_file()) { int eof = entry_.Data()->data_size[index]; - if (eof > user_buffers_[index]->Start() && !Flush(index)) + if (eof > user_buffers_[index]->Start() && !Flush(index, 0)) return false; } } if (!user_buffers_[index]->PreWrite(offset, buf_len)) { - if (!Flush(index)) + if (!Flush(index, offset + buf_len)) return false; // Lets try again. @@ -1159,30 +1163,34 @@ bool EntryImpl::PrepareBuffer(int index, int offset, int buf_len) { return true; } -bool EntryImpl::Flush(int index) { +bool EntryImpl::Flush(int index, int min_len) { Addr address(entry_.Data()->data_addr[index]); DCHECK(user_buffers_[index].get()); + DCHECK(!address.is_initialized() || address.is_separate_file()); + + int size = std::max(entry_.Data()->data_size[index], min_len); + if (!address.is_initialized() && !CreateDataBlock(index, size)) + return false; if (!entry_.Data()->data_size[index]) { DCHECK(!user_buffers_[index]->Size()); return true; } - if (!address.is_initialized() && - !CreateDataBlock(index, entry_.Data()->data_size[index])) - return false; - address.set_value(entry_.Data()->data_addr[index]); - File* file = GetBackingFile(address, index); int len = user_buffers_[index]->Size(); int offset = user_buffers_[index]->Start(); + if (!len && !offset) + return true; + if (address.is_block_file()) { DCHECK_EQ(len, entry_.Data()->data_size[index]); DCHECK(!offset); offset = address.start_block() * address.BlockSize() + kBlockHeaderSize; } + File* file = GetBackingFile(address, index); if (!file) return false; diff --git a/net/disk_cache/entry_impl.h b/net/disk_cache/entry_impl.h index f1b9251..e27f23a 100644 --- a/net/disk_cache/entry_impl.h +++ b/net/disk_cache/entry_impl.h @@ -179,8 +179,9 @@ class EntryImpl : public Entry, public base::RefCounted<EntryImpl> { // bytes to |offset|. bool PrepareBuffer(int index, int offset, int buf_len); - // Flushes the in-memory data to the backing storage. - bool Flush(int index); + // Flushes the in-memory data to the backing storage. The data destination + // is determined based on the current data length and |min_len|. + bool Flush(int index, int min_len); // Updates the size of a given data stream. void UpdateSize(int index, int old_size, int new_size); diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc index ce0c11f..c4dc705f 100644 --- a/net/disk_cache/entry_unittest.cc +++ b/net/disk_cache/entry_unittest.cc @@ -9,6 +9,7 @@ #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" +#include "net/disk_cache/backend_impl.h" #include "net/disk_cache/disk_cache_test_base.h" #include "net/disk_cache/disk_cache_test_util.h" #include "net/disk_cache/entry_impl.h" @@ -37,6 +38,8 @@ class DiskCacheEntryTest : public DiskCacheTestWithCache { void GrowData(); void TruncateData(); void ZeroLengthIO(); + void Buffering(); + void SizeChanges(); void ReuseEntry(int size); void InvalidData(); void DoomNormalEntry(); @@ -343,6 +346,13 @@ TEST_F(DiskCacheEntryTest, ExternalSyncIO) { ExternalSyncIO(); } +TEST_F(DiskCacheEntryTest, ExternalSyncIONoBuffer) { + SetDirectMode(); + InitCache(); + cache_impl_->SetFlags(disk_cache::kNoBuffering); + ExternalSyncIO(); +} + TEST_F(DiskCacheEntryTest, MemoryOnlyExternalSyncIO) { SetMemoryOnlyMode(); InitCache(); @@ -452,6 +462,13 @@ TEST_F(DiskCacheEntryTest, ExternalAsyncIO) { ExternalAsyncIO(); } +TEST_F(DiskCacheEntryTest, ExternalAsyncIONoBuffer) { + SetDirectMode(); + InitCache(); + cache_impl_->SetFlags(disk_cache::kNoBuffering); + ExternalAsyncIO(); +} + TEST_F(DiskCacheEntryTest, MemoryOnlyExternalAsyncIO) { SetMemoryOnlyMode(); InitCache(); @@ -662,6 +679,13 @@ TEST_F(DiskCacheEntryTest, GrowData) { GrowData(); } +TEST_F(DiskCacheEntryTest, GrowDataNoBuffer) { + SetDirectMode(); + InitCache(); + cache_impl_->SetFlags(disk_cache::kNoBuffering); + GrowData(); +} + TEST_F(DiskCacheEntryTest, MemoryOnlyGrowData) { SetMemoryOnlyMode(); InitCache(); @@ -738,6 +762,18 @@ TEST_F(DiskCacheEntryTest, TruncateData) { helper.WaitUntilCacheIoFinished(1); } +TEST_F(DiskCacheEntryTest, TruncateDataNoBuffer) { + SetDirectMode(); + InitCache(); + cache_impl_->SetFlags(disk_cache::kNoBuffering); + TruncateData(); + + // We generate asynchronous IO that is not really tracked until completion + // so we just wait here before running the next test. + MessageLoopHelper helper; + helper.WaitUntilCacheIoFinished(1); +} + TEST_F(DiskCacheEntryTest, MemoryOnlyTruncateData) { SetMemoryOnlyMode(); InitCache(); @@ -787,6 +823,13 @@ TEST_F(DiskCacheEntryTest, ZeroLengthIO) { ZeroLengthIO(); } +TEST_F(DiskCacheEntryTest, ZeroLengthIONoBuffer) { + SetDirectMode(); + InitCache(); + cache_impl_->SetFlags(disk_cache::kNoBuffering); + ZeroLengthIO(); +} + TEST_F(DiskCacheEntryTest, MemoryOnlyZeroLengthIO) { SetMemoryOnlyMode(); InitCache(); @@ -794,8 +837,7 @@ TEST_F(DiskCacheEntryTest, MemoryOnlyZeroLengthIO) { } // Tests that we handle the content correctly when buffering. -TEST_F(DiskCacheEntryTest, Buffering) { - InitCache(); +void DiskCacheEntryTest::Buffering() { std::string key("the first key"); disk_cache::Entry* entry; ASSERT_EQ(net::OK, CreateEntry(key, &entry)); @@ -861,10 +903,21 @@ TEST_F(DiskCacheEntryTest, Buffering) { entry->Close(); } +TEST_F(DiskCacheEntryTest, Buffering) { + InitCache(); + Buffering(); +} + +TEST_F(DiskCacheEntryTest, BufferingNoBuffer) { + SetDirectMode(); + InitCache(); + cache_impl_->SetFlags(disk_cache::kNoBuffering); + Buffering(); +} + // Some extra tests to make sure that buffering works properly when changing // the entry size. -TEST_F(DiskCacheEntryTest, SizeChanges) { - InitCache(); +void DiskCacheEntryTest::SizeChanges() { std::string key("the first key"); disk_cache::Entry* entry; ASSERT_EQ(net::OK, CreateEntry(key, &entry)); @@ -937,6 +990,18 @@ TEST_F(DiskCacheEntryTest, SizeChanges) { entry->Close(); } +TEST_F(DiskCacheEntryTest, SizeChanges) { + InitCache(); + SizeChanges(); +} + +TEST_F(DiskCacheEntryTest, SizeChangesNoBuffer) { + SetDirectMode(); + InitCache(); + cache_impl_->SetFlags(disk_cache::kNoBuffering); + SizeChanges(); +} + // Write more than the total cache capacity but to a single entry. |size| is the // amount of bytes to write each time. void DiskCacheEntryTest::ReuseEntry(int size) { @@ -1063,6 +1128,13 @@ TEST_F(DiskCacheEntryTest, InvalidData) { InvalidData(); } +TEST_F(DiskCacheEntryTest, InvalidDataNoBuffer) { + SetDirectMode(); + InitCache(); + cache_impl_->SetFlags(disk_cache::kNoBuffering); + InvalidData(); +} + TEST_F(DiskCacheEntryTest, MemoryOnlyInvalidData) { SetMemoryOnlyMode(); InitCache(); |