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" | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |