Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(346)

Unified Diff: net/disk_cache/simple/simple_synchronous_entry.cc

Issue 23983005: SimpleCache: merge the first and second stream in one file (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Stream 0 size in footer Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/disk_cache/simple/simple_synchronous_entry.cc
diff --git a/net/disk_cache/simple/simple_synchronous_entry.cc b/net/disk_cache/simple/simple_synchronous_entry.cc
index a1ff1ac6adaab1664d6a61656ed1a1af93a0d308..67af92f8b92ecae91fce2980e2e5d03f9c3adc73 100644
--- a/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -146,7 +146,9 @@ using simple_util::GetEntryHashKey;
using simple_util::GetFilenameFromEntryHashAndIndex;
using simple_util::GetDataSizeFromKeyAndFileSize;
using simple_util::GetFileSizeFromKeyAndDataSize;
-using simple_util::GetFileOffsetFromKeyAndDataOffset;
+using simple_util::GetFileIndexFromStreamIndex;
+using simple_util::GetLastEOFRecordOffset;
+using simple_util::GetFileOffsetFromDataOffset;
SimpleEntryStat::SimpleEntryStat() {}
@@ -158,6 +160,27 @@ SimpleEntryStat::SimpleEntryStat(base::Time last_used_p,
memcpy(data_size, data_size_p, sizeof(data_size));
}
+int SimpleEntryStat::GetOffsetInFile(const std::string& key,
+ int offset,
+ int stream_index) const {
+ return GetFileOffsetFromDataOffset(key, offset, stream_index, data_size[1]);
+}
+
+int SimpleEntryStat::GetEOFOffsetInFile(const std::string& key,
+ int stream_index) const {
+ return GetFileOffsetFromDataOffset(
+ key, data_size[stream_index], stream_index, data_size[1]);
+}
+
+int SimpleEntryStat::GetLastEOFOffsetInFile(const std::string& key,
+ int stream_index) const {
+ return GetOffsetInFile(
+ key,
+ GetLastEOFRecordOffset(GetFileIndexFromStreamIndex(stream_index),
+ data_size),
+ stream_index);
+}
+
SimpleEntryCreationResults::SimpleEntryCreationResults(
SimpleEntryStat entry_stat)
: sync_entry(NULL),
@@ -206,11 +229,12 @@ void SimpleSynchronousEntry::OpenEntry(
SimpleSynchronousEntry* sync_entry =
new SimpleSynchronousEntry(cache_type, path, "", entry_hash);
out_results->result = sync_entry->InitializeForOpen(
- had_index, &out_results->entry_stat);
+ had_index, &out_results->entry_stat, &out_results->stream_0_data);
if (out_results->result != net::OK) {
sync_entry->Doom();
delete sync_entry;
out_results->sync_entry = NULL;
+ out_results->stream_0_data = NULL;
return;
}
out_results->sync_entry = sync_entry;
@@ -279,17 +303,16 @@ int SimpleSynchronousEntry::DoomEntrySet(
void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op,
net::IOBuffer* out_buf,
uint32* out_crc32,
- base::Time* out_last_used,
+ SimpleEntryStat* out_entry_stat,
int* out_result) const {
DCHECK(initialized_);
- int64 file_offset =
- GetFileOffsetFromKeyAndDataOffset(key_, in_entry_op.offset);
- int bytes_read = ReadPlatformFile(files_[in_entry_op.index],
- file_offset,
- out_buf->data(),
- in_entry_op.buf_len);
+ const int64 file_offset = out_entry_stat->GetOffsetInFile(
+ key_, in_entry_op.offset, in_entry_op.index);
+ int file_index = GetFileIndexFromStreamIndex(in_entry_op.index);
+ int bytes_read = ReadPlatformFile(
+ files_[file_index], file_offset, out_buf->data(), in_entry_op.buf_len);
if (bytes_read > 0) {
- *out_last_used = Time::Now();
+ out_entry_stat->last_used = Time::Now();
*out_crc32 = crc32(crc32(0L, Z_NULL, 0),
reinterpret_cast<const Bytef*>(out_buf->data()),
bytes_read);
@@ -308,26 +331,28 @@ void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op,
int* out_result) const {
DCHECK(initialized_);
int index = in_entry_op.index;
+ int file_index = GetFileIndexFromStreamIndex(index);
int offset = in_entry_op.offset;
int buf_len = in_entry_op.buf_len;
int truncate = in_entry_op.truncate;
-
+ const int64 file_offset = out_entry_stat->GetOffsetInFile(
+ key_, in_entry_op.offset, in_entry_op.index);
bool extending_by_write = offset + buf_len > out_entry_stat->data_size[index];
if (extending_by_write) {
- // We are extending the file, and need to insure the EOF record is zeroed.
- const int64 file_eof_offset = GetFileOffsetFromKeyAndDataOffset(
- key_, out_entry_stat->data_size[index]);
- if (!TruncatePlatformFile(files_[index], file_eof_offset)) {
+ // The EOF record and the eventual stream afterward need to be zeroed out.
+ const int64 file_eof_offset =
+ out_entry_stat->GetEOFOffsetInFile(key_, index);
+ if (!TruncatePlatformFile(files_[file_index], file_eof_offset)) {
RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE);
Doom();
*out_result = net::ERR_CACHE_WRITE_FAILURE;
return;
}
}
- const int64 file_offset = GetFileOffsetFromKeyAndDataOffset(key_, offset);
if (buf_len > 0) {
if (WritePlatformFile(
- files_[index], file_offset, in_buf->data(), buf_len) != buf_len) {
+ files_[file_index], file_offset, in_buf->data(), buf_len) !=
+ buf_len) {
RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE);
Doom();
*out_result = net::ERR_CACHE_WRITE_FAILURE;
@@ -338,13 +363,14 @@ void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op,
out_entry_stat->data_size[index] =
std::max(out_entry_stat->data_size[index], offset + buf_len);
} else {
- if (!TruncatePlatformFile(files_[index], file_offset + buf_len)) {
+ out_entry_stat->data_size[index] = offset + buf_len;
+ int file_eof_offset = out_entry_stat->GetLastEOFOffsetInFile(key_, index);
+ if (!TruncatePlatformFile(files_[file_index], file_eof_offset)) {
RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE);
Doom();
*out_result = net::ERR_CACHE_WRITE_FAILURE;
return;
}
- out_entry_stat->data_size[index] = offset + buf_len;
}
RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS);
@@ -353,61 +379,63 @@ void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op,
}
void SimpleSynchronousEntry::CheckEOFRecord(int index,
- int32 data_size,
+ const SimpleEntryStat& entry_stat,
uint32 expected_crc32,
int* out_result) const {
DCHECK(initialized_);
-
- SimpleFileEOF eof_record;
- int64 file_offset = GetFileOffsetFromKeyAndDataOffset(key_, data_size);
- if (ReadPlatformFile(files_[index],
- file_offset,
- reinterpret_cast<char*>(&eof_record),
- sizeof(eof_record)) != sizeof(eof_record)) {
- RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE);
+ uint32 crc32;
+ bool has_crc32;
+ int stream_size;
+ *out_result =
+ GetEOFRecordData(index, entry_stat, &has_crc32, &crc32, &stream_size);
+ if (*out_result != net::OK) {
Doom();
- *out_result = net::ERR_CACHE_CHECKSUM_READ_FAILURE;
return;
}
-
- if (eof_record.final_magic_number != kSimpleFinalMagicNumber) {
- RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH);
- DLOG(INFO) << "eof record had bad magic number.";
- Doom();
- *out_result = net::ERR_CACHE_CHECKSUM_READ_FAILURE;
- return;
- }
-
- const bool has_crc = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) ==
- SimpleFileEOF::FLAG_HAS_CRC32;
- SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, has_crc);
- if (has_crc && eof_record.data_crc32 != expected_crc32) {
+ if (has_crc32 && crc32 != expected_crc32) {
+ DLOG(INFO) << "Eof record had bad crc.";
+ *out_result = net::ERR_CACHE_CHECKSUM_MISMATCH;
RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
- DLOG(INFO) << "eof record had bad crc.";
Doom();
- *out_result = net::ERR_CACHE_CHECKSUM_MISMATCH;
return;
}
-
RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
- *out_result = net::OK;
}
void SimpleSynchronousEntry::Close(
const SimpleEntryStat& entry_stat,
- scoped_ptr<std::vector<CRCRecord> > crc32s_to_write) {
+ scoped_ptr<std::vector<CRCRecord> > crc32s_to_write,
+ net::GrowableIOBuffer* stream_0_data) {
+ if (!stream_0_data) {
gavinp 2013/09/17 13:27:11 What's happening in this case?
clamy 2013/09/17 13:59:42 If we were supposed to have data and we don't, it'
gavinp 2013/09/17 14:25:33 In practice we always have data in stream 0, but i
clamy 2013/09/17 14:29:48 If we get non 0 size in data_size[0], then we expe
gavinp 2013/09/17 15:07:43 Aha, yup. So you were right the first time, this s
clamy 2013/09/18 16:17:14 With the other modifications that went in, we shou
+ if (entry_stat.data_size[0])
+ Doom();
+ } else {
+ // Write stream 0 data.
+ int stream_0_offset = entry_stat.GetOffsetInFile(key_, 0, 0);
+ if (WritePlatformFile(files_[0],
+ stream_0_offset,
+ stream_0_data->data(),
+ entry_stat.data_size[0]) != entry_stat.data_size[0]) {
+ RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
+ DLOG(INFO) << "Could not write stream 0 data.";
+ Doom();
+ }
+ }
+
for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin();
it != crc32s_to_write->end(); ++it) {
SimpleFileEOF eof_record;
+ int index = it->index;
+ eof_record.stream_size = entry_stat.data_size[index];
eof_record.final_magic_number = kSimpleFinalMagicNumber;
eof_record.flags = 0;
if (it->has_crc32)
eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32;
eof_record.data_crc32 = it->data_crc32;
- int64 file_offset = GetFileOffsetFromKeyAndDataOffset(
- key_, entry_stat.data_size[it->index]);
- if (WritePlatformFile(files_[it->index],
- file_offset,
+ int file_index = GetFileIndexFromStreamIndex(index);
+ int eof_offset = entry_stat.GetEOFOffsetInFile(key_, index);
+ if (WritePlatformFile(files_[file_index],
+ eof_offset,
reinterpret_cast<const char*>(&eof_record),
sizeof(eof_record)) != sizeof(eof_record)) {
RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
@@ -415,7 +443,12 @@ void SimpleSynchronousEntry::Close(
Doom();
break;
}
- const int64 file_size = file_offset + sizeof(eof_record);
+ }
+ for (int i = 0; i < kSimpleEntryFileCount; ++i) {
+ bool did_close_file = ClosePlatformFile(files_[i]);
+ CHECK(did_close_file);
+ const int64 file_size = GetFileSizeFromKeyAndDataSize(
+ key_, GetLastEOFRecordOffset(i, entry_stat.data_size));
SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
"LastClusterSize", cache_type_,
file_size % 4096, 0, 4097, 50);
@@ -424,11 +457,6 @@ void SimpleSynchronousEntry::Close(
"LastClusterLossPercent", cache_type_,
cluster_loss * 100 / (cluster_loss + file_size));
}
-
- for (int i = 0; i < kSimpleEntryFileCount; ++i) {
- bool did_close_file = ClosePlatformFile(files_[i]);
- CHECK(did_close_file);
- }
RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS);
have_open_files_ = false;
delete this;
@@ -517,7 +545,7 @@ bool SimpleSynchronousEntry::OpenOrCreateFiles(
have_open_files_ = true;
if (create) {
out_entry_stat->last_modified = out_entry_stat->last_used = Time::Now();
- for (int i = 0; i < kSimpleEntryFileCount; ++i)
+ for (int i = 0; i < kSimpleEntryStreamCount; ++i)
out_entry_stat->data_size[i] = 0;
} else {
base::TimeDelta entry_age = base::Time::Now() - base::Time::UnixEpoch();
@@ -540,9 +568,9 @@ bool SimpleSynchronousEntry::OpenOrCreateFiles(
if (stream_age < entry_age)
entry_age = stream_age;
- // Keep the file size in |data size_| briefly until the key is initialized
- // properly.
- out_entry_stat->data_size[i] = file_info.size;
+ // Keep the file size in |data size_| temporarily until the data sizes are
+ // initialized correctly.
+ out_entry_stat->data_size[i + 1] = file_info.size;
}
SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
"SyncOpenEntryAge", cache_type_,
@@ -560,12 +588,13 @@ void SimpleSynchronousEntry::CloseFiles() {
}
}
-int SimpleSynchronousEntry::InitializeForOpen(bool had_index,
- SimpleEntryStat* out_entry_stat) {
+int SimpleSynchronousEntry::InitializeForOpen(
+ bool had_index,
+ SimpleEntryStat* out_entry_stat,
+ scoped_refptr<net::GrowableIOBuffer>* stream_0_data) {
DCHECK(!initialized_);
if (!OpenOrCreateFiles(false, had_index, out_entry_stat))
return net::ERR_FAILED;
-
for (int i = 0; i < kSimpleEntryFileCount; ++i) {
SimpleFileHeader header;
int header_read_result =
@@ -602,12 +631,19 @@ int SimpleSynchronousEntry::InitializeForOpen(bool had_index,
}
key_ = std::string(key.get(), header.key_length);
- out_entry_stat->data_size[i] =
- GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size[i]);
- if (out_entry_stat->data_size[i] < 0) {
- // This entry can't possibly be valid, as it does not have enough space to
- // store a valid SimpleFileEOF record.
- return net::ERR_FAILED;
+ if (i == 0) {
+ // File size for stream 0 has been stored temporarily in data_size[1].
+ int total_data_size =
+ GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size[1]);
+ int ret_value_stream_0 = ReadAndValidateStream0(
+ total_data_size, out_entry_stat, stream_0_data);
+ if (ret_value_stream_0 != net::OK)
+ return ret_value_stream_0;
+ } else {
+ out_entry_stat->data_size[2] =
+ GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size[2]);
+ if (out_entry_stat->data_size[2] < 0)
+ return net::ERR_FAILED;
}
if (base::Hash(key.get(), header.key_length) != header.key_hash) {
@@ -638,16 +674,18 @@ int SimpleSynchronousEntry::InitializeForCreate(
header.key_length = key_.size();
header.key_hash = base::Hash(key_);
- if (WritePlatformFile(files_[i], 0, reinterpret_cast<char*>(&header),
- sizeof(header)) != sizeof(header)) {
- DLOG(WARNING) << "Could not write headers to new cache entry.";
+ if (WritePlatformFile(
+ files_[i], 0, reinterpret_cast<char*>(&header), sizeof(header)) !=
+ sizeof(header)) {
+ DLOG(WARNING) << "Could not write cache file header to cache entry.";
RecordSyncCreateResult(
cache_type_, CREATE_ENTRY_CANT_WRITE_HEADER, had_index);
return net::ERR_FAILED;
}
- if (WritePlatformFile(files_[i], sizeof(header), key_.data(),
- key_.size()) != implicit_cast<int>(key_.size())) {
+ if (WritePlatformFile(
+ files_[i], sizeof(SimpleFileHeader), key_.data(), key_.size()) !=
+ implicit_cast<int>(key_.size())) {
DLOG(WARNING) << "Could not write keys to new cache entry.";
RecordSyncCreateResult(
cache_type_, CREATE_ENTRY_CANT_WRITE_KEY, had_index);
@@ -659,6 +697,88 @@ int SimpleSynchronousEntry::InitializeForCreate(
return net::OK;
}
+int SimpleSynchronousEntry::ReadAndValidateStream0(
+ int total_data_size,
+ SimpleEntryStat* out_entry_stat,
+ scoped_refptr<net::GrowableIOBuffer>* stream_0_data) const {
+ // Temporarily assign all the data size to stream 1 in order to read the
+ // EOF record for stream 0, which contains the size of stream 0.
+ out_entry_stat->data_size[0] = 0;
+ out_entry_stat->data_size[1] = total_data_size - sizeof(SimpleFileEOF);
+
+ bool has_crc32;
+ uint32 read_crc32;
+ int stream_0_size;
+ int ret_value_crc32 = GetEOFRecordData(
+ 0, *out_entry_stat, &has_crc32, &read_crc32, &stream_0_size);
+ if (ret_value_crc32 != net::OK)
+ return ret_value_crc32;
+
+ if (stream_0_size > out_entry_stat->data_size[1])
+ return net::ERR_FAILED;
+
+ // These are the real values of data size.
+ out_entry_stat->data_size[0] = stream_0_size;
+ out_entry_stat->data_size[1] -= stream_0_size;
+
+ // Put stream 0 data in memory.
+ *stream_0_data = NULL;
+ if (stream_0_size != 0) {
+ *stream_0_data = new net::GrowableIOBuffer();
+ (*stream_0_data)->SetCapacity(stream_0_size);
+ int file_offset = out_entry_stat->GetOffsetInFile(key_, 0, 0);
+ int bytes_read = ReadPlatformFile(
+ files_[0], file_offset, (*stream_0_data)->data(), stream_0_size);
+ if (bytes_read != stream_0_size)
+ return net::ERR_FAILED;
+ }
+
+ // Check the CRC32.
+ uint32 expected_crc32 =
+ stream_0_size == 0
+ ? crc32(0, Z_NULL, 0)
+ : crc32(crc32(0, Z_NULL, 0),
+ reinterpret_cast<const Bytef*>((*stream_0_data)->data()),
+ stream_0_size);
+ if (has_crc32 && read_crc32 != expected_crc32) {
+ DLOG(INFO) << "Eof record had bad crc.";
+ RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
+ return net::ERR_FAILED;
+ }
+ RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
+ return net::OK;
+}
+
+int SimpleSynchronousEntry::GetEOFRecordData(int index,
+ const SimpleEntryStat& entry_stat,
+ bool* out_has_crc32,
+ uint32* out_crc32,
+ int* out_data_size) const {
+ SimpleFileEOF eof_record;
+ int file_offset = entry_stat.GetEOFOffsetInFile(key_, index);
+ int file_index = GetFileIndexFromStreamIndex(index);
+ if (ReadPlatformFile(files_[file_index],
+ file_offset,
+ reinterpret_cast<char*>(&eof_record),
+ sizeof(eof_record)) != sizeof(eof_record)) {
+ RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE);
+ return net::ERR_CACHE_CHECKSUM_READ_FAILURE;
+ }
+
+ if (eof_record.final_magic_number != kSimpleFinalMagicNumber) {
+ RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH);
+ DLOG(INFO) << "Eof record had bad magic number.";
+ return net::ERR_CACHE_CHECKSUM_READ_FAILURE;
+ }
+
+ *out_has_crc32 = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) ==
+ SimpleFileEOF::FLAG_HAS_CRC32;
+ *out_crc32 = eof_record.data_crc32;
+ *out_data_size = eof_record.stream_size;
+ SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, *out_has_crc32);
+ return net::OK;
+}
+
void SimpleSynchronousEntry::Doom() const {
// TODO(gavinp): Consider if we should guard against redundant Doom() calls.
DeleteFilesForEntryHash(path_, entry_hash_);

Powered by Google App Engine
This is Rietveld 408576698