OLD | NEW |
---|---|
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" | |
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" |
22 #include "net/base/io_buffer.h" | 23 #include "net/base/io_buffer.h" |
23 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
24 #include "net/disk_cache/simple/simple_backend_version.h" | 25 #include "net/disk_cache/simple/simple_backend_version.h" |
26 #include "net/disk_cache/simple/simple_experiment.h" | |
25 #include "net/disk_cache/simple/simple_histogram_macros.h" | 27 #include "net/disk_cache/simple/simple_histogram_macros.h" |
26 #include "net/disk_cache/simple/simple_util.h" | 28 #include "net/disk_cache/simple/simple_util.h" |
27 #include "third_party/zlib/zlib.h" | 29 #include "third_party/zlib/zlib.h" |
28 | 30 |
29 using base::File; | 31 using base::File; |
30 using base::FilePath; | 32 using base::FilePath; |
31 using base::Time; | 33 using base::Time; |
32 | 34 |
33 namespace { | 35 namespace { |
34 | 36 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
111 SIMPLE_CACHE_UMA(ENUMERATION, | 113 SIMPLE_CACHE_UMA(ENUMERATION, |
112 "SyncCloseResult", cache_type, result, CLOSE_RESULT_MAX); | 114 "SyncCloseResult", cache_type, result, CLOSE_RESULT_MAX); |
113 } | 115 } |
114 | 116 |
115 void RecordKeySHA256Result(net::CacheType cache_type, KeySHA256Result result) { | 117 void RecordKeySHA256Result(net::CacheType cache_type, KeySHA256Result result) { |
116 SIMPLE_CACHE_UMA(ENUMERATION, "SyncKeySHA256Result", cache_type, | 118 SIMPLE_CACHE_UMA(ENUMERATION, "SyncKeySHA256Result", cache_type, |
117 static_cast<int>(result), | 119 static_cast<int>(result), |
118 static_cast<int>(KeySHA256Result::MAX)); | 120 static_cast<int>(KeySHA256Result::MAX)); |
119 } | 121 } |
120 | 122 |
123 void RecordSyncOpenPrefetchStatus(net::CacheType cache_type, bool result) { | |
pasko
2017/07/18 13:46:31
my favorite: nit on naming, because it is always p
Maks Orlovich
2017/07/21 18:37:33
Done'ish
| |
124 SIMPLE_CACHE_UMA(BOOLEAN, "SyncOpenDidPrefetch", cache_type, result); | |
125 } | |
126 | |
121 bool CanOmitEmptyFile(int file_index) { | 127 bool CanOmitEmptyFile(int file_index) { |
122 DCHECK_GE(file_index, 0); | 128 DCHECK_GE(file_index, 0); |
123 DCHECK_LT(file_index, disk_cache::kSimpleEntryFileCount); | 129 DCHECK_LT(file_index, disk_cache::kSimpleEntryFileCount); |
124 return file_index == disk_cache::simple_util::GetFileIndexFromStreamIndex(2); | 130 return file_index == disk_cache::simple_util::GetFileIndexFromStreamIndex(2); |
125 } | 131 } |
126 | 132 |
127 bool TruncatePath(const FilePath& filename_to_truncate) { | 133 bool TruncatePath(const FilePath& filename_to_truncate) { |
128 File file_to_truncate; | 134 File file_to_truncate; |
129 int flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE | | 135 int flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE | |
130 File::FLAG_SHARE_DELETE; | 136 File::FLAG_SHARE_DELETE; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 const base::TimeTicks& time_enqueued, | 268 const base::TimeTicks& time_enqueued, |
263 SimpleEntryCreationResults* out_results) { | 269 SimpleEntryCreationResults* out_results) { |
264 base::TimeTicks start_sync_open_entry = base::TimeTicks::Now(); | 270 base::TimeTicks start_sync_open_entry = base::TimeTicks::Now(); |
265 SIMPLE_CACHE_UMA(TIMES, "QueueLatency.OpenEntry", cache_type, | 271 SIMPLE_CACHE_UMA(TIMES, "QueueLatency.OpenEntry", cache_type, |
266 (start_sync_open_entry - time_enqueued)); | 272 (start_sync_open_entry - time_enqueued)); |
267 | 273 |
268 SimpleSynchronousEntry* sync_entry = | 274 SimpleSynchronousEntry* sync_entry = |
269 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index); | 275 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index); |
270 out_results->result = sync_entry->InitializeForOpen( | 276 out_results->result = sync_entry->InitializeForOpen( |
271 &out_results->entry_stat, &out_results->stream_0_data, | 277 &out_results->entry_stat, &out_results->stream_0_data, |
272 &out_results->stream_0_crc32); | 278 &out_results->stream_0_crc32, &out_results->stream_1_data, |
279 &out_results->stream_1_crc32); | |
pasko
2017/07/18 13:46:31
too many output arguments some set under non-trivi
Maks Orlovich
2017/07/28 17:27:35
Ended up grouping into array of structs, also simp
| |
273 if (out_results->result != net::OK) { | 280 if (out_results->result != net::OK) { |
274 sync_entry->Doom(); | 281 sync_entry->Doom(); |
275 delete sync_entry; | 282 delete sync_entry; |
276 out_results->sync_entry = NULL; | 283 out_results->sync_entry = NULL; |
277 out_results->stream_0_data = NULL; | 284 out_results->stream_0_data = NULL; |
278 return; | 285 return; |
279 } | 286 } |
280 SIMPLE_CACHE_UMA(TIMES, "DiskOpenLatency", cache_type, | 287 SIMPLE_CACHE_UMA(TIMES, "DiskOpenLatency", cache_type, |
281 base::TimeTicks::Now() - start_sync_open_entry); | 288 base::TimeTicks::Now() - start_sync_open_entry); |
282 out_results->sync_entry = sync_entry; | 289 out_results->sync_entry = sync_entry; |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
685 ++it; | 692 ++it; |
686 } | 693 } |
687 | 694 |
688 int64_t len_from_start = len - (start - offset); | 695 int64_t len_from_start = len - (start - offset); |
689 *out_start = start; | 696 *out_start = start; |
690 *out_result = static_cast<int>(std::min(avail_so_far, len_from_start)); | 697 *out_result = static_cast<int>(std::min(avail_so_far, len_from_start)); |
691 } | 698 } |
692 | 699 |
693 int SimpleSynchronousEntry::CheckEOFRecord(int index, | 700 int SimpleSynchronousEntry::CheckEOFRecord(int index, |
694 const SimpleEntryStat& entry_stat, | 701 const SimpleEntryStat& entry_stat, |
695 uint32_t expected_crc32) const { | 702 uint32_t expected_crc32) { |
696 DCHECK(initialized_); | 703 DCHECK(initialized_); |
697 uint32_t crc32; | 704 SimpleFileEOF eof_record; |
698 bool has_crc32; | 705 int rv = GetEOFRecordData(nullptr, 0, index, entry_stat, &eof_record); |
699 bool has_key_sha256; | 706 |
700 int32_t stream_size; | |
701 int rv = GetEOFRecordData(index, entry_stat, &has_crc32, &has_key_sha256, | |
702 &crc32, &stream_size); | |
703 if (rv != net::OK) { | 707 if (rv != net::OK) { |
704 Doom(); | 708 Doom(); |
705 return rv; | 709 return rv; |
706 } | 710 } |
707 if (has_crc32 && crc32 != expected_crc32) { | 711 if ((eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) && |
712 eof_record.data_crc32 != expected_crc32) { | |
708 DVLOG(1) << "EOF record had bad crc."; | 713 DVLOG(1) << "EOF record had bad crc."; |
709 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); | 714 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); |
710 Doom(); | 715 Doom(); |
711 return net::ERR_CACHE_CHECKSUM_MISMATCH; | 716 return net::ERR_CACHE_CHECKSUM_MISMATCH; |
712 } | 717 } |
713 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); | 718 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); |
714 return net::OK; | 719 return net::OK; |
715 } | 720 } |
716 | 721 |
722 int SimpleSynchronousEntry::PreReadStreamPayload( | |
pasko
2017/07/18 13:46:31
Why Pre? It just reads, no?
morlovich
2017/07/18 14:32:31
Because it's only used in the prefetch path?
pasko
2017/07/19 16:28:26
ah, ok
Maks Orlovich
2017/07/21 18:37:34
Acknowledged.
| |
723 char* prefetch_buf, | |
724 int file_size, | |
725 int stream_index, | |
726 int extra_size, | |
727 const SimpleEntryStat& entry_stat, | |
728 const SimpleFileEOF& eof_record, | |
729 scoped_refptr<net::GrowableIOBuffer>* stream_data, | |
730 uint32_t* out_crc32) { | |
731 int stream_size = entry_stat.data_size(stream_index); | |
732 int read_size = stream_size + extra_size; | |
733 *stream_data = new net::GrowableIOBuffer(); | |
734 (*stream_data)->SetCapacity(read_size); | |
735 int file_offset = entry_stat.GetOffsetInFile(key_.size(), 0, stream_index); | |
736 if (!ReadFromFileOrPrefetched(prefetch_buf, file_size, file_offset, read_size, | |
737 (*stream_data)->data())) | |
738 return net::ERR_FAILED; | |
739 | |
740 // Check the CRC32. | |
741 uint32_t expected_crc32 = | |
742 stream_size == 0 | |
743 ? crc32(0, Z_NULL, 0) | |
744 : crc32(crc32(0, Z_NULL, 0), | |
745 reinterpret_cast<const Bytef*>((*stream_data)->data()), | |
pasko
2017/07/19 16:28:26
In case you have similar allergies to reinterpret_
Maks Orlovich
2017/07/25 16:06:29
Split out into https://chromium-review.googlesourc
| |
746 stream_size); | |
747 if ((eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) && | |
748 eof_record.data_crc32 != expected_crc32) { | |
749 DVLOG(1) << "EOF record had bad crc."; | |
750 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); | |
pasko
2017/07/19 16:28:26
just realized that this might slightly increase th
Maks Orlovich
2017/07/21 18:37:34
Acknowledged.
| |
751 return net::ERR_CACHE_CHECKSUM_MISMATCH; | |
752 } | |
753 *out_crc32 = expected_crc32; | |
754 return net::OK; | |
755 } | |
756 | |
717 void SimpleSynchronousEntry::Close( | 757 void SimpleSynchronousEntry::Close( |
718 const SimpleEntryStat& entry_stat, | 758 const SimpleEntryStat& entry_stat, |
719 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write, | 759 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write, |
720 net::GrowableIOBuffer* stream_0_data) { | 760 net::GrowableIOBuffer* stream_0_data) { |
721 base::ElapsedTimer close_time; | 761 base::ElapsedTimer close_time; |
722 DCHECK(stream_0_data); | 762 DCHECK(stream_0_data); |
723 | 763 |
724 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); | 764 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); |
725 it != crc32s_to_write->end(); ++it) { | 765 it != crc32s_to_write->end(); ++it) { |
726 const int stream_index = it->index; | 766 const int stream_index = it->index; |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1089 } | 1129 } |
1090 } | 1130 } |
1091 | 1131 |
1092 header_and_key_check_needed_[file_index] = false; | 1132 header_and_key_check_needed_[file_index] = false; |
1093 return true; | 1133 return true; |
1094 } | 1134 } |
1095 | 1135 |
1096 int SimpleSynchronousEntry::InitializeForOpen( | 1136 int SimpleSynchronousEntry::InitializeForOpen( |
1097 SimpleEntryStat* out_entry_stat, | 1137 SimpleEntryStat* out_entry_stat, |
1098 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, | 1138 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, |
1099 uint32_t* out_stream_0_crc32) { | 1139 uint32_t* out_stream_0_crc32, |
1140 scoped_refptr<net::GrowableIOBuffer>* stream_1_data, | |
1141 uint32_t* out_stream_1_crc32) { | |
1100 DCHECK(!initialized_); | 1142 DCHECK(!initialized_); |
1101 if (!OpenFiles(out_entry_stat)) { | 1143 if (!OpenFiles(out_entry_stat)) { |
1102 DLOG(WARNING) << "Could not open platform files for entry."; | 1144 DLOG(WARNING) << "Could not open platform files for entry."; |
1103 return net::ERR_FAILED; | 1145 return net::ERR_FAILED; |
1104 } | 1146 } |
1105 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | 1147 for (int i = 0; i < kSimpleEntryFileCount; ++i) { |
1106 if (empty_file_omitted_[i]) | 1148 if (empty_file_omitted_[i]) |
1107 continue; | 1149 continue; |
1108 | 1150 |
1109 if (key_.empty()) { | 1151 if (key_.empty()) { |
1110 // If |key_| is empty, we were opened via the iterator interface, without | 1152 // If |key_| is empty, we were opened via the iterator interface, without |
1111 // knowing what our key is. We must therefore read the header immediately | 1153 // knowing what our key is. We must therefore read the header immediately |
1112 // to discover it, so SimpleEntryImpl can make it available to | 1154 // to discover it, so SimpleEntryImpl can make it available to |
1113 // disk_cache::Entry::GetKey(). | 1155 // disk_cache::Entry::GetKey(). |
1114 if (!CheckHeaderAndKey(i)) | 1156 if (!CheckHeaderAndKey(i)) |
1115 return net::ERR_FAILED; | 1157 return net::ERR_FAILED; |
1116 } else { | 1158 } else { |
1117 // If we do know which key were are looking for, we still need to | 1159 // If we do know which key were are looking for, we still need to |
1118 // check that the file actually has it (rather than just being a hash | 1160 // check that the file actually has it (rather than just being a hash |
1119 // collision or some sort of file system accident), but that can be put | 1161 // collision or some sort of file system accident), but that can be put |
1120 // off until opportune time: either the read of the footer, or when we | 1162 // off until opportune time: either the read of the footer, or when we |
1121 // start reading in the data, depending on stream # and format revision. | 1163 // start reading in the data, depending on stream # and format revision. |
1122 header_and_key_check_needed_[i] = true; | 1164 header_and_key_check_needed_[i] = true; |
1123 } | 1165 } |
1124 | 1166 |
1125 if (i == 0) { | 1167 if (i == 0) { |
1126 // File size for stream 0 has been stored temporarily in data_size[1]. | 1168 // File size for stream 0 has been stored temporarily in data_size[1]. |
1127 int ret_value_stream_0 = | 1169 int ret_value_stream_0 = ReadAndValidateStream0( |
1128 ReadAndValidateStream0(out_entry_stat->data_size(1), out_entry_stat, | 1170 out_entry_stat->data_size(1), out_entry_stat, stream_0_data, |
1129 stream_0_data, out_stream_0_crc32); | 1171 out_stream_0_crc32, stream_1_data, out_stream_1_crc32); |
1130 if (ret_value_stream_0 != net::OK) | 1172 if (ret_value_stream_0 != net::OK) |
1131 return ret_value_stream_0; | 1173 return ret_value_stream_0; |
1132 } else { | 1174 } else { |
1133 out_entry_stat->set_data_size( | 1175 out_entry_stat->set_data_size( |
1134 2, | 1176 2, |
1135 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(2))); | 1177 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(2))); |
1136 if (out_entry_stat->data_size(2) < 0) { | 1178 if (out_entry_stat->data_size(2) < 0) { |
1137 DLOG(WARNING) << "Stream 2 file is too small."; | 1179 DLOG(WARNING) << "Stream 2 file is too small."; |
1138 return net::ERR_FAILED; | 1180 return net::ERR_FAILED; |
1139 } | 1181 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1210 if (!InitializeCreatedFile(i, &result)) { | 1252 if (!InitializeCreatedFile(i, &result)) { |
1211 RecordSyncCreateResult(result, had_index_); | 1253 RecordSyncCreateResult(result, had_index_); |
1212 return net::ERR_FAILED; | 1254 return net::ERR_FAILED; |
1213 } | 1255 } |
1214 } | 1256 } |
1215 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index_); | 1257 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index_); |
1216 initialized_ = true; | 1258 initialized_ = true; |
1217 return net::OK; | 1259 return net::OK; |
1218 } | 1260 } |
1219 | 1261 |
1220 int SimpleSynchronousEntry::ReadAndValidateStream0( | 1262 int SimpleSynchronousEntry::ReadAndValidateStream0( |
pasko
2017/07/18 13:46:31
this fetches stream 1 as well, so the name of the
morlovich
2017/07/18 14:32:31
How awful is ReadAndValidateStream0AndMaybe1 ?
Any
pasko
2017/07/19 16:28:26
As a name it sounds good to me
| |
1221 int file_size, | 1263 int file_size, |
1222 SimpleEntryStat* out_entry_stat, | 1264 SimpleEntryStat* out_entry_stat, |
1223 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, | 1265 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, |
1224 uint32_t* out_stream_0_crc32) { | 1266 uint32_t* out_stream_0_crc32, |
1267 scoped_refptr<net::GrowableIOBuffer>* stream_1_data, | |
1268 uint32_t* out_stream_1_crc32) { | |
1269 // If the file is sufficiently small, we will prefetch everything -- | |
1270 // in which case |prefetch_buf| will be non-null, and we should look at it | |
1271 // rather than call ::Read for the bits. | |
1272 std::unique_ptr<char[]> prefetch_buf; | |
1273 | |
1274 if (file_size <= GetSimpleCachePrefetchSize()) { | |
1275 RecordSyncOpenPrefetchStatus(cache_type_, true); | |
1276 prefetch_buf = base::MakeUnique<char[]>(file_size); | |
1277 if (files_[0].Read(0, prefetch_buf.get(), file_size) != file_size) | |
1278 return net::ERR_FAILED; | |
1279 } else { | |
1280 RecordSyncOpenPrefetchStatus(cache_type_, false); | |
pasko
2017/07/18 13:46:31
nit: it is usually easier to read if the short bra
Maks Orlovich
2017/07/21 18:37:33
[Citation needed], but done.
pasko
2017/07/24 12:22:45
unfortunately, could not find a good one, and now
| |
1281 } | |
1282 | |
1225 // Pretend this file has a null stream zero, and contains the optional key | 1283 // Pretend this file has a null stream zero, and contains the optional key |
1226 // SHA256. This is good enough to read the EOF record on the file, which gives | 1284 // SHA256. This is good enough to read the EOF record on the file, which gives |
1227 // the actual size of stream 0. | 1285 // the actual size of stream 0. |
1228 int temp_data_size = GetDataSizeFromFileSize(key_.size(), file_size); | 1286 int temp_data_size = GetDataSizeFromFileSize(key_.size(), file_size); |
1229 out_entry_stat->set_data_size(0, 0); | 1287 out_entry_stat->set_data_size(0, 0); |
1230 out_entry_stat->set_data_size( | 1288 out_entry_stat->set_data_size( |
1231 1, temp_data_size - sizeof(net::SHA256HashValue) - sizeof(SimpleFileEOF)); | 1289 1, temp_data_size - sizeof(net::SHA256HashValue) - sizeof(SimpleFileEOF)); |
1232 | 1290 |
1233 bool has_crc32; | 1291 SimpleFileEOF stream_0_eof; |
1234 bool has_key_sha256; | 1292 int rv = GetEOFRecordData(prefetch_buf.get(), file_size, 0, *out_entry_stat, |
1235 uint32_t read_crc32; | 1293 &stream_0_eof); |
1236 int32_t stream_0_size; | 1294 if (rv != net::OK) |
1237 int ret_value_crc32 = | 1295 return rv; |
1238 GetEOFRecordData(0, *out_entry_stat, &has_crc32, &has_key_sha256, | 1296 |
1239 &read_crc32, &stream_0_size); | 1297 bool has_key_sha256 = |
1240 if (ret_value_crc32 != net::OK) | 1298 (stream_0_eof.flags & SimpleFileEOF::FLAG_HAS_KEY_SHA256) == |
1241 return ret_value_crc32; | 1299 SimpleFileEOF::FLAG_HAS_KEY_SHA256; |
1300 int32_t stream_0_size = stream_0_eof.stream_size; | |
1242 | 1301 |
1243 // Calculate and set the real values for the two streams. | 1302 // Calculate and set the real values for the two streams. |
1244 int32_t total_size = out_entry_stat->data_size(1); | 1303 int32_t total_size = out_entry_stat->data_size(1); |
1245 if (!has_key_sha256) | 1304 if (!has_key_sha256) |
1246 total_size += sizeof(net::SHA256HashValue); | 1305 total_size += sizeof(net::SHA256HashValue); |
1306 | |
1307 // Sanity-check: don't want to be allocating a gigantic buffer > file size | |
1308 // just because of a header field. | |
1247 if (stream_0_size > total_size) | 1309 if (stream_0_size > total_size) |
1248 return net::ERR_FAILED; | 1310 return net::ERR_FAILED; |
1249 out_entry_stat->set_data_size(0, stream_0_size); | 1311 out_entry_stat->set_data_size(0, stream_0_size); |
1250 out_entry_stat->set_data_size(1, total_size - stream_0_size); | 1312 out_entry_stat->set_data_size(1, total_size - stream_0_size); |
1251 | 1313 |
1252 // Put stream 0 data in memory. | 1314 // Put stream 0 data in memory --- plus maybe the sha256(key) footer. |
1253 *stream_0_data = new net::GrowableIOBuffer(); | 1315 int extra_stream_0_read = 0; |
1254 (*stream_0_data)->SetCapacity(stream_0_size + sizeof(net::SHA256HashValue)); | |
1255 int file_offset = out_entry_stat->GetOffsetInFile(key_.size(), 0, 0); | |
1256 int read_size = stream_0_size; | |
1257 if (has_key_sha256) | 1316 if (has_key_sha256) |
1258 read_size += sizeof(net::SHA256HashValue); | 1317 extra_stream_0_read += sizeof(net::SHA256HashValue); |
1259 if (files_[0].Read(file_offset, (*stream_0_data)->data(), read_size) != | 1318 rv = PreReadStreamPayload(prefetch_buf.get(), file_size, 0, |
1260 read_size) | 1319 extra_stream_0_read, *out_entry_stat, stream_0_eof, |
1261 return net::ERR_FAILED; | 1320 stream_0_data, out_stream_0_crc32); |
1321 if (rv != net::OK) | |
1322 return rv; | |
1262 | 1323 |
1263 // Check the CRC32. | 1324 // If prefetch buffer is available, and we have sha256(key) (so we don't need |
1264 uint32_t expected_crc32 = | 1325 // to look at the header), extract out stream 1 info as well. |
1265 stream_0_size == 0 | 1326 if (prefetch_buf && has_key_sha256) { |
1266 ? crc32(0, Z_NULL, 0) | 1327 SimpleFileEOF stream_1_eof; |
1267 : crc32(crc32(0, Z_NULL, 0), | 1328 rv = GetEOFRecordData(prefetch_buf.get(), file_size, 1, *out_entry_stat, |
1268 reinterpret_cast<const Bytef*>((*stream_0_data)->data()), | 1329 &stream_1_eof); |
1269 stream_0_size); | 1330 if (rv != net::OK) |
1270 if (has_crc32 && read_crc32 != expected_crc32) { | 1331 return rv; |
1271 DVLOG(1) << "EOF record had bad crc."; | 1332 |
1272 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); | 1333 rv = PreReadStreamPayload(prefetch_buf.get(), file_size, 1, 0, |
1273 return net::ERR_FAILED; | 1334 *out_entry_stat, stream_1_eof, stream_1_data, |
1335 out_stream_1_crc32); | |
1336 if (rv != net::OK) | |
1337 return rv; | |
1338 } else { | |
1339 *stream_1_data = nullptr; | |
1274 } | 1340 } |
1275 *out_stream_0_crc32 = expected_crc32; | |
1276 | 1341 |
1277 // If present, check the key SHA256. | 1342 // If present, check the key SHA256. |
1278 if (has_key_sha256) { | 1343 if (has_key_sha256) { |
1279 net::SHA256HashValue hash_value; | 1344 net::SHA256HashValue hash_value; |
1280 CalculateSHA256OfKey(key_, &hash_value); | 1345 CalculateSHA256OfKey(key_, &hash_value); |
1281 bool matched = | 1346 bool matched = |
1282 std::memcmp(&hash_value, (*stream_0_data)->data() + stream_0_size, | 1347 std::memcmp(&hash_value, (*stream_0_data)->data() + stream_0_size, |
1283 sizeof(hash_value)) == 0; | 1348 sizeof(hash_value)) == 0; |
1284 if (!matched) { | 1349 if (!matched) { |
1285 RecordKeySHA256Result(cache_type_, KeySHA256Result::NO_MATCH); | 1350 RecordKeySHA256Result(cache_type_, KeySHA256Result::NO_MATCH); |
1286 return net::ERR_FAILED; | 1351 return net::ERR_FAILED; |
1287 } | 1352 } |
1288 // Elide header check if we verified sha256(key) via footer. | 1353 // Elide header check if we verified sha256(key) via footer. |
1289 header_and_key_check_needed_[0] = false; | 1354 header_and_key_check_needed_[0] = false; |
1290 RecordKeySHA256Result(cache_type_, KeySHA256Result::MATCHED); | 1355 RecordKeySHA256Result(cache_type_, KeySHA256Result::MATCHED); |
1291 } else { | 1356 } else { |
1292 RecordKeySHA256Result(cache_type_, KeySHA256Result::NOT_PRESENT); | 1357 RecordKeySHA256Result(cache_type_, KeySHA256Result::NOT_PRESENT); |
1293 } | 1358 } |
1294 | 1359 |
1295 // Ensure the key is validated before completion. | 1360 // Ensure the key is validated before completion. |
1296 if (!has_key_sha256 && header_and_key_check_needed_[0]) | 1361 if (!has_key_sha256 && header_and_key_check_needed_[0]) |
1297 CheckHeaderAndKey(0); | 1362 CheckHeaderAndKey(0); |
1298 | 1363 |
1299 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); | 1364 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); |
1300 return net::OK; | 1365 return net::OK; |
1301 } | 1366 } |
1302 | 1367 |
1303 int SimpleSynchronousEntry::GetEOFRecordData(int index, | 1368 bool SimpleSynchronousEntry::ReadFromFileOrPrefetched(char* prefetch_buf, |
1369 int file_size, | |
1370 int offset, | |
1371 int size, | |
1372 char* dest) { | |
1373 if (!prefetch_buf) { | |
1374 return files_[0].Read(offset, dest, size) == size; | |
1375 } else { | |
1376 if (offset < 0 || size < 0) | |
1377 return false; | |
1378 base::CheckedNumeric<int> end = | |
1379 base::CheckedNumeric<int>(offset) + size - 1; | |
1380 if (!end.IsValid()) | |
1381 return false; | |
1382 if (offset >= file_size || end.ValueOrDie() >= file_size) | |
pasko
2017/07/18 13:46:31
feel free to insert a DCHECK for the overflow, but
morlovich
2017/07/18 14:32:31
See the conditional in line 1380, this can't actua
pasko
2017/07/19 16:28:26
Ah, missed that. AssignIfValid() looks lengthy, I'
Maks Orlovich
2017/07/21 18:37:33
Ended up with AssignIfValid anyway, but I think it
| |
1383 return false; | |
1384 | |
1385 memcpy(dest, prefetch_buf + offset, size); | |
1386 return true; | |
1387 } | |
1388 } | |
1389 | |
1390 int SimpleSynchronousEntry::GetEOFRecordData(char* prefetch_buf, | |
1391 int file_size, | |
1392 int stream_index, | |
1304 const SimpleEntryStat& entry_stat, | 1393 const SimpleEntryStat& entry_stat, |
1305 bool* out_has_crc32, | 1394 SimpleFileEOF* eof_record) { |
1306 bool* out_has_key_sha256, | 1395 int file_offset = entry_stat.GetEOFOffsetInFile(key_.size(), stream_index); |
1307 uint32_t* out_crc32, | 1396 int file_index = GetFileIndexFromStreamIndex(stream_index); |
1308 int32_t* out_data_size) const { | 1397 |
pasko
2017/07/18 13:46:31
Following how the state migrates from disk to the
morlovich
2017/07/18 14:32:31
So my idea was that ReadFromFileOrPrefetched would
pasko
2017/07/19 16:28:26
Yeah, I understand your way to put ReadFromFileOrP
| |
1309 SimpleFileEOF eof_record; | 1398 // Should only have prefetch_buf when reading things in file 0. |
1310 int file_offset = entry_stat.GetEOFOffsetInFile(key_.size(), index); | 1399 DCHECK(file_index == 0 || !prefetch_buf); |
1311 int file_index = GetFileIndexFromStreamIndex(index); | 1400 bool ok; |
1312 File* file = const_cast<File*>(&files_[file_index]); | 1401 if (prefetch_buf) |
1313 if (file->Read(file_offset, reinterpret_cast<char*>(&eof_record), | 1402 ok = ReadFromFileOrPrefetched(prefetch_buf, file_size, file_offset, |
1314 sizeof(eof_record)) != | 1403 sizeof(SimpleFileEOF), |
1315 sizeof(eof_record)) { | 1404 reinterpret_cast<char*>(eof_record)); |
1405 else | |
1406 // Need to support files_[1], so can't use ReadFromFileOrPrefetched | |
1407 // in this case. | |
1408 ok = files_[file_index].Read( | |
1409 file_offset, reinterpret_cast<char*>(eof_record), | |
1410 sizeof(SimpleFileEOF)) == sizeof(SimpleFileEOF); | |
1411 | |
1412 if (!ok) { | |
1316 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE); | 1413 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE); |
1317 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; | 1414 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; |
1318 } | 1415 } |
1319 | 1416 |
1320 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) { | 1417 if (eof_record->final_magic_number != kSimpleFinalMagicNumber) { |
1321 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH); | 1418 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH); |
1322 DVLOG(1) << "EOF record had bad magic number."; | 1419 DVLOG(1) << "EOF record had bad magic number."; |
1323 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; | 1420 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; |
1324 } | 1421 } |
1325 | 1422 |
1326 if (!base::IsValueInRangeForNumericType<int32_t>(eof_record.stream_size)) | 1423 if (!base::IsValueInRangeForNumericType<int32_t>(eof_record->stream_size)) |
1327 return net::ERR_FAILED; | 1424 return net::ERR_FAILED; |
1328 | 1425 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, |
1329 *out_has_crc32 = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) == | 1426 (eof_record->flags & SimpleFileEOF::FLAG_HAS_CRC32) == |
1330 SimpleFileEOF::FLAG_HAS_CRC32; | 1427 SimpleFileEOF::FLAG_HAS_CRC32); |
1331 *out_has_key_sha256 = | |
1332 (eof_record.flags & SimpleFileEOF::FLAG_HAS_KEY_SHA256) == | |
1333 SimpleFileEOF::FLAG_HAS_KEY_SHA256; | |
1334 *out_crc32 = eof_record.data_crc32; | |
1335 *out_data_size = eof_record.stream_size; | |
1336 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, *out_has_crc32); | |
1337 return net::OK; | 1428 return net::OK; |
1338 } | 1429 } |
1339 | 1430 |
1340 void SimpleSynchronousEntry::Doom() const { | 1431 void SimpleSynchronousEntry::Doom() const { |
1341 DeleteFilesForEntryHash(path_, entry_hash_); | 1432 DeleteFilesForEntryHash(path_, entry_hash_); |
1342 } | 1433 } |
1343 | 1434 |
1344 // static | 1435 // static |
1345 bool SimpleSynchronousEntry::DeleteFileForEntryHash(const FilePath& path, | 1436 bool SimpleSynchronousEntry::DeleteFileForEntryHash(const FilePath& path, |
1346 const uint64_t entry_hash, | 1437 const uint64_t entry_hash, |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1651 range.offset = offset; | 1742 range.offset = offset; |
1652 range.length = len; | 1743 range.length = len; |
1653 range.data_crc32 = data_crc32; | 1744 range.data_crc32 = data_crc32; |
1654 range.file_offset = data_file_offset; | 1745 range.file_offset = data_file_offset; |
1655 sparse_ranges_.insert(std::make_pair(offset, range)); | 1746 sparse_ranges_.insert(std::make_pair(offset, range)); |
1656 | 1747 |
1657 return true; | 1748 return true; |
1658 } | 1749 } |
1659 | 1750 |
1660 } // namespace disk_cache | 1751 } // namespace disk_cache |
OLD | NEW |