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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « net/disk_cache/simple/simple_synchronous_entry.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/disk_cache/simple/simple_synchronous_entry.h" 5 #include "net/disk_cache/simple/simple_synchronous_entry.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cstring> 8 #include <cstring>
9 #include <functional> 9 #include <functional>
10 #include <limits> 10 #include <limits>
11 11
12 #include "base/command_line.h"
12 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
13 #include "base/files/file_util.h" 14 #include "base/files/file_util.h"
14 #include "base/hash.h" 15 #include "base/hash.h"
15 #include "base/location.h" 16 #include "base/location.h"
16 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.h"
17 #include "base/numerics/safe_conversions.h" 18 #include "base/numerics/safe_conversions.h"
18 #include "base/sha1.h" 19 #include "base/sha1.h"
19 #include "base/timer/elapsed_timer.h" 20 #include "base/timer/elapsed_timer.h"
20 #include "crypto/secure_hash.h" 21 #include "crypto/secure_hash.h"
21 #include "net/base/hash_value.h" 22 #include "net/base/hash_value.h"
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 if (key_ != key_from_header) { 1086 if (key_ != key_from_header) {
1086 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_KEY_MISMATCH, had_index_); 1087 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_KEY_MISMATCH, had_index_);
1087 return false; 1088 return false;
1088 } 1089 }
1089 } 1090 }
1090 1091
1091 header_and_key_check_needed_[file_index] = false; 1092 header_and_key_check_needed_[file_index] = false;
1092 return true; 1093 return true;
1093 } 1094 }
1094 1095
1096 bool SimpleSynchronousEntry::ReadStream0Data(
1097 SimpleEntryStat* out_entry_stat,
1098 scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
1099 uint32_t* out_stream_0_crc32) {
1100 // How many bytes in the entry file are consumed by metadata.
1101 const size_t header_overhead_bytes = sizeof(SimpleFileHeader) + key_.size();
1102 size_t total_overhead_bytes = header_overhead_bytes + 2 * sizeof(SimpleFileEOF );
1103
1104 int32_t file_size = out_entry_stat->data_size(1);
1105 if (static_cast<int>(total_overhead_bytes) > file_size)
1106 return false;
1107
1108 // Initially make an aligned read of at least 32k (or read the entire file),
1109 // which should be large enough to retrieve the stream 0 data and both EOF
1110 // records.
1111 std::vector<char> tail_data(std::min(file_size,
1112 8192 + file_size % 4096));
1113 int bytes_read = files_[0].Read(file_size - tail_data.size(),
1114 tail_data.data(), tail_data.size());
1115 if (bytes_read != static_cast<int>(tail_data.size()))
1116 return false;
1117
1118 const SimpleFileEOF* stream_0_eof = reinterpret_cast<const SimpleFileEOF*>(tai l_data.data() + tail_data.size() - sizeof(SimpleFileEOF));
1119
1120 if (stream_0_eof->final_magic_number != kSimpleFinalMagicNumber)
1121 return false;
1122 if (!base::IsValueInRangeForNumericType<int32_t>(stream_0_eof->stream_size))
1123 return false;
1124 const int32_t stream_0_size = stream_0_eof->stream_size;
1125
1126 const bool has_key_sha256 = (stream_0_eof->flags & SimpleFileEOF::FLAG_HAS_KEY _SHA256) == SimpleFileEOF::FLAG_HAS_KEY_SHA256;
1127 const bool has_crc32 = (stream_0_eof->flags & SimpleFileEOF::FLAG_HAS_CRC32) = = SimpleFileEOF::FLAG_HAS_CRC32;
1128 const uint32_t data_crc32 = stream_0_eof->data_crc32;
1129 // Clear |stream_0_eof| because subsequent vector resize operations may invali date it.
1130 stream_0_eof = nullptr;
1131
1132 base::CheckedNumeric<size_t> tail_bytes_needed = 2 * sizeof(SimpleFileEOF);
1133 if (has_key_sha256) {
1134 total_overhead_bytes += sizeof(net::SHA256HashValue);
1135 tail_bytes_needed += sizeof(net::SHA256HashValue);
1136 }
1137 if (stream_0_size > file_size - static_cast<int>(total_overhead_bytes))
1138 return false;
1139
1140 tail_bytes_needed += stream_0_size;
1141 if (!tail_bytes_needed.IsValid())
1142 return false;
1143 size_t safe_tail_bytes_needed = tail_bytes_needed.ValueOrDie();
1144 if (safe_tail_bytes_needed > file_size - header_overhead_bytes)
1145 return false;
1146 if (safe_tail_bytes_needed > tail_data.size()) {
1147 // The tail read was too short, we need to enlarge the buffer and read the e xtra
1148 // data.
1149 size_t missing_bytes = safe_tail_bytes_needed - tail_data.size();
1150 if (!base::IsValueInRangeForNumericType<int>(missing_bytes))
1151 return false;
1152
1153 LOG(INFO) << "doing a second read. Originally " << tail_data.size() << ", bu t need " << safe_tail_bytes_needed << ", so reading " << missing_bytes;
1154 LOG(INFO) << "key length " << key_.size();
1155 tail_data.resize(safe_tail_bytes_needed);
1156 std::copy_backward(tail_data.begin(), tail_data.end() - missing_bytes,
1157 tail_data.end());
1158 if (files_[0].Read(file_size - safe_tail_bytes_needed,
1159 tail_data.data(), missing_bytes) != static_cast<int>(miss ing_bytes)) {
1160 return false;
1161 }
1162 }
1163
1164 // Calculate and set the real values for data size.
1165 out_entry_stat->set_data_size(0, stream_0_size);
1166 out_entry_stat->set_data_size(1, file_size - total_overhead_bytes - stream_0_s ize);
1167
1168 // Copy stream 0 data.
1169 *stream_0_data = new net::GrowableIOBuffer();
1170 (*stream_0_data)->SetCapacity(out_entry_stat->data_size(0));
1171 std::copy_n(tail_data.end() - safe_tail_bytes_needed + sizeof(SimpleFileEOF),
1172 stream_0_size, (*stream_0_data)->data());
1173
1174 // Check the CRC32.
1175 uint32_t expected_crc32 = crc32(0, Z_NULL, 0);
1176 if (stream_0_size != 0) {
1177 expected_crc32 = crc32(expected_crc32,
1178 reinterpret_cast<const Bytef*>((*stream_0_data)->data ()),
1179 stream_0_size);
1180 }
1181 if (has_crc32 && data_crc32 != expected_crc32) {
1182 return false;
1183 }
1184 *out_stream_0_crc32 = expected_crc32;
1185
1186 if (has_key_sha256) {
1187 net::SHA256HashValue hash_value;
1188 CalculateSHA256OfKey(key_, &hash_value);
1189 bool matched = std::memcmp(&hash_value, tail_data.data() + tail_data.size() - sizeof(SimpleFileEOF) - sizeof(hash_value), sizeof(hash_value)) == 0;
1190 if (!matched) {
1191 return false;
1192 }
1193 }
1194
1195 if (!has_key_sha256 && header_and_key_check_needed_[0])
1196 CheckHeaderAndKey(0);
1197 return true;
1198 }
1199
1095 int SimpleSynchronousEntry::InitializeForOpen( 1200 int SimpleSynchronousEntry::InitializeForOpen(
1096 SimpleEntryStat* out_entry_stat, 1201 SimpleEntryStat* out_entry_stat,
1097 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, 1202 scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
1098 uint32_t* out_stream_0_crc32) { 1203 uint32_t* out_stream_0_crc32) {
1099 DCHECK(!initialized_); 1204 DCHECK(!initialized_);
1100 if (!OpenFiles(out_entry_stat)) { 1205 if (!OpenFiles(out_entry_stat)) {
1101 DLOG(WARNING) << "Could not open platform files for entry."; 1206 DLOG(WARNING) << "Could not open platform files for entry.";
1102 return net::ERR_FAILED; 1207 return net::ERR_FAILED;
1103 } 1208 }
1104 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 1209 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
(...skipping 10 matching lines...) Expand all
1115 } else { 1220 } else {
1116 // If we do know which key were are looking for, we still need to 1221 // If we do know which key were are looking for, we still need to
1117 // check that the file actually has it (rather than just being a hash 1222 // check that the file actually has it (rather than just being a hash
1118 // collision or some sort of file system accident), but that can be put 1223 // collision or some sort of file system accident), but that can be put
1119 // off until opportune time: either the read of the footer, or when we 1224 // off until opportune time: either the read of the footer, or when we
1120 // start reading in the data, depending on stream # and format revision. 1225 // start reading in the data, depending on stream # and format revision.
1121 header_and_key_check_needed_[i] = true; 1226 header_and_key_check_needed_[i] = true;
1122 } 1227 }
1123 1228
1124 if (i == 0) { 1229 if (i == 0) {
1125 // File size for stream 0 has been stored temporarily in data_size[1]. 1230 if (base::CommandLine::ForCurrentProcess()->HasSwitch("backseek")) {
1126 int ret_value_stream_0 = 1231 if (!ReadStream0Data(out_entry_stat, stream_0_data, out_stream_0_crc32))
1127 ReadAndValidateStream0(out_entry_stat->data_size(1), out_entry_stat, 1232 return net::ERR_FAILED;
1128 stream_0_data, out_stream_0_crc32); 1233 } else {
1129 if (ret_value_stream_0 != net::OK) 1234 // File size for stream 0 has been stored temporarily in data_size[1].
1130 return ret_value_stream_0; 1235 int ret_value_stream_0 =
1236 ReadAndValidateStream0(out_entry_stat->data_size(1), out_entry_stat,
1237 stream_0_data, out_stream_0_crc32);
1238 if (ret_value_stream_0 != net::OK)
1239 return ret_value_stream_0;
1240 }
1131 } else { 1241 } else {
1132 out_entry_stat->set_data_size( 1242 out_entry_stat->set_data_size(
1133 2, 1243 2,
1134 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(2))); 1244 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(2)));
1135 if (out_entry_stat->data_size(2) < 0) { 1245 if (out_entry_stat->data_size(2) < 0) {
1136 DLOG(WARNING) << "Stream 2 file is too small."; 1246 DLOG(WARNING) << "Stream 2 file is too small.";
1137 return net::ERR_FAILED; 1247 return net::ERR_FAILED;
1138 } 1248 }
1139 } 1249 }
1140 } 1250 }
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
1641 range.offset = offset; 1751 range.offset = offset;
1642 range.length = len; 1752 range.length = len;
1643 range.data_crc32 = data_crc32; 1753 range.data_crc32 = data_crc32;
1644 range.file_offset = data_file_offset; 1754 range.file_offset = data_file_offset;
1645 sparse_ranges_.insert(std::make_pair(offset, range)); 1755 sparse_ranges_.insert(std::make_pair(offset, range));
1646 1756
1647 return true; 1757 return true;
1648 } 1758 }
1649 1759
1650 } // namespace disk_cache 1760 } // namespace disk_cache
OLDNEW
« 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