summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/disk_cache/backend_impl.cc3
-rw-r--r--net/disk_cache/backend_impl.h3
-rw-r--r--net/disk_cache/entry_impl.cc30
-rw-r--r--net/disk_cache/entry_impl.h5
-rw-r--r--net/disk_cache/entry_unittest.cc80
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();