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

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

Issue 2090263004: **WIP** Simple Cache: reduce seeks on stream 0 read. Base URL: https://chromium.googlesource.com/chromium/src.git@simply-oom
Patch Set: rebase better Created 3 years, 4 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
« no previous file with comments | « net/disk_cache/simple/simple_synchronous_entry.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 cb9700211d977052eb75623fd41d4b8832d98e8b..9e2e6e9f433d8d90e2680b2a68a5edecaa804676 100644
--- a/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -9,6 +9,7 @@
#include <functional>
#include <limits>
+#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/files/file_util.h"
#include "base/hash.h"
@@ -1092,6 +1093,110 @@ bool SimpleSynchronousEntry::CheckHeaderAndKey(int file_index) {
return true;
}
+bool SimpleSynchronousEntry::ReadStream0Data(
+ SimpleEntryStat* out_entry_stat,
+ scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
+ uint32_t* out_stream_0_crc32) {
+ // How many bytes in the entry file are consumed by metadata.
+ const size_t header_overhead_bytes = sizeof(SimpleFileHeader) + key_.size();
+ size_t total_overhead_bytes = header_overhead_bytes + 2 * sizeof(SimpleFileEOF);
+
+ int32_t file_size = out_entry_stat->data_size(1);
+ if (static_cast<int>(total_overhead_bytes) > file_size)
+ return false;
+
+ // Initially make an aligned read of at least 32k (or read the entire file),
+ // which should be large enough to retrieve the stream 0 data and both EOF
+ // records.
+ std::vector<char> tail_data(std::min(file_size,
+ 8192 + file_size % 4096));
+ int bytes_read = files_[0].Read(file_size - tail_data.size(),
+ tail_data.data(), tail_data.size());
+ if (bytes_read != static_cast<int>(tail_data.size()))
+ return false;
+
+ const SimpleFileEOF* stream_0_eof = reinterpret_cast<const SimpleFileEOF*>(tail_data.data() + tail_data.size() - sizeof(SimpleFileEOF));
+
+ if (stream_0_eof->final_magic_number != kSimpleFinalMagicNumber)
+ return false;
+ if (!base::IsValueInRangeForNumericType<int32_t>(stream_0_eof->stream_size))
+ return false;
+ const int32_t stream_0_size = stream_0_eof->stream_size;
+
+ const bool has_key_sha256 = (stream_0_eof->flags & SimpleFileEOF::FLAG_HAS_KEY_SHA256) == SimpleFileEOF::FLAG_HAS_KEY_SHA256;
+ const bool has_crc32 = (stream_0_eof->flags & SimpleFileEOF::FLAG_HAS_CRC32) == SimpleFileEOF::FLAG_HAS_CRC32;
+ const uint32_t data_crc32 = stream_0_eof->data_crc32;
+ // Clear |stream_0_eof| because subsequent vector resize operations may invalidate it.
+ stream_0_eof = nullptr;
+
+ base::CheckedNumeric<size_t> tail_bytes_needed = 2 * sizeof(SimpleFileEOF);
+ if (has_key_sha256) {
+ total_overhead_bytes += sizeof(net::SHA256HashValue);
+ tail_bytes_needed += sizeof(net::SHA256HashValue);
+ }
+ if (stream_0_size > file_size - static_cast<int>(total_overhead_bytes))
+ return false;
+
+ tail_bytes_needed += stream_0_size;
+ if (!tail_bytes_needed.IsValid())
+ return false;
+ size_t safe_tail_bytes_needed = tail_bytes_needed.ValueOrDie();
+ if (safe_tail_bytes_needed > file_size - header_overhead_bytes)
+ return false;
+ if (safe_tail_bytes_needed > tail_data.size()) {
+ // The tail read was too short, we need to enlarge the buffer and read the extra
+ // data.
+ size_t missing_bytes = safe_tail_bytes_needed - tail_data.size();
+ if (!base::IsValueInRangeForNumericType<int>(missing_bytes))
+ return false;
+
+ LOG(INFO) << "doing a second read. Originally " << tail_data.size() << ", but need " << safe_tail_bytes_needed << ", so reading " << missing_bytes;
+ LOG(INFO) << "key length " << key_.size();
+ tail_data.resize(safe_tail_bytes_needed);
+ std::copy_backward(tail_data.begin(), tail_data.end() - missing_bytes,
+ tail_data.end());
+ if (files_[0].Read(file_size - safe_tail_bytes_needed,
+ tail_data.data(), missing_bytes) != static_cast<int>(missing_bytes)) {
+ return false;
+ }
+ }
+
+ // Calculate and set the real values for data size.
+ out_entry_stat->set_data_size(0, stream_0_size);
+ out_entry_stat->set_data_size(1, file_size - total_overhead_bytes - stream_0_size);
+
+ // Copy stream 0 data.
+ *stream_0_data = new net::GrowableIOBuffer();
+ (*stream_0_data)->SetCapacity(out_entry_stat->data_size(0));
+ std::copy_n(tail_data.end() - safe_tail_bytes_needed + sizeof(SimpleFileEOF),
+ stream_0_size, (*stream_0_data)->data());
+
+ // Check the CRC32.
+ uint32_t expected_crc32 = crc32(0, Z_NULL, 0);
+ if (stream_0_size != 0) {
+ expected_crc32 = crc32(expected_crc32,
+ reinterpret_cast<const Bytef*>((*stream_0_data)->data()),
+ stream_0_size);
+ }
+ if (has_crc32 && data_crc32 != expected_crc32) {
+ return false;
+ }
+ *out_stream_0_crc32 = expected_crc32;
+
+ if (has_key_sha256) {
+ net::SHA256HashValue hash_value;
+ CalculateSHA256OfKey(key_, &hash_value);
+ bool matched = std::memcmp(&hash_value, tail_data.data() + tail_data.size() - sizeof(SimpleFileEOF) - sizeof(hash_value), sizeof(hash_value)) == 0;
+ if (!matched) {
+ return false;
+ }
+ }
+
+ if (!has_key_sha256 && header_and_key_check_needed_[0])
+ CheckHeaderAndKey(0);
+ return true;
+}
+
int SimpleSynchronousEntry::InitializeForOpen(
SimpleEntryStat* out_entry_stat,
scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
@@ -1122,12 +1227,17 @@ int SimpleSynchronousEntry::InitializeForOpen(
}
if (i == 0) {
- // File size for stream 0 has been stored temporarily in data_size[1].
- int ret_value_stream_0 =
- ReadAndValidateStream0(out_entry_stat->data_size(1), out_entry_stat,
- stream_0_data, out_stream_0_crc32);
- if (ret_value_stream_0 != net::OK)
- return ret_value_stream_0;
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch("backseek")) {
+ if (!ReadStream0Data(out_entry_stat, stream_0_data, out_stream_0_crc32))
+ return net::ERR_FAILED;
+ } else {
+ // File size for stream 0 has been stored temporarily in data_size[1].
+ int ret_value_stream_0 =
+ ReadAndValidateStream0(out_entry_stat->data_size(1), out_entry_stat,
+ stream_0_data, out_stream_0_crc32);
+ if (ret_value_stream_0 != net::OK)
+ return ret_value_stream_0;
+ }
} else {
out_entry_stat->set_data_size(
2,
« no previous file with comments | « net/disk_cache/simple/simple_synchronous_entry.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698