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

Side by Side Diff: net/disk_cache/simple/simple_synchronous_entry.cc

Issue 2874833005: SimpleCache: read small files all at once. (Closed)
Patch Set: Group and array up data + crc to cut down on code dupe and excessive arg counts. 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
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/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/files/file_util.h" 13 #include "base/files/file_util.h"
14 #include "base/hash.h" 14 #include "base/hash.h"
15 #include "base/location.h" 15 #include "base/location.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/metrics/field_trial_params.h"
16 #include "base/metrics/histogram_macros.h" 18 #include "base/metrics/histogram_macros.h"
17 #include "base/numerics/safe_conversions.h" 19 #include "base/numerics/safe_conversions.h"
18 #include "base/sha1.h" 20 #include "base/sha1.h"
21 #include "base/strings/string_piece.h"
19 #include "base/timer/elapsed_timer.h" 22 #include "base/timer/elapsed_timer.h"
20 #include "crypto/secure_hash.h" 23 #include "crypto/secure_hash.h"
21 #include "net/base/hash_value.h" 24 #include "net/base/hash_value.h"
22 #include "net/base/io_buffer.h" 25 #include "net/base/io_buffer.h"
23 #include "net/base/net_errors.h" 26 #include "net/base/net_errors.h"
24 #include "net/disk_cache/simple/simple_backend_version.h" 27 #include "net/disk_cache/simple/simple_backend_version.h"
28 #include "net/disk_cache/simple/simple_experiment.h"
25 #include "net/disk_cache/simple/simple_histogram_macros.h" 29 #include "net/disk_cache/simple/simple_histogram_macros.h"
26 #include "net/disk_cache/simple/simple_util.h" 30 #include "net/disk_cache/simple/simple_util.h"
27 #include "third_party/zlib/zlib.h" 31 #include "third_party/zlib/zlib.h"
28 32
29 using base::File; 33 using base::File;
30 using base::FilePath; 34 using base::FilePath;
31 using base::Time; 35 using base::Time;
32 36
33 namespace { 37 namespace {
34 38
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 SIMPLE_CACHE_UMA(ENUMERATION, 115 SIMPLE_CACHE_UMA(ENUMERATION,
112 "SyncCloseResult", cache_type, result, CLOSE_RESULT_MAX); 116 "SyncCloseResult", cache_type, result, CLOSE_RESULT_MAX);
113 } 117 }
114 118
115 void RecordKeySHA256Result(net::CacheType cache_type, KeySHA256Result result) { 119 void RecordKeySHA256Result(net::CacheType cache_type, KeySHA256Result result) {
116 SIMPLE_CACHE_UMA(ENUMERATION, "SyncKeySHA256Result", cache_type, 120 SIMPLE_CACHE_UMA(ENUMERATION, "SyncKeySHA256Result", cache_type,
117 static_cast<int>(result), 121 static_cast<int>(result),
118 static_cast<int>(KeySHA256Result::MAX)); 122 static_cast<int>(KeySHA256Result::MAX));
119 } 123 }
120 124
125 void RecordWhetherOpenDidPrefetch(net::CacheType cache_type, bool result) {
126 SIMPLE_CACHE_UMA(BOOLEAN, "SyncOpenDidPrefetch", cache_type, result);
127 }
128
121 bool CanOmitEmptyFile(int file_index) { 129 bool CanOmitEmptyFile(int file_index) {
122 DCHECK_GE(file_index, 0); 130 DCHECK_GE(file_index, 0);
123 DCHECK_LT(file_index, disk_cache::kSimpleEntryFileCount); 131 DCHECK_LT(file_index, disk_cache::kSimpleEntryFileCount);
124 return file_index == disk_cache::simple_util::GetFileIndexFromStreamIndex(2); 132 return file_index == disk_cache::simple_util::GetFileIndexFromStreamIndex(2);
125 } 133 }
126 134
127 bool TruncatePath(const FilePath& filename_to_truncate) { 135 bool TruncatePath(const FilePath& filename_to_truncate) {
128 File file_to_truncate; 136 File file_to_truncate;
129 int flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE | 137 int flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE |
130 File::FLAG_SHARE_DELETE; 138 File::FLAG_SHARE_DELETE;
(...skipping 18 matching lines...) Expand all
149 namespace disk_cache { 157 namespace disk_cache {
150 158
151 using simple_util::GetEntryHashKey; 159 using simple_util::GetEntryHashKey;
152 using simple_util::GetFilenameFromEntryHashAndFileIndex; 160 using simple_util::GetFilenameFromEntryHashAndFileIndex;
153 using simple_util::GetSparseFilenameFromEntryHash; 161 using simple_util::GetSparseFilenameFromEntryHash;
154 using simple_util::GetHeaderSize; 162 using simple_util::GetHeaderSize;
155 using simple_util::GetDataSizeFromFileSize; 163 using simple_util::GetDataSizeFromFileSize;
156 using simple_util::GetFileSizeFromDataSize; 164 using simple_util::GetFileSizeFromDataSize;
157 using simple_util::GetFileIndexFromStreamIndex; 165 using simple_util::GetFileIndexFromStreamIndex;
158 166
167 const base::Feature kSimpleCachePrefetchExperiment = {
168 "GetSimpleCachePrefetchExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
169 const char kSimplePrefetchBytesParam[] = "Bytes";
170
171 int GetSimpleCachePrefetchSize() {
172 return base::GetFieldTrialParamByFeatureAsInt(kSimpleCachePrefetchExperiment,
173 kSimplePrefetchBytesParam, 0);
174 }
175
159 SimpleEntryStat::SimpleEntryStat(base::Time last_used, 176 SimpleEntryStat::SimpleEntryStat(base::Time last_used,
160 base::Time last_modified, 177 base::Time last_modified,
161 const int32_t data_size[], 178 const int32_t data_size[],
162 const int32_t sparse_data_size) 179 const int32_t sparse_data_size)
163 : last_used_(last_used), 180 : last_used_(last_used),
164 last_modified_(last_modified), 181 last_modified_(last_modified),
165 sparse_data_size_(sparse_data_size) { 182 sparse_data_size_(sparse_data_size) {
166 memcpy(data_size_, data_size, sizeof(data_size_)); 183 memcpy(data_size_, data_size, sizeof(data_size_));
167 } 184 }
168 185
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 int32_t total_data_size; 218 int32_t total_data_size;
202 if (file_index == 0) { 219 if (file_index == 0) {
203 total_data_size = data_size_[0] + data_size_[1] + 220 total_data_size = data_size_[0] + data_size_[1] +
204 sizeof(net::SHA256HashValue) + sizeof(SimpleFileEOF); 221 sizeof(net::SHA256HashValue) + sizeof(SimpleFileEOF);
205 } else { 222 } else {
206 total_data_size = data_size_[2]; 223 total_data_size = data_size_[2];
207 } 224 }
208 return GetFileSizeFromDataSize(key_length, total_data_size); 225 return GetFileSizeFromDataSize(key_length, total_data_size);
209 } 226 }
210 227
228 SimpleStreamPrefetchData::SimpleStreamPrefetchData()
229 : stream_crc32(crc32(0, Z_NULL, 0)) {}
230
231 SimpleStreamPrefetchData::~SimpleStreamPrefetchData() {}
232
211 SimpleEntryCreationResults::SimpleEntryCreationResults( 233 SimpleEntryCreationResults::SimpleEntryCreationResults(
212 SimpleEntryStat entry_stat) 234 SimpleEntryStat entry_stat)
213 : sync_entry(NULL), 235 : sync_entry(NULL), entry_stat(entry_stat), result(net::OK) {}
214 entry_stat(entry_stat),
215 stream_0_crc32(crc32(0, Z_NULL, 0)),
216 result(net::OK) {
217 }
218 236
219 SimpleEntryCreationResults::~SimpleEntryCreationResults() { 237 SimpleEntryCreationResults::~SimpleEntryCreationResults() {
220 } 238 }
221 239
222 SimpleSynchronousEntry::CRCRecord::CRCRecord() : index(-1), 240 SimpleSynchronousEntry::CRCRecord::CRCRecord() : index(-1),
223 has_crc32(false), 241 has_crc32(false),
224 data_crc32(0) { 242 data_crc32(0) {
225 } 243 }
226 244
227 SimpleSynchronousEntry::CRCRecord::CRCRecord(int index_p, 245 SimpleSynchronousEntry::CRCRecord::CRCRecord(int index_p,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 const bool had_index, 279 const bool had_index,
262 const base::TimeTicks& time_enqueued, 280 const base::TimeTicks& time_enqueued,
263 SimpleEntryCreationResults* out_results) { 281 SimpleEntryCreationResults* out_results) {
264 base::TimeTicks start_sync_open_entry = base::TimeTicks::Now(); 282 base::TimeTicks start_sync_open_entry = base::TimeTicks::Now();
265 SIMPLE_CACHE_UMA(TIMES, "QueueLatency.OpenEntry", cache_type, 283 SIMPLE_CACHE_UMA(TIMES, "QueueLatency.OpenEntry", cache_type,
266 (start_sync_open_entry - time_enqueued)); 284 (start_sync_open_entry - time_enqueued));
267 285
268 SimpleSynchronousEntry* sync_entry = 286 SimpleSynchronousEntry* sync_entry =
269 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index); 287 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index);
270 out_results->result = sync_entry->InitializeForOpen( 288 out_results->result = sync_entry->InitializeForOpen(
271 &out_results->entry_stat, &out_results->stream_0_data, 289 &out_results->entry_stat, out_results->stream_prefetch_data);
272 &out_results->stream_0_crc32);
273 if (out_results->result != net::OK) { 290 if (out_results->result != net::OK) {
274 sync_entry->Doom(); 291 sync_entry->Doom();
275 delete sync_entry; 292 delete sync_entry;
276 out_results->sync_entry = NULL; 293 out_results->sync_entry = NULL;
277 out_results->stream_0_data = NULL; 294 out_results->stream_prefetch_data[0].data = nullptr;
295 out_results->stream_prefetch_data[1].data = nullptr;
278 return; 296 return;
279 } 297 }
280 SIMPLE_CACHE_UMA(TIMES, "DiskOpenLatency", cache_type, 298 SIMPLE_CACHE_UMA(TIMES, "DiskOpenLatency", cache_type,
281 base::TimeTicks::Now() - start_sync_open_entry); 299 base::TimeTicks::Now() - start_sync_open_entry);
282 out_results->sync_entry = sync_entry; 300 out_results->sync_entry = sync_entry;
283 } 301 }
284 302
285 // static 303 // static
286 void SimpleSynchronousEntry::CreateEntry( 304 void SimpleSynchronousEntry::CreateEntry(
287 net::CacheType cache_type, 305 net::CacheType cache_type,
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 it->second.offset == start + avail_so_far) { 700 it->second.offset == start + avail_so_far) {
683 avail_so_far += it->second.length; 701 avail_so_far += it->second.length;
684 ++it; 702 ++it;
685 } 703 }
686 704
687 int64_t len_from_start = len - (start - offset); 705 int64_t len_from_start = len - (start - offset);
688 *out_start = start; 706 *out_start = start;
689 *out_result = static_cast<int>(std::min(avail_so_far, len_from_start)); 707 *out_result = static_cast<int>(std::min(avail_so_far, len_from_start));
690 } 708 }
691 709
692 int SimpleSynchronousEntry::CheckEOFRecord(int index, 710 int SimpleSynchronousEntry::CheckEOFRecord(int stream_index,
693 const SimpleEntryStat& entry_stat, 711 const SimpleEntryStat& entry_stat,
694 uint32_t expected_crc32) const { 712 uint32_t expected_crc32) {
695 DCHECK(initialized_); 713 DCHECK(initialized_);
696 uint32_t crc32; 714 SimpleFileEOF eof_record;
697 bool has_crc32; 715 int rv = GetEOFRecordData(base::StringPiece(), stream_index, entry_stat,
pasko 2017/08/04 01:28:34 base::StringPiece is one of those rare classes tha
Maks Orlovich 2017/08/04 18:35:44 I prefer the explicit construction since it increa
pasko 2017/08/09 12:28:21 OK, makes sense. I am not sure I fully understand
Maks Orlovich 2017/08/09 15:25:01 Yeah, bundles up the pointer and length together,
698 bool has_key_sha256; 716 &eof_record);
699 int32_t stream_size; 717
700 int rv = GetEOFRecordData(index, entry_stat, &has_crc32, &has_key_sha256,
701 &crc32, &stream_size);
702 if (rv != net::OK) { 718 if (rv != net::OK) {
703 Doom(); 719 Doom();
704 return rv; 720 return rv;
705 } 721 }
706 if (has_crc32 && crc32 != expected_crc32) { 722 if ((eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) &&
723 eof_record.data_crc32 != expected_crc32) {
707 DVLOG(1) << "EOF record had bad crc."; 724 DVLOG(1) << "EOF record had bad crc.";
708 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); 725 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
709 Doom(); 726 Doom();
710 return net::ERR_CACHE_CHECKSUM_MISMATCH; 727 return net::ERR_CACHE_CHECKSUM_MISMATCH;
711 } 728 }
712 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); 729 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
713 return net::OK; 730 return net::OK;
714 } 731 }
715 732
733 int SimpleSynchronousEntry::PreReadStreamPayload(
734 base::StringPiece file_0_prefetch,
735 int stream_index,
736 int extra_size,
737 const SimpleEntryStat& entry_stat,
738 const SimpleFileEOF& eof_record,
739 scoped_refptr<net::GrowableIOBuffer>* stream_data,
740 uint32_t* out_crc32) {
741 DCHECK(stream_index == 0 || stream_index == 1);
742
743 int stream_size = entry_stat.data_size(stream_index);
744 int read_size = stream_size + extra_size;
745 *stream_data = new net::GrowableIOBuffer();
746 (*stream_data)->SetCapacity(read_size);
747 int file_offset = entry_stat.GetOffsetInFile(key_.size(), 0, stream_index);
748 if (!ReadFromFileOrPrefetched(file_0_prefetch, 0, file_offset, read_size,
749 (*stream_data)->data()))
750 return net::ERR_FAILED;
751
752 // Check the CRC32.
753 uint32_t expected_crc32 =
754 simple_util::Crc32((*stream_data)->data(), stream_size);
755 if ((eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) &&
756 eof_record.data_crc32 != expected_crc32) {
757 DVLOG(1) << "EOF record had bad crc.";
758 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
759 return net::ERR_CACHE_CHECKSUM_MISMATCH;
760 }
761 *out_crc32 = expected_crc32;
762 return net::OK;
763 }
764
716 void SimpleSynchronousEntry::Close( 765 void SimpleSynchronousEntry::Close(
717 const SimpleEntryStat& entry_stat, 766 const SimpleEntryStat& entry_stat,
718 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write, 767 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write,
719 net::GrowableIOBuffer* stream_0_data) { 768 net::GrowableIOBuffer* stream_0_data) {
720 base::ElapsedTimer close_time; 769 base::ElapsedTimer close_time;
721 DCHECK(stream_0_data); 770 DCHECK(stream_0_data);
722 771
723 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); 772 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin();
724 it != crc32s_to_write->end(); ++it) { 773 it != crc32s_to_write->end(); ++it) {
725 const int stream_index = it->index; 774 const int stream_index = it->index;
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 // 2) Stream 0 and stream 1 are in the same file, and the exact size for 992 // 2) Stream 0 and stream 1 are in the same file, and the exact size for
944 // each will only be known when reading the EOF record for stream 0. 993 // each will only be known when reading the EOF record for stream 0.
945 // 994 //
946 // The size for file 0 and 1 is temporarily kept in 995 // The size for file 0 and 1 is temporarily kept in
947 // |data_size(1)| and |data_size(2)| respectively. Reading the key in 996 // |data_size(1)| and |data_size(2)| respectively. Reading the key in
948 // InitializeForOpen yields the data size for each file. In the case of 997 // InitializeForOpen yields the data size for each file. In the case of
949 // file hash_1, this is the total size of stream 2, and is assigned to 998 // file hash_1, this is the total size of stream 2, and is assigned to
950 // data_size(2). In the case of file 0, it is the combined size of stream 999 // data_size(2). In the case of file 0, it is the combined size of stream
951 // 0, stream 1 and one EOF record. The exact distribution of sizes between 1000 // 0, stream 1 and one EOF record. The exact distribution of sizes between
952 // stream 1 and stream 0 is only determined after reading the EOF record 1001 // stream 1 and stream 0 is only determined after reading the EOF record
953 // for stream 0 in ReadAndValidateStream0. 1002 // for stream 0 in ReadAndValidateStream0AndMaybe1.
954 if (!base::IsValueInRangeForNumericType<int>(file_info.size)) { 1003 if (!base::IsValueInRangeForNumericType<int>(file_info.size)) {
955 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_INVALID_FILE_LENGTH, 1004 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_INVALID_FILE_LENGTH,
956 had_index_); 1005 had_index_);
957 return false; 1006 return false;
958 } 1007 }
959 out_entry_stat->set_data_size(i + 1, static_cast<int>(file_info.size)); 1008 out_entry_stat->set_data_size(i + 1, static_cast<int>(file_info.size));
960 } 1009 }
961 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, 1010 SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
962 "SyncOpenEntryAge", cache_type_, 1011 "SyncOpenEntryAge", cache_type_,
963 entry_age.InHours(), 1, 1000, 50); 1012 entry_age.InHours(), 1, 1000, 50);
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 return false; 1136 return false;
1088 } 1137 }
1089 } 1138 }
1090 1139
1091 header_and_key_check_needed_[file_index] = false; 1140 header_and_key_check_needed_[file_index] = false;
1092 return true; 1141 return true;
1093 } 1142 }
1094 1143
1095 int SimpleSynchronousEntry::InitializeForOpen( 1144 int SimpleSynchronousEntry::InitializeForOpen(
1096 SimpleEntryStat* out_entry_stat, 1145 SimpleEntryStat* out_entry_stat,
1097 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, 1146 SimpleStreamPrefetchData* stream_prefetch_data) {
1098 uint32_t* out_stream_0_crc32) {
1099 DCHECK(!initialized_); 1147 DCHECK(!initialized_);
1100 if (!OpenFiles(out_entry_stat)) { 1148 if (!OpenFiles(out_entry_stat)) {
1101 DLOG(WARNING) << "Could not open platform files for entry."; 1149 DLOG(WARNING) << "Could not open platform files for entry.";
1102 return net::ERR_FAILED; 1150 return net::ERR_FAILED;
1103 } 1151 }
1104 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 1152 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
1105 if (empty_file_omitted_[i]) 1153 if (empty_file_omitted_[i])
1106 continue; 1154 continue;
1107 1155
1108 if (key_.empty()) { 1156 if (key_.empty()) {
1109 // If |key_| is empty, we were opened via the iterator interface, without 1157 // If |key_| is empty, we were opened via the iterator interface, without
1110 // knowing what our key is. We must therefore read the header immediately 1158 // knowing what our key is. We must therefore read the header immediately
1111 // to discover it, so SimpleEntryImpl can make it available to 1159 // to discover it, so SimpleEntryImpl can make it available to
1112 // disk_cache::Entry::GetKey(). 1160 // disk_cache::Entry::GetKey().
1113 if (!CheckHeaderAndKey(i)) 1161 if (!CheckHeaderAndKey(i))
1114 return net::ERR_FAILED; 1162 return net::ERR_FAILED;
1115 } else { 1163 } else {
1116 // If we do know which key were are looking for, we still need to 1164 // 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 1165 // 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 1166 // 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 1167 // 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. 1168 // start reading in the data, depending on stream # and format revision.
1121 header_and_key_check_needed_[i] = true; 1169 header_and_key_check_needed_[i] = true;
1122 } 1170 }
1123 1171
1124 if (i == 0) { 1172 if (i == 0) {
1125 // File size for stream 0 has been stored temporarily in data_size[1]. 1173 // File size for stream 0 has been stored temporarily in data_size[1].
1126 int ret_value_stream_0 = 1174 int ret_value_stream_0 = ReadAndValidateStream0AndMaybe1(
1127 ReadAndValidateStream0(out_entry_stat->data_size(1), out_entry_stat, 1175 out_entry_stat->data_size(1), out_entry_stat, stream_prefetch_data);
1128 stream_0_data, out_stream_0_crc32);
1129 if (ret_value_stream_0 != net::OK) 1176 if (ret_value_stream_0 != net::OK)
1130 return ret_value_stream_0; 1177 return ret_value_stream_0;
1131 } else { 1178 } else {
1132 out_entry_stat->set_data_size( 1179 out_entry_stat->set_data_size(
1133 2, 1180 2,
1134 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(2))); 1181 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(2)));
1135 if (out_entry_stat->data_size(2) < 0) { 1182 if (out_entry_stat->data_size(2) < 0) {
1136 DLOG(WARNING) << "Stream 2 file is too small."; 1183 DLOG(WARNING) << "Stream 2 file is too small.";
1137 return net::ERR_FAILED; 1184 return net::ERR_FAILED;
1138 } 1185 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 if (!InitializeCreatedFile(i, &result)) { 1256 if (!InitializeCreatedFile(i, &result)) {
1210 RecordSyncCreateResult(result, had_index_); 1257 RecordSyncCreateResult(result, had_index_);
1211 return net::ERR_FAILED; 1258 return net::ERR_FAILED;
1212 } 1259 }
1213 } 1260 }
1214 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index_); 1261 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index_);
1215 initialized_ = true; 1262 initialized_ = true;
1216 return net::OK; 1263 return net::OK;
1217 } 1264 }
1218 1265
1219 int SimpleSynchronousEntry::ReadAndValidateStream0( 1266 int SimpleSynchronousEntry::ReadAndValidateStream0AndMaybe1(
1220 int file_size, 1267 int file_size,
1221 SimpleEntryStat* out_entry_stat, 1268 SimpleEntryStat* out_entry_stat,
1222 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, 1269 SimpleStreamPrefetchData* stream_prefetch_data) {
1223 uint32_t* out_stream_0_crc32) { 1270 // If the file is sufficiently small, we will prefetch everything --
1271 // in which case |prefetch_buf| will be non-null, and we should look at it
1272 // rather than call ::Read for the bits.
1273 std::unique_ptr<char[]> prefetch_buf;
1274 base::StringPiece file_0_prefetch;
1275
1276 if (file_size > GetSimpleCachePrefetchSize()) {
1277 RecordWhetherOpenDidPrefetch(cache_type_, false);
1278 } else {
1279 RecordWhetherOpenDidPrefetch(cache_type_, true);
1280 prefetch_buf = base::MakeUnique<char[]>(file_size);
1281 if (files_[0].Read(0, prefetch_buf.get(), file_size) != file_size)
1282 return net::ERR_FAILED;
1283 file_0_prefetch.set(prefetch_buf.get(), file_size);
1284 }
1285
1224 // Pretend this file has a null stream zero, and contains the optional key 1286 // Pretend this file has a null stream zero, and contains the optional key
1225 // SHA256. This is good enough to read the EOF record on the file, which gives 1287 // SHA256. This is good enough to read the EOF record on the file, which gives
1226 // the actual size of stream 0. 1288 // the actual size of stream 0.
1227 int temp_data_size = GetDataSizeFromFileSize(key_.size(), file_size); 1289 int temp_data_size = GetDataSizeFromFileSize(key_.size(), file_size);
1228 out_entry_stat->set_data_size(0, 0); 1290 out_entry_stat->set_data_size(0, 0);
1229 out_entry_stat->set_data_size( 1291 out_entry_stat->set_data_size(
1230 1, temp_data_size - sizeof(net::SHA256HashValue) - sizeof(SimpleFileEOF)); 1292 1, temp_data_size - sizeof(net::SHA256HashValue) - sizeof(SimpleFileEOF));
1231 1293
1232 bool has_crc32; 1294 SimpleFileEOF stream_0_eof;
1233 bool has_key_sha256; 1295 int rv = GetEOFRecordData(file_0_prefetch, 0, *out_entry_stat, &stream_0_eof);
1234 uint32_t read_crc32; 1296 if (rv != net::OK)
1235 int32_t stream_0_size; 1297 return rv;
1236 int ret_value_crc32 = 1298
1237 GetEOFRecordData(0, *out_entry_stat, &has_crc32, &has_key_sha256, 1299 bool has_key_sha256 =
1238 &read_crc32, &stream_0_size); 1300 (stream_0_eof.flags & SimpleFileEOF::FLAG_HAS_KEY_SHA256) ==
1239 if (ret_value_crc32 != net::OK) 1301 SimpleFileEOF::FLAG_HAS_KEY_SHA256;
1240 return ret_value_crc32; 1302 int32_t stream_0_size = stream_0_eof.stream_size;
1241 1303
1242 // Calculate and set the real values for the two streams. 1304 // Calculate and set the real values for the two streams.
1243 int32_t total_size = out_entry_stat->data_size(1); 1305 int32_t total_size = out_entry_stat->data_size(1);
1244 if (!has_key_sha256) 1306 if (!has_key_sha256)
1245 total_size += sizeof(net::SHA256HashValue); 1307 total_size += sizeof(net::SHA256HashValue);
1308
1309 // Sanity-check: don't want to be allocating a gigantic buffer > file size
1310 // just because of a header field.
1246 if (stream_0_size > total_size) 1311 if (stream_0_size > total_size)
1247 return net::ERR_FAILED; 1312 return net::ERR_FAILED;
1248 out_entry_stat->set_data_size(0, stream_0_size); 1313 out_entry_stat->set_data_size(0, stream_0_size);
1249 out_entry_stat->set_data_size(1, total_size - stream_0_size); 1314 out_entry_stat->set_data_size(1, total_size - stream_0_size);
1250 1315
1251 // Put stream 0 data in memory. 1316 // Put stream 0 data in memory --- plus maybe the sha256(key) footer.
1252 *stream_0_data = new net::GrowableIOBuffer(); 1317 int extra_stream_0_read = 0;
1253 (*stream_0_data)->SetCapacity(stream_0_size + sizeof(net::SHA256HashValue));
1254 int file_offset = out_entry_stat->GetOffsetInFile(key_.size(), 0, 0);
1255 int read_size = stream_0_size;
1256 if (has_key_sha256) 1318 if (has_key_sha256)
1257 read_size += sizeof(net::SHA256HashValue); 1319 extra_stream_0_read += sizeof(net::SHA256HashValue);
1258 if (files_[0].Read(file_offset, (*stream_0_data)->data(), read_size) != 1320 rv = PreReadStreamPayload(
1259 read_size) 1321 file_0_prefetch, 0, extra_stream_0_read, *out_entry_stat, stream_0_eof,
pasko 2017/08/04 01:28:34 maybe a few explanations how args correspond to pa
Maks Orlovich 2017/08/04 18:35:44 I went for extra_post_stream_0_read as name instea
1260 return net::ERR_FAILED; 1322 &stream_prefetch_data[0].data, &stream_prefetch_data[0].stream_crc32);
1323 if (rv != net::OK)
1324 return rv;
1261 1325
1262 // Check the CRC32. 1326 // If prefetch buffer is available, and we have sha256(key) (so we don't need
1263 uint32_t expected_crc32 = 1327 // to look at the header), extract out stream 1 info as well.
1264 simple_util::Crc32((*stream_0_data)->data(), stream_0_size); 1328 if (prefetch_buf && has_key_sha256) {
1265 if (has_crc32 && read_crc32 != expected_crc32) { 1329 SimpleFileEOF stream_1_eof;
1266 DVLOG(1) << "EOF record had bad crc."; 1330 rv = GetEOFRecordData(file_0_prefetch, 1, *out_entry_stat, &stream_1_eof);
1267 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); 1331 if (rv != net::OK)
1268 return net::ERR_FAILED; 1332 return rv;
1333
1334 rv = PreReadStreamPayload(file_0_prefetch, 1, 0, *out_entry_stat,
pasko 2017/08/04 01:28:34 s!0,!0 /* extra_size */,!
Maks Orlovich 2017/08/04 18:35:44 Did a variant of that.
pasko 2017/08/09 12:28:21 Thanks for that, I forgot the style guide
1335 stream_1_eof, &stream_prefetch_data[1].data,
1336 &stream_prefetch_data[1].stream_crc32);
1337 if (rv != net::OK)
1338 return rv;
1269 } 1339 }
1270 *out_stream_0_crc32 = expected_crc32;
1271 1340
1272 // If present, check the key SHA256. 1341 // If present, check the key SHA256.
1273 if (has_key_sha256) { 1342 if (has_key_sha256) {
1274 net::SHA256HashValue hash_value; 1343 net::SHA256HashValue hash_value;
1275 CalculateSHA256OfKey(key_, &hash_value); 1344 CalculateSHA256OfKey(key_, &hash_value);
1276 bool matched = 1345 bool matched =
1277 std::memcmp(&hash_value, (*stream_0_data)->data() + stream_0_size, 1346 std::memcmp(&hash_value,
1347 stream_prefetch_data[0].data->data() + stream_0_size,
1278 sizeof(hash_value)) == 0; 1348 sizeof(hash_value)) == 0;
1279 if (!matched) { 1349 if (!matched) {
1280 RecordKeySHA256Result(cache_type_, KeySHA256Result::NO_MATCH); 1350 RecordKeySHA256Result(cache_type_, KeySHA256Result::NO_MATCH);
1281 return net::ERR_FAILED; 1351 return net::ERR_FAILED;
1282 } 1352 }
1283 // Elide header check if we verified sha256(key) via footer. 1353 // Elide header check if we verified sha256(key) via footer.
1284 header_and_key_check_needed_[0] = false; 1354 header_and_key_check_needed_[0] = false;
1285 RecordKeySHA256Result(cache_type_, KeySHA256Result::MATCHED); 1355 RecordKeySHA256Result(cache_type_, KeySHA256Result::MATCHED);
1286 } else { 1356 } else {
1287 RecordKeySHA256Result(cache_type_, KeySHA256Result::NOT_PRESENT); 1357 RecordKeySHA256Result(cache_type_, KeySHA256Result::NOT_PRESENT);
1288 } 1358 }
1289 1359
1290 // Ensure the key is validated before completion. 1360 // Ensure the key is validated before completion.
1291 if (!has_key_sha256 && header_and_key_check_needed_[0]) 1361 if (!has_key_sha256 && header_and_key_check_needed_[0])
1292 CheckHeaderAndKey(0); 1362 CheckHeaderAndKey(0);
1293 1363
1294 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); 1364 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
1295 return net::OK; 1365 return net::OK;
1296 } 1366 }
1297 1367
1298 int SimpleSynchronousEntry::GetEOFRecordData(int index, 1368 bool SimpleSynchronousEntry::ReadFromFileOrPrefetched(
1369 base::StringPiece file_0_prefetch,
1370 int file_index,
1371 int offset,
1372 int size,
1373 char* dest) {
1374 if (file_0_prefetch.empty() || file_index != 0) {
1375 return files_[file_index].Read(offset, dest, size) == size;
1376 } else {
1377 if (offset < 0 || size < 0)
1378 return false;
1379 if (size == 0)
1380 return true;
1381
1382 base::CheckedNumeric<size_t> start(offset);
1383 size_t start_numeric;
1384 if (!start.AssignIfValid(&start_numeric) ||
1385 start_numeric >= file_0_prefetch.size())
1386 return false;
1387
1388 base::CheckedNumeric<size_t> end = start + size - 1;
1389 size_t end_numeric;
1390 if (!end.AssignIfValid(&end_numeric) ||
1391 end_numeric >= file_0_prefetch.size())
1392 return false;
1393
1394 memcpy(dest, file_0_prefetch.data() + offset, size);
1395 return true;
1396 }
1397 }
1398
1399 int SimpleSynchronousEntry::GetEOFRecordData(base::StringPiece file_0_prefetch,
1400 int stream_index,
1299 const SimpleEntryStat& entry_stat, 1401 const SimpleEntryStat& entry_stat,
1300 bool* out_has_crc32, 1402 SimpleFileEOF* eof_record) {
1301 bool* out_has_key_sha256, 1403 int file_offset = entry_stat.GetEOFOffsetInFile(key_.size(), stream_index);
1302 uint32_t* out_crc32, 1404 int file_index = GetFileIndexFromStreamIndex(stream_index);
1303 int32_t* out_data_size) const { 1405
1304 SimpleFileEOF eof_record; 1406 bool ok = ReadFromFileOrPrefetched(file_0_prefetch, file_index, file_offset,
1305 int file_offset = entry_stat.GetEOFOffsetInFile(key_.size(), index); 1407 sizeof(SimpleFileEOF),
pasko 2017/08/04 01:28:34 generally it is less error-prone to to use sizeof(
Maks Orlovich 2017/08/04 18:35:44 It would have to be sizeof(*variable) in this case
1306 int file_index = GetFileIndexFromStreamIndex(index); 1408 reinterpret_cast<char*>(eof_record));
1307 File* file = const_cast<File*>(&files_[file_index]); 1409 if (!ok) {
1308 if (file->Read(file_offset, reinterpret_cast<char*>(&eof_record),
1309 sizeof(eof_record)) !=
1310 sizeof(eof_record)) {
1311 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE); 1410 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE);
1312 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; 1411 return net::ERR_CACHE_CHECKSUM_READ_FAILURE;
1313 } 1412 }
1314 1413
1315 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) { 1414 if (eof_record->final_magic_number != kSimpleFinalMagicNumber) {
1316 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH); 1415 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH);
1317 DVLOG(1) << "EOF record had bad magic number."; 1416 DVLOG(1) << "EOF record had bad magic number.";
1318 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; 1417 return net::ERR_CACHE_CHECKSUM_READ_FAILURE;
1319 } 1418 }
1320 1419
1321 if (!base::IsValueInRangeForNumericType<int32_t>(eof_record.stream_size)) 1420 if (!base::IsValueInRangeForNumericType<int32_t>(eof_record->stream_size))
1322 return net::ERR_FAILED; 1421 return net::ERR_FAILED;
1323 1422 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_,
pasko 2017/08/04 01:28:34 Seems like both prefetch and last ReadData would r
Maks Orlovich 2017/08/04 18:35:44 I think it can't actually happen. To hit sync-side
pasko 2017/08/09 12:28:21 Even though this might be currently true, I find i
Maks Orlovich 2017/08/09 17:52:29 Good call on this since while SyncCheckEOFHasCrc w
1324 *out_has_crc32 = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) == 1423 (eof_record->flags & SimpleFileEOF::FLAG_HAS_CRC32) ==
1325 SimpleFileEOF::FLAG_HAS_CRC32; 1424 SimpleFileEOF::FLAG_HAS_CRC32);
1326 *out_has_key_sha256 =
1327 (eof_record.flags & SimpleFileEOF::FLAG_HAS_KEY_SHA256) ==
1328 SimpleFileEOF::FLAG_HAS_KEY_SHA256;
1329 *out_crc32 = eof_record.data_crc32;
1330 *out_data_size = eof_record.stream_size;
1331 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, *out_has_crc32);
1332 return net::OK; 1425 return net::OK;
1333 } 1426 }
1334 1427
1335 void SimpleSynchronousEntry::Doom() const { 1428 void SimpleSynchronousEntry::Doom() const {
1336 DeleteFilesForEntryHash(path_, entry_hash_); 1429 DeleteFilesForEntryHash(path_, entry_hash_);
1337 } 1430 }
1338 1431
1339 // static 1432 // static
1340 bool SimpleSynchronousEntry::DeleteFileForEntryHash(const FilePath& path, 1433 bool SimpleSynchronousEntry::DeleteFileForEntryHash(const FilePath& path,
1341 const uint64_t entry_hash, 1434 const uint64_t entry_hash,
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
1641 range.offset = offset; 1734 range.offset = offset;
1642 range.length = len; 1735 range.length = len;
1643 range.data_crc32 = data_crc32; 1736 range.data_crc32 = data_crc32;
1644 range.file_offset = data_file_offset; 1737 range.file_offset = data_file_offset;
1645 sparse_ranges_.insert(std::make_pair(offset, range)); 1738 sparse_ranges_.insert(std::make_pair(offset, range));
1646 1739
1647 return true; 1740 return true;
1648 } 1741 }
1649 1742
1650 } // namespace disk_cache 1743 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698