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/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
17 #include "base/numerics/safe_conversions.h" | 17 #include "base/numerics/safe_conversions.h" |
18 #include "base/sha1.h" | 18 #include "base/sha1.h" |
19 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
20 #include "base/timer/elapsed_timer.h" | 20 #include "base/timer/elapsed_timer.h" |
| 21 #include "crypto/secure_hash.h" |
| 22 #include "net/base/hash_value.h" |
21 #include "net/base/io_buffer.h" | 23 #include "net/base/io_buffer.h" |
22 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
23 #include "net/disk_cache/simple/simple_backend_version.h" | 25 #include "net/disk_cache/simple/simple_backend_version.h" |
24 #include "net/disk_cache/simple/simple_histogram_macros.h" | 26 #include "net/disk_cache/simple/simple_histogram_macros.h" |
25 #include "net/disk_cache/simple/simple_util.h" | 27 #include "net/disk_cache/simple/simple_util.h" |
26 #include "third_party/zlib/zlib.h" | 28 #include "third_party/zlib/zlib.h" |
27 | 29 |
28 using base::File; | 30 using base::File; |
29 using base::FilePath; | 31 using base::FilePath; |
30 using base::Time; | 32 using base::Time; |
31 | 33 |
32 namespace { | 34 namespace { |
33 | 35 |
34 // Used in histograms, please only add entries at the end. | 36 // Used in histograms, please only add entries at the end. |
35 enum OpenEntryResult { | 37 enum OpenEntryResult { |
36 OPEN_ENTRY_SUCCESS = 0, | 38 OPEN_ENTRY_SUCCESS = 0, |
37 OPEN_ENTRY_PLATFORM_FILE_ERROR = 1, | 39 OPEN_ENTRY_PLATFORM_FILE_ERROR = 1, |
38 OPEN_ENTRY_CANT_READ_HEADER = 2, | 40 OPEN_ENTRY_CANT_READ_HEADER = 2, |
39 OPEN_ENTRY_BAD_MAGIC_NUMBER = 3, | 41 OPEN_ENTRY_BAD_MAGIC_NUMBER = 3, |
40 OPEN_ENTRY_BAD_VERSION = 4, | 42 OPEN_ENTRY_BAD_VERSION = 4, |
41 OPEN_ENTRY_CANT_READ_KEY = 5, | 43 OPEN_ENTRY_CANT_READ_KEY = 5, |
42 // OPEN_ENTRY_KEY_MISMATCH = 6, Deprecated. | 44 OPEN_ENTRY_KEY_MISMATCH = 6, |
43 OPEN_ENTRY_KEY_HASH_MISMATCH = 7, | 45 OPEN_ENTRY_KEY_HASH_MISMATCH = 7, |
44 OPEN_ENTRY_SPARSE_OPEN_FAILED = 8, | 46 OPEN_ENTRY_SPARSE_OPEN_FAILED = 8, |
45 OPEN_ENTRY_MAX = 9, | 47 OPEN_ENTRY_MAX = 9, |
46 }; | 48 }; |
47 | 49 |
48 // Used in histograms, please only add entries at the end. | 50 // Used in histograms, please only add entries at the end. |
49 enum WriteResult { | 51 enum WriteResult { |
50 WRITE_RESULT_SUCCESS = 0, | 52 WRITE_RESULT_SUCCESS = 0, |
51 WRITE_RESULT_PRETRUNCATE_FAILURE, | 53 WRITE_RESULT_PRETRUNCATE_FAILURE, |
52 WRITE_RESULT_WRITE_FAILURE, | 54 WRITE_RESULT_WRITE_FAILURE, |
53 WRITE_RESULT_TRUNCATE_FAILURE, | 55 WRITE_RESULT_TRUNCATE_FAILURE, |
54 WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED, | 56 WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED, |
55 WRITE_RESULT_LAZY_CREATE_FAILURE, | 57 WRITE_RESULT_LAZY_CREATE_FAILURE, |
56 WRITE_RESULT_LAZY_INITIALIZE_FAILURE, | 58 WRITE_RESULT_LAZY_INITIALIZE_FAILURE, |
57 WRITE_RESULT_MAX, | 59 WRITE_RESULT_MAX, |
58 }; | 60 }; |
59 | 61 |
60 // Used in histograms, please only add entries at the end. | 62 // Used in histograms, please only add entries at the end. |
61 enum CheckEOFResult { | 63 enum CheckEOFResult { |
62 CHECK_EOF_RESULT_SUCCESS, | 64 CHECK_EOF_RESULT_SUCCESS, |
63 CHECK_EOF_RESULT_READ_FAILURE, | 65 CHECK_EOF_RESULT_READ_FAILURE, |
64 CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH, | 66 CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH, |
65 CHECK_EOF_RESULT_CRC_MISMATCH, | 67 CHECK_EOF_RESULT_CRC_MISMATCH, |
| 68 CHECK_EOF_RESULT_KEY_SHA256_MISMATCH, |
66 CHECK_EOF_RESULT_MAX, | 69 CHECK_EOF_RESULT_MAX, |
67 }; | 70 }; |
68 | 71 |
69 // Used in histograms, please only add entries at the end. | 72 // Used in histograms, please only add entries at the end. |
70 enum CloseResult { | 73 enum CloseResult { |
71 CLOSE_RESULT_SUCCESS, | 74 CLOSE_RESULT_SUCCESS, |
72 CLOSE_RESULT_WRITE_FAILURE, | 75 CLOSE_RESULT_WRITE_FAILURE, |
73 }; | 76 }; |
74 | 77 |
| 78 // Used in histograms, please only add entries at the end. |
| 79 enum class KeySHA256Result { NOT_PRESENT, MATCHED, NO_MATCH, MAX }; |
| 80 |
75 void RecordSyncOpenResult(net::CacheType cache_type, | 81 void RecordSyncOpenResult(net::CacheType cache_type, |
76 OpenEntryResult result, | 82 OpenEntryResult result, |
77 bool had_index) { | 83 bool had_index) { |
78 DCHECK_LT(result, OPEN_ENTRY_MAX); | 84 DCHECK_LT(result, OPEN_ENTRY_MAX); |
79 SIMPLE_CACHE_UMA(ENUMERATION, | 85 SIMPLE_CACHE_UMA(ENUMERATION, |
80 "SyncOpenResult", cache_type, result, OPEN_ENTRY_MAX); | 86 "SyncOpenResult", cache_type, result, OPEN_ENTRY_MAX); |
81 if (had_index) { | 87 if (had_index) { |
82 SIMPLE_CACHE_UMA(ENUMERATION, | 88 SIMPLE_CACHE_UMA(ENUMERATION, |
83 "SyncOpenResult_WithIndex", cache_type, | 89 "SyncOpenResult_WithIndex", cache_type, |
84 result, OPEN_ENTRY_MAX); | 90 result, OPEN_ENTRY_MAX); |
(...skipping 13 matching lines...) Expand all Loading... |
98 SIMPLE_CACHE_UMA(ENUMERATION, | 104 SIMPLE_CACHE_UMA(ENUMERATION, |
99 "SyncCheckEOFResult", cache_type, | 105 "SyncCheckEOFResult", cache_type, |
100 result, CHECK_EOF_RESULT_MAX); | 106 result, CHECK_EOF_RESULT_MAX); |
101 } | 107 } |
102 | 108 |
103 void RecordCloseResult(net::CacheType cache_type, CloseResult result) { | 109 void RecordCloseResult(net::CacheType cache_type, CloseResult result) { |
104 SIMPLE_CACHE_UMA(ENUMERATION, | 110 SIMPLE_CACHE_UMA(ENUMERATION, |
105 "SyncCloseResult", cache_type, result, WRITE_RESULT_MAX); | 111 "SyncCloseResult", cache_type, result, WRITE_RESULT_MAX); |
106 } | 112 } |
107 | 113 |
| 114 void RecordKeySHA256Result(net::CacheType cache_type, KeySHA256Result result) { |
| 115 SIMPLE_CACHE_UMA(ENUMERATION, "SyncKeySHA256Result", cache_type, |
| 116 static_cast<int>(result), |
| 117 static_cast<int>(KeySHA256Result::MAX)); |
| 118 } |
| 119 |
108 bool CanOmitEmptyFile(int file_index) { | 120 bool CanOmitEmptyFile(int file_index) { |
109 DCHECK_GE(file_index, 0); | 121 DCHECK_GE(file_index, 0); |
110 DCHECK_LT(file_index, disk_cache::kSimpleEntryFileCount); | 122 DCHECK_LT(file_index, disk_cache::kSimpleEntryFileCount); |
111 return file_index == disk_cache::simple_util::GetFileIndexFromStreamIndex(2); | 123 return file_index == disk_cache::simple_util::GetFileIndexFromStreamIndex(2); |
112 } | 124 } |
113 | 125 |
114 bool TruncatePath(const FilePath& filename_to_truncate) { | 126 bool TruncatePath(const FilePath& filename_to_truncate) { |
115 File file_to_truncate; | 127 File file_to_truncate; |
116 int flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE | | 128 int flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE | |
117 File::FLAG_SHARE_DELETE; | 129 File::FLAG_SHARE_DELETE; |
118 file_to_truncate.Initialize(filename_to_truncate, flags); | 130 file_to_truncate.Initialize(filename_to_truncate, flags); |
119 if (!file_to_truncate.IsValid()) | 131 if (!file_to_truncate.IsValid()) |
120 return false; | 132 return false; |
121 if (!file_to_truncate.SetLength(0)) | 133 if (!file_to_truncate.SetLength(0)) |
122 return false; | 134 return false; |
123 return true; | 135 return true; |
124 } | 136 } |
125 | 137 |
| 138 void CalculateSHA256OfKey(const std::string& key, |
| 139 net::SHA256HashValue* out_hash_value) { |
| 140 std::unique_ptr<crypto::SecureHash> hash( |
| 141 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); |
| 142 hash->Update(key.data(), key.size()); |
| 143 hash->Finish(out_hash_value, sizeof(*out_hash_value)); |
| 144 } |
| 145 |
126 } // namespace | 146 } // namespace |
127 | 147 |
128 namespace disk_cache { | 148 namespace disk_cache { |
129 | 149 |
130 using simple_util::GetEntryHashKey; | 150 using simple_util::GetEntryHashKey; |
131 using simple_util::GetFilenameFromEntryHashAndFileIndex; | 151 using simple_util::GetFilenameFromEntryHashAndFileIndex; |
132 using simple_util::GetSparseFilenameFromEntryHash; | 152 using simple_util::GetSparseFilenameFromEntryHash; |
133 using simple_util::GetDataSizeFromKeyAndFileSize; | 153 using simple_util::GetHeaderSize; |
134 using simple_util::GetFileSizeFromKeyAndDataSize; | 154 using simple_util::GetDataSizeFromFileSize; |
| 155 using simple_util::GetFileSizeFromDataSize; |
135 using simple_util::GetFileIndexFromStreamIndex; | 156 using simple_util::GetFileIndexFromStreamIndex; |
136 | 157 |
137 SimpleEntryStat::SimpleEntryStat(base::Time last_used, | 158 SimpleEntryStat::SimpleEntryStat(base::Time last_used, |
138 base::Time last_modified, | 159 base::Time last_modified, |
139 const int32_t data_size[], | 160 const int32_t data_size[], |
140 const int32_t sparse_data_size) | 161 const int32_t sparse_data_size) |
141 : last_used_(last_used), | 162 : last_used_(last_used), |
142 last_modified_(last_modified), | 163 last_modified_(last_modified), |
143 sparse_data_size_(sparse_data_size) { | 164 sparse_data_size_(sparse_data_size) { |
144 memcpy(data_size_, data_size, sizeof(data_size_)); | 165 memcpy(data_size_, data_size, sizeof(data_size_)); |
145 } | 166 } |
146 | 167 |
147 int SimpleEntryStat::GetOffsetInFile(const std::string& key, | 168 // These size methods all assume the presence of the SHA256 on stream zero, |
| 169 // since this version of the cache always writes it. In the read case, it may |
| 170 // not be present and these methods can't be relied upon. |
| 171 |
| 172 int SimpleEntryStat::GetOffsetInFile(size_t key_length, |
148 int offset, | 173 int offset, |
149 int stream_index) const { | 174 int stream_index) const { |
150 const size_t headers_size = sizeof(SimpleFileHeader) + key.size(); | 175 const size_t headers_size = sizeof(SimpleFileHeader) + key_length; |
151 const size_t additional_offset = | 176 const size_t additional_offset = |
152 stream_index == 0 ? data_size_[1] + sizeof(SimpleFileEOF) : 0; | 177 stream_index == 0 ? data_size_[1] + sizeof(SimpleFileEOF) : 0; |
153 return headers_size + offset + additional_offset; | 178 return headers_size + offset + additional_offset; |
154 } | 179 } |
155 | 180 |
156 int SimpleEntryStat::GetEOFOffsetInFile(const std::string& key, | 181 int SimpleEntryStat::GetEOFOffsetInFile(size_t key_length, |
157 int stream_index) const { | 182 int stream_index) const { |
158 return GetOffsetInFile(key, data_size_[stream_index], stream_index); | 183 size_t additional_offset; |
| 184 if (stream_index != 0) |
| 185 additional_offset = 0; |
| 186 else |
| 187 additional_offset = sizeof(net::SHA256HashValue); |
| 188 return additional_offset + |
| 189 GetOffsetInFile(key_length, data_size_[stream_index], stream_index); |
159 } | 190 } |
160 | 191 |
161 int SimpleEntryStat::GetLastEOFOffsetInFile(const std::string& key, | 192 int SimpleEntryStat::GetLastEOFOffsetInFile(size_t key_length, |
162 int stream_index) const { | 193 int stream_index) const { |
163 const int file_index = GetFileIndexFromStreamIndex(stream_index); | 194 if (stream_index == 1) |
164 const int eof_data_offset = | 195 return GetEOFOffsetInFile(key_length, 0); |
165 file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF) | 196 return GetEOFOffsetInFile(key_length, stream_index); |
166 : data_size_[2]; | |
167 return GetOffsetInFile(key, eof_data_offset, stream_index); | |
168 } | 197 } |
169 | 198 |
170 int64_t SimpleEntryStat::GetFileSize(const std::string& key, | 199 int64_t SimpleEntryStat::GetFileSize(size_t key_length, int file_index) const { |
171 int file_index) const { | 200 int32_t total_data_size; |
172 const int32_t total_data_size = | 201 if (file_index == 0) { |
173 file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF) | 202 total_data_size = data_size_[0] + data_size_[1] + |
174 : data_size_[2]; | 203 sizeof(net::SHA256HashValue) + sizeof(SimpleFileEOF); |
175 return GetFileSizeFromKeyAndDataSize(key, total_data_size); | 204 } else { |
| 205 total_data_size = data_size_[2]; |
| 206 } |
| 207 return GetFileSizeFromDataSize(key_length, total_data_size); |
176 } | 208 } |
177 | 209 |
178 SimpleEntryCreationResults::SimpleEntryCreationResults( | 210 SimpleEntryCreationResults::SimpleEntryCreationResults( |
179 SimpleEntryStat entry_stat) | 211 SimpleEntryStat entry_stat) |
180 : sync_entry(NULL), | 212 : sync_entry(NULL), |
181 entry_stat(entry_stat), | 213 entry_stat(entry_stat), |
182 stream_0_crc32(crc32(0, Z_NULL, 0)), | 214 stream_0_crc32(crc32(0, Z_NULL, 0)), |
183 result(net::OK) { | 215 result(net::OK) { |
184 } | 216 } |
185 | 217 |
(...skipping 30 matching lines...) Expand all Loading... |
216 | 248 |
217 SimpleSynchronousEntry::EntryOperationData::EntryOperationData( | 249 SimpleSynchronousEntry::EntryOperationData::EntryOperationData( |
218 int64_t sparse_offset_p, | 250 int64_t sparse_offset_p, |
219 int buf_len_p) | 251 int buf_len_p) |
220 : sparse_offset(sparse_offset_p), buf_len(buf_len_p) {} | 252 : sparse_offset(sparse_offset_p), buf_len(buf_len_p) {} |
221 | 253 |
222 // static | 254 // static |
223 void SimpleSynchronousEntry::OpenEntry( | 255 void SimpleSynchronousEntry::OpenEntry( |
224 net::CacheType cache_type, | 256 net::CacheType cache_type, |
225 const FilePath& path, | 257 const FilePath& path, |
| 258 const std::string& key, |
226 const uint64_t entry_hash, | 259 const uint64_t entry_hash, |
227 bool had_index, | 260 const bool had_index, |
228 SimpleEntryCreationResults* out_results) { | 261 SimpleEntryCreationResults* out_results) { |
229 base::ElapsedTimer open_time; | 262 base::ElapsedTimer open_time; |
230 SimpleSynchronousEntry* sync_entry = | 263 SimpleSynchronousEntry* sync_entry = |
231 new SimpleSynchronousEntry(cache_type, path, "", entry_hash); | 264 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index); |
232 out_results->result = | 265 out_results->result = sync_entry->InitializeForOpen( |
233 sync_entry->InitializeForOpen(had_index, | 266 &out_results->entry_stat, &out_results->stream_0_data, |
234 &out_results->entry_stat, | 267 &out_results->stream_0_crc32); |
235 &out_results->stream_0_data, | |
236 &out_results->stream_0_crc32); | |
237 if (out_results->result != net::OK) { | 268 if (out_results->result != net::OK) { |
238 sync_entry->Doom(); | 269 sync_entry->Doom(); |
239 delete sync_entry; | 270 delete sync_entry; |
240 out_results->sync_entry = NULL; | 271 out_results->sync_entry = NULL; |
241 out_results->stream_0_data = NULL; | 272 out_results->stream_0_data = NULL; |
242 return; | 273 return; |
243 } | 274 } |
244 UMA_HISTOGRAM_TIMES("SimpleCache.DiskOpenLatency", open_time.Elapsed()); | 275 UMA_HISTOGRAM_TIMES("SimpleCache.DiskOpenLatency", open_time.Elapsed()); |
245 out_results->sync_entry = sync_entry; | 276 out_results->sync_entry = sync_entry; |
246 } | 277 } |
247 | 278 |
248 // static | 279 // static |
249 void SimpleSynchronousEntry::CreateEntry( | 280 void SimpleSynchronousEntry::CreateEntry( |
250 net::CacheType cache_type, | 281 net::CacheType cache_type, |
251 const FilePath& path, | 282 const FilePath& path, |
252 const std::string& key, | 283 const std::string& key, |
253 const uint64_t entry_hash, | 284 const uint64_t entry_hash, |
254 bool had_index, | 285 const bool had_index, |
255 SimpleEntryCreationResults* out_results) { | 286 SimpleEntryCreationResults* out_results) { |
256 DCHECK_EQ(entry_hash, GetEntryHashKey(key)); | 287 DCHECK_EQ(entry_hash, GetEntryHashKey(key)); |
257 SimpleSynchronousEntry* sync_entry = | 288 SimpleSynchronousEntry* sync_entry = |
258 new SimpleSynchronousEntry(cache_type, path, key, entry_hash); | 289 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index); |
259 out_results->result = sync_entry->InitializeForCreate( | 290 out_results->result = |
260 had_index, &out_results->entry_stat); | 291 sync_entry->InitializeForCreate(&out_results->entry_stat); |
261 if (out_results->result != net::OK) { | 292 if (out_results->result != net::OK) { |
262 if (out_results->result != net::ERR_FILE_EXISTS) | 293 if (out_results->result != net::ERR_FILE_EXISTS) |
263 sync_entry->Doom(); | 294 sync_entry->Doom(); |
264 delete sync_entry; | 295 delete sync_entry; |
265 out_results->sync_entry = NULL; | 296 out_results->sync_entry = NULL; |
266 return; | 297 return; |
267 } | 298 } |
268 out_results->sync_entry = sync_entry; | 299 out_results->sync_entry = sync_entry; |
269 } | 300 } |
270 | 301 |
(...skipping 20 matching lines...) Expand all Loading... |
291 [&path](const uint64_t& key_hash) { | 322 [&path](const uint64_t& key_hash) { |
292 return SimpleSynchronousEntry::DeleteFilesForEntryHash(path, key_hash); | 323 return SimpleSynchronousEntry::DeleteFilesForEntryHash(path, key_hash); |
293 }); | 324 }); |
294 return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED; | 325 return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED; |
295 } | 326 } |
296 | 327 |
297 void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op, | 328 void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op, |
298 net::IOBuffer* out_buf, | 329 net::IOBuffer* out_buf, |
299 uint32_t* out_crc32, | 330 uint32_t* out_crc32, |
300 SimpleEntryStat* entry_stat, | 331 SimpleEntryStat* entry_stat, |
301 int* out_result) const { | 332 int* out_result) { |
302 DCHECK(initialized_); | 333 DCHECK(initialized_); |
303 DCHECK_NE(0, in_entry_op.index); | 334 DCHECK_NE(0, in_entry_op.index); |
304 const int64_t file_offset = | |
305 entry_stat->GetOffsetInFile(key_, in_entry_op.offset, in_entry_op.index); | |
306 int file_index = GetFileIndexFromStreamIndex(in_entry_op.index); | 335 int file_index = GetFileIndexFromStreamIndex(in_entry_op.index); |
| 336 if (header_and_key_check_needed_[file_index] && |
| 337 !CheckHeaderAndKey(file_index)) { |
| 338 *out_result = net::ERR_FAILED; |
| 339 Doom(); |
| 340 return; |
| 341 } |
| 342 const int64_t file_offset = entry_stat->GetOffsetInFile( |
| 343 key_.size(), in_entry_op.offset, in_entry_op.index); |
307 // Zero-length reads and reads to the empty streams of omitted files should | 344 // Zero-length reads and reads to the empty streams of omitted files should |
308 // be handled in the SimpleEntryImpl. | 345 // be handled in the SimpleEntryImpl. |
309 DCHECK_GT(in_entry_op.buf_len, 0); | 346 DCHECK_GT(in_entry_op.buf_len, 0); |
310 DCHECK(!empty_file_omitted_[file_index]); | 347 DCHECK(!empty_file_omitted_[file_index]); |
311 File* file = const_cast<File*>(&files_[file_index]); | 348 int bytes_read = files_[file_index].Read(file_offset, out_buf->data(), |
312 int bytes_read = | 349 in_entry_op.buf_len); |
313 file->Read(file_offset, out_buf->data(), in_entry_op.buf_len); | |
314 if (bytes_read > 0) { | 350 if (bytes_read > 0) { |
315 entry_stat->set_last_used(Time::Now()); | 351 entry_stat->set_last_used(Time::Now()); |
316 *out_crc32 = crc32(crc32(0L, Z_NULL, 0), | 352 *out_crc32 = crc32(crc32(0L, Z_NULL, 0), |
317 reinterpret_cast<const Bytef*>(out_buf->data()), | 353 reinterpret_cast<const Bytef*>(out_buf->data()), |
318 bytes_read); | 354 bytes_read); |
319 } | 355 } |
320 if (bytes_read >= 0) { | 356 if (bytes_read >= 0) { |
321 *out_result = bytes_read; | 357 *out_result = bytes_read; |
322 } else { | 358 } else { |
323 *out_result = net::ERR_CACHE_READ_FAILURE; | 359 *out_result = net::ERR_CACHE_READ_FAILURE; |
324 Doom(); | 360 Doom(); |
325 } | 361 } |
326 } | 362 } |
327 | 363 |
328 void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op, | 364 void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op, |
329 net::IOBuffer* in_buf, | 365 net::IOBuffer* in_buf, |
330 SimpleEntryStat* out_entry_stat, | 366 SimpleEntryStat* out_entry_stat, |
331 int* out_result) { | 367 int* out_result) { |
332 DCHECK(initialized_); | 368 DCHECK(initialized_); |
333 DCHECK_NE(0, in_entry_op.index); | 369 DCHECK_NE(0, in_entry_op.index); |
334 int index = in_entry_op.index; | 370 int index = in_entry_op.index; |
335 int file_index = GetFileIndexFromStreamIndex(index); | 371 int file_index = GetFileIndexFromStreamIndex(index); |
| 372 if (header_and_key_check_needed_[file_index] && |
| 373 !empty_file_omitted_[file_index] && !CheckHeaderAndKey(file_index)) { |
| 374 *out_result = net::ERR_FAILED; |
| 375 Doom(); |
| 376 return; |
| 377 } |
336 int offset = in_entry_op.offset; | 378 int offset = in_entry_op.offset; |
337 int buf_len = in_entry_op.buf_len; | 379 int buf_len = in_entry_op.buf_len; |
338 bool truncate = in_entry_op.truncate; | 380 bool truncate = in_entry_op.truncate; |
339 bool doomed = in_entry_op.doomed; | 381 bool doomed = in_entry_op.doomed; |
340 const int64_t file_offset = out_entry_stat->GetOffsetInFile( | 382 const int64_t file_offset = out_entry_stat->GetOffsetInFile( |
341 key_, in_entry_op.offset, in_entry_op.index); | 383 key_.size(), in_entry_op.offset, in_entry_op.index); |
342 bool extending_by_write = offset + buf_len > out_entry_stat->data_size(index); | 384 bool extending_by_write = offset + buf_len > out_entry_stat->data_size(index); |
343 | 385 |
344 if (empty_file_omitted_[file_index]) { | 386 if (empty_file_omitted_[file_index]) { |
345 // Don't create a new file if the entry has been doomed, to avoid it being | 387 // Don't create a new file if the entry has been doomed, to avoid it being |
346 // mixed up with a newly-created entry with the same key. | 388 // mixed up with a newly-created entry with the same key. |
347 if (doomed) { | 389 if (doomed) { |
348 DLOG(WARNING) << "Rejecting write to lazily omitted stream " | 390 DLOG(WARNING) << "Rejecting write to lazily omitted stream " |
349 << in_entry_op.index << " of doomed cache entry."; | 391 << in_entry_op.index << " of doomed cache entry."; |
350 RecordWriteResult(cache_type_, WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED); | 392 RecordWriteResult(cache_type_, WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED); |
351 *out_result = net::ERR_CACHE_WRITE_FAILURE; | 393 *out_result = net::ERR_CACHE_WRITE_FAILURE; |
(...skipping 12 matching lines...) Expand all Loading... |
364 Doom(); | 406 Doom(); |
365 *out_result = net::ERR_CACHE_WRITE_FAILURE; | 407 *out_result = net::ERR_CACHE_WRITE_FAILURE; |
366 return; | 408 return; |
367 } | 409 } |
368 } | 410 } |
369 DCHECK(!empty_file_omitted_[file_index]); | 411 DCHECK(!empty_file_omitted_[file_index]); |
370 | 412 |
371 if (extending_by_write) { | 413 if (extending_by_write) { |
372 // The EOF record and the eventual stream afterward need to be zeroed out. | 414 // The EOF record and the eventual stream afterward need to be zeroed out. |
373 const int64_t file_eof_offset = | 415 const int64_t file_eof_offset = |
374 out_entry_stat->GetEOFOffsetInFile(key_, index); | 416 out_entry_stat->GetEOFOffsetInFile(key_.size(), index); |
375 if (!files_[file_index].SetLength(file_eof_offset)) { | 417 if (!files_[file_index].SetLength(file_eof_offset)) { |
376 RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE); | 418 RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE); |
377 Doom(); | 419 Doom(); |
378 *out_result = net::ERR_CACHE_WRITE_FAILURE; | 420 *out_result = net::ERR_CACHE_WRITE_FAILURE; |
379 return; | 421 return; |
380 } | 422 } |
381 } | 423 } |
382 if (buf_len > 0) { | 424 if (buf_len > 0) { |
383 if (files_[file_index].Write(file_offset, in_buf->data(), buf_len) != | 425 if (files_[file_index].Write(file_offset, in_buf->data(), buf_len) != |
384 buf_len) { | 426 buf_len) { |
385 RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE); | 427 RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE); |
386 Doom(); | 428 Doom(); |
387 *out_result = net::ERR_CACHE_WRITE_FAILURE; | 429 *out_result = net::ERR_CACHE_WRITE_FAILURE; |
388 return; | 430 return; |
389 } | 431 } |
390 } | 432 } |
391 if (!truncate && (buf_len > 0 || !extending_by_write)) { | 433 if (!truncate && (buf_len > 0 || !extending_by_write)) { |
392 out_entry_stat->set_data_size( | 434 out_entry_stat->set_data_size( |
393 index, std::max(out_entry_stat->data_size(index), offset + buf_len)); | 435 index, std::max(out_entry_stat->data_size(index), offset + buf_len)); |
394 } else { | 436 } else { |
395 out_entry_stat->set_data_size(index, offset + buf_len); | 437 out_entry_stat->set_data_size(index, offset + buf_len); |
396 int file_eof_offset = out_entry_stat->GetLastEOFOffsetInFile(key_, index); | 438 int file_eof_offset = |
| 439 out_entry_stat->GetLastEOFOffsetInFile(key_.size(), index); |
397 if (!files_[file_index].SetLength(file_eof_offset)) { | 440 if (!files_[file_index].SetLength(file_eof_offset)) { |
398 RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE); | 441 RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE); |
399 Doom(); | 442 Doom(); |
400 *out_result = net::ERR_CACHE_WRITE_FAILURE; | 443 *out_result = net::ERR_CACHE_WRITE_FAILURE; |
401 return; | 444 return; |
402 } | 445 } |
403 } | 446 } |
404 | 447 |
405 RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS); | 448 RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS); |
406 base::Time modification_time = Time::Now(); | 449 base::Time modification_time = Time::Now(); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 *out_result = static_cast<int>(std::min(avail_so_far, len_from_start)); | 657 *out_result = static_cast<int>(std::min(avail_so_far, len_from_start)); |
615 } | 658 } |
616 | 659 |
617 void SimpleSynchronousEntry::CheckEOFRecord(int index, | 660 void SimpleSynchronousEntry::CheckEOFRecord(int index, |
618 const SimpleEntryStat& entry_stat, | 661 const SimpleEntryStat& entry_stat, |
619 uint32_t expected_crc32, | 662 uint32_t expected_crc32, |
620 int* out_result) const { | 663 int* out_result) const { |
621 DCHECK(initialized_); | 664 DCHECK(initialized_); |
622 uint32_t crc32; | 665 uint32_t crc32; |
623 bool has_crc32; | 666 bool has_crc32; |
| 667 bool has_key_sha256; |
624 int stream_size; | 668 int stream_size; |
625 *out_result = | 669 *out_result = GetEOFRecordData(index, entry_stat, &has_crc32, &has_key_sha256, |
626 GetEOFRecordData(index, entry_stat, &has_crc32, &crc32, &stream_size); | 670 &crc32, &stream_size); |
627 if (*out_result != net::OK) { | 671 if (*out_result != net::OK) { |
628 Doom(); | 672 Doom(); |
629 return; | 673 return; |
630 } | 674 } |
631 if (has_crc32 && crc32 != expected_crc32) { | 675 if (has_crc32 && crc32 != expected_crc32) { |
632 DVLOG(1) << "EOF record had bad crc."; | 676 DVLOG(1) << "EOF record had bad crc."; |
633 *out_result = net::ERR_CACHE_CHECKSUM_MISMATCH; | 677 *out_result = net::ERR_CACHE_CHECKSUM_MISMATCH; |
634 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); | 678 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); |
635 Doom(); | 679 Doom(); |
636 return; | 680 return; |
637 } | 681 } |
638 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); | 682 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); |
639 } | 683 } |
640 | 684 |
641 void SimpleSynchronousEntry::Close( | 685 void SimpleSynchronousEntry::Close( |
642 const SimpleEntryStat& entry_stat, | 686 const SimpleEntryStat& entry_stat, |
643 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write, | 687 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write, |
644 net::GrowableIOBuffer* stream_0_data) { | 688 net::GrowableIOBuffer* stream_0_data) { |
645 DCHECK(stream_0_data); | 689 DCHECK(stream_0_data); |
646 // Write stream 0 data. | 690 // Write stream 0 data. |
647 int stream_0_offset = entry_stat.GetOffsetInFile(key_, 0, 0); | 691 int stream_0_offset = entry_stat.GetOffsetInFile(key_.size(), 0, 0); |
648 if (files_[0].Write(stream_0_offset, stream_0_data->data(), | 692 if (files_[0].Write(stream_0_offset, stream_0_data->data(), |
649 entry_stat.data_size(0)) != | 693 entry_stat.data_size(0)) != |
650 entry_stat.data_size(0)) { | 694 entry_stat.data_size(0)) { |
651 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); | 695 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); |
652 DVLOG(1) << "Could not write stream 0 data."; | 696 DVLOG(1) << "Could not write stream 0 data."; |
653 Doom(); | 697 Doom(); |
654 } | 698 } |
| 699 net::SHA256HashValue hash_value; |
| 700 CalculateSHA256OfKey(key_, &hash_value); |
| 701 if (files_[0].Write(stream_0_offset + entry_stat.data_size(0), |
| 702 reinterpret_cast<char*>(hash_value.data), |
| 703 sizeof(hash_value)) != sizeof(hash_value)) { |
| 704 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); |
| 705 DVLOG(1) << "Could not write stream 0 data."; |
| 706 Doom(); |
| 707 } |
655 | 708 |
656 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); | 709 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); |
657 it != crc32s_to_write->end(); ++it) { | 710 it != crc32s_to_write->end(); ++it) { |
658 const int stream_index = it->index; | 711 const int stream_index = it->index; |
659 const int file_index = GetFileIndexFromStreamIndex(stream_index); | 712 const int file_index = GetFileIndexFromStreamIndex(stream_index); |
660 if (empty_file_omitted_[file_index]) | 713 if (empty_file_omitted_[file_index]) |
661 continue; | 714 continue; |
662 | 715 |
663 SimpleFileEOF eof_record; | 716 SimpleFileEOF eof_record; |
664 eof_record.stream_size = entry_stat.data_size(stream_index); | 717 eof_record.stream_size = entry_stat.data_size(stream_index); |
665 eof_record.final_magic_number = kSimpleFinalMagicNumber; | 718 eof_record.final_magic_number = kSimpleFinalMagicNumber; |
666 eof_record.flags = 0; | 719 eof_record.flags = 0; |
667 if (it->has_crc32) | 720 if (it->has_crc32) |
668 eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32; | 721 eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32; |
| 722 if (stream_index == 0) |
| 723 eof_record.flags |= SimpleFileEOF::FLAG_HAS_KEY_SHA256; |
669 eof_record.data_crc32 = it->data_crc32; | 724 eof_record.data_crc32 = it->data_crc32; |
670 int eof_offset = entry_stat.GetEOFOffsetInFile(key_, stream_index); | 725 int eof_offset = entry_stat.GetEOFOffsetInFile(key_.size(), stream_index); |
671 // If stream 0 changed size, the file needs to be resized, otherwise the | 726 // If stream 0 changed size, the file needs to be resized, otherwise the |
672 // next open will yield wrong stream sizes. On stream 1 and stream 2 proper | 727 // next open will yield wrong stream sizes. On stream 1 and stream 2 proper |
673 // resizing of the file is handled in SimpleSynchronousEntry::WriteData(). | 728 // resizing of the file is handled in SimpleSynchronousEntry::WriteData(). |
674 if (stream_index == 0 && | 729 if (stream_index == 0 && |
675 !files_[file_index].SetLength(eof_offset)) { | 730 !files_[file_index].SetLength(eof_offset)) { |
676 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); | 731 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); |
677 DVLOG(1) << "Could not truncate stream 0 file."; | 732 DVLOG(1) << "Could not truncate stream 0 file."; |
678 Doom(); | 733 Doom(); |
679 break; | 734 break; |
680 } | 735 } |
681 if (files_[file_index].Write(eof_offset, | 736 if (files_[file_index].Write(eof_offset, |
682 reinterpret_cast<const char*>(&eof_record), | 737 reinterpret_cast<const char*>(&eof_record), |
683 sizeof(eof_record)) != | 738 sizeof(eof_record)) != |
684 sizeof(eof_record)) { | 739 sizeof(eof_record)) { |
685 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); | 740 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); |
686 DVLOG(1) << "Could not write eof record."; | 741 DVLOG(1) << "Could not write eof record."; |
687 Doom(); | 742 Doom(); |
688 break; | 743 break; |
689 } | 744 } |
690 } | 745 } |
691 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | 746 for (int i = 0; i < kSimpleEntryFileCount; ++i) { |
692 if (empty_file_omitted_[i]) | 747 if (empty_file_omitted_[i]) |
693 continue; | 748 continue; |
694 | 749 |
| 750 if (header_and_key_check_needed_[i] && !CheckHeaderAndKey(i)) { |
| 751 Doom(); |
| 752 } |
695 files_[i].Close(); | 753 files_[i].Close(); |
696 const int64_t file_size = entry_stat.GetFileSize(key_, i); | 754 const int64_t file_size = entry_stat.GetFileSize(key_.size(), i); |
697 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, | 755 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, |
698 "LastClusterSize", cache_type_, | 756 "LastClusterSize", cache_type_, |
699 file_size % 4096, 0, 4097, 50); | 757 file_size % 4096, 0, 4097, 50); |
700 const int64_t cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0; | 758 const int64_t cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0; |
701 SIMPLE_CACHE_UMA(PERCENTAGE, | 759 SIMPLE_CACHE_UMA(PERCENTAGE, |
702 "LastClusterLossPercent", cache_type_, | 760 "LastClusterLossPercent", cache_type_, |
703 static_cast<base::HistogramBase::Sample>( | 761 static_cast<base::HistogramBase::Sample>( |
704 cluster_loss * 100 / (cluster_loss + file_size))); | 762 cluster_loss * 100 / (cluster_loss + file_size))); |
705 } | 763 } |
706 | 764 |
707 if (sparse_file_open()) | 765 if (sparse_file_open()) |
708 sparse_file_.Close(); | 766 sparse_file_.Close(); |
709 | 767 |
710 if (files_created_) { | 768 if (files_created_) { |
711 const int stream2_file_index = GetFileIndexFromStreamIndex(2); | 769 const int stream2_file_index = GetFileIndexFromStreamIndex(2); |
712 SIMPLE_CACHE_UMA(BOOLEAN, "EntryCreatedAndStream2Omitted", cache_type_, | 770 SIMPLE_CACHE_UMA(BOOLEAN, "EntryCreatedAndStream2Omitted", cache_type_, |
713 empty_file_omitted_[stream2_file_index]); | 771 empty_file_omitted_[stream2_file_index]); |
714 } | 772 } |
715 RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS); | 773 RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS); |
716 have_open_files_ = false; | 774 have_open_files_ = false; |
717 delete this; | 775 delete this; |
718 } | 776 } |
719 | 777 |
720 SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type, | 778 SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type, |
721 const FilePath& path, | 779 const FilePath& path, |
722 const std::string& key, | 780 const std::string& key, |
723 const uint64_t entry_hash) | 781 const uint64_t entry_hash, |
| 782 const bool had_index) |
724 : cache_type_(cache_type), | 783 : cache_type_(cache_type), |
725 path_(path), | 784 path_(path), |
726 entry_hash_(entry_hash), | 785 entry_hash_(entry_hash), |
| 786 had_index_(had_index), |
727 key_(key), | 787 key_(key), |
728 have_open_files_(false), | 788 have_open_files_(false), |
729 initialized_(false) { | 789 initialized_(false) { |
730 for (int i = 0; i < kSimpleEntryFileCount; ++i) | 790 for (int i = 0; i < kSimpleEntryFileCount; ++i) |
731 empty_file_omitted_[i] = false; | 791 empty_file_omitted_[i] = false; |
732 } | 792 } |
733 | 793 |
734 SimpleSynchronousEntry::~SimpleSynchronousEntry() { | 794 SimpleSynchronousEntry::~SimpleSynchronousEntry() { |
735 DCHECK(!(have_open_files_ && initialized_)); | 795 DCHECK(!(have_open_files_ && initialized_)); |
736 if (have_open_files_) | 796 if (have_open_files_) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 int flags = File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE | | 832 int flags = File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE | |
773 File::FLAG_SHARE_DELETE; | 833 File::FLAG_SHARE_DELETE; |
774 files_[file_index].Initialize(filename, flags); | 834 files_[file_index].Initialize(filename, flags); |
775 *out_error = files_[file_index].error_details(); | 835 *out_error = files_[file_index].error_details(); |
776 | 836 |
777 empty_file_omitted_[file_index] = false; | 837 empty_file_omitted_[file_index] = false; |
778 | 838 |
779 return files_[file_index].IsValid(); | 839 return files_[file_index].IsValid(); |
780 } | 840 } |
781 | 841 |
782 bool SimpleSynchronousEntry::OpenFiles( | 842 bool SimpleSynchronousEntry::OpenFiles(SimpleEntryStat* out_entry_stat) { |
783 bool had_index, | |
784 SimpleEntryStat* out_entry_stat) { | |
785 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | 843 for (int i = 0; i < kSimpleEntryFileCount; ++i) { |
786 File::Error error; | 844 File::Error error; |
787 if (!MaybeOpenFile(i, &error)) { | 845 if (!MaybeOpenFile(i, &error)) { |
788 // TODO(juliatuttle,gavinp): Remove one each of these triplets of | 846 // TODO(juliatuttle,gavinp): Remove one each of these triplets of |
789 // histograms. We can calculate the third as the sum or difference of the | 847 // histograms. We can calculate the third as the sum or difference of the |
790 // other two. | 848 // other two. |
791 RecordSyncOpenResult( | 849 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_PLATFORM_FILE_ERROR, |
792 cache_type_, OPEN_ENTRY_PLATFORM_FILE_ERROR, had_index); | 850 had_index_); |
793 SIMPLE_CACHE_UMA(ENUMERATION, | 851 SIMPLE_CACHE_UMA(ENUMERATION, |
794 "SyncOpenPlatformFileError", cache_type_, | 852 "SyncOpenPlatformFileError", cache_type_, |
795 -error, -base::File::FILE_ERROR_MAX); | 853 -error, -base::File::FILE_ERROR_MAX); |
796 if (had_index) { | 854 if (had_index_) { |
797 SIMPLE_CACHE_UMA(ENUMERATION, | 855 SIMPLE_CACHE_UMA(ENUMERATION, |
798 "SyncOpenPlatformFileError_WithIndex", cache_type_, | 856 "SyncOpenPlatformFileError_WithIndex", cache_type_, |
799 -error, -base::File::FILE_ERROR_MAX); | 857 -error, -base::File::FILE_ERROR_MAX); |
800 } else { | 858 } else { |
801 SIMPLE_CACHE_UMA(ENUMERATION, | 859 SIMPLE_CACHE_UMA(ENUMERATION, |
802 "SyncOpenPlatformFileError_WithoutIndex", | 860 "SyncOpenPlatformFileError_WithoutIndex", |
803 cache_type_, | 861 cache_type_, |
804 -error, -base::File::FILE_ERROR_MAX); | 862 -error, -base::File::FILE_ERROR_MAX); |
805 } | 863 } |
806 while (--i >= 0) | 864 while (--i >= 0) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 } | 911 } |
854 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, | 912 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, |
855 "SyncOpenEntryAge", cache_type_, | 913 "SyncOpenEntryAge", cache_type_, |
856 entry_age.InHours(), 1, 1000, 50); | 914 entry_age.InHours(), 1, 1000, 50); |
857 | 915 |
858 files_created_ = false; | 916 files_created_ = false; |
859 | 917 |
860 return true; | 918 return true; |
861 } | 919 } |
862 | 920 |
863 bool SimpleSynchronousEntry::CreateFiles( | 921 bool SimpleSynchronousEntry::CreateFiles(SimpleEntryStat* out_entry_stat) { |
864 bool had_index, | |
865 SimpleEntryStat* out_entry_stat) { | |
866 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | 922 for (int i = 0; i < kSimpleEntryFileCount; ++i) { |
867 File::Error error; | 923 File::Error error; |
868 if (!MaybeCreateFile(i, FILE_NOT_REQUIRED, &error)) { | 924 if (!MaybeCreateFile(i, FILE_NOT_REQUIRED, &error)) { |
869 // TODO(juliatuttle,gavinp): Remove one each of these triplets of | 925 // TODO(juliatuttle,gavinp): Remove one each of these triplets of |
870 // histograms. We can calculate the third as the sum or difference of the | 926 // histograms. We can calculate the third as the sum or difference of the |
871 // other two. | 927 // other two. |
872 RecordSyncCreateResult(CREATE_ENTRY_PLATFORM_FILE_ERROR, had_index); | 928 RecordSyncCreateResult(CREATE_ENTRY_PLATFORM_FILE_ERROR, had_index_); |
873 SIMPLE_CACHE_UMA(ENUMERATION, | 929 SIMPLE_CACHE_UMA(ENUMERATION, |
874 "SyncCreatePlatformFileError", cache_type_, | 930 "SyncCreatePlatformFileError", cache_type_, |
875 -error, -base::File::FILE_ERROR_MAX); | 931 -error, -base::File::FILE_ERROR_MAX); |
876 if (had_index) { | 932 if (had_index_) { |
877 SIMPLE_CACHE_UMA(ENUMERATION, | 933 SIMPLE_CACHE_UMA(ENUMERATION, |
878 "SyncCreatePlatformFileError_WithIndex", cache_type_, | 934 "SyncCreatePlatformFileError_WithIndex", cache_type_, |
879 -error, -base::File::FILE_ERROR_MAX); | 935 -error, -base::File::FILE_ERROR_MAX); |
880 } else { | 936 } else { |
881 SIMPLE_CACHE_UMA(ENUMERATION, | 937 SIMPLE_CACHE_UMA(ENUMERATION, |
882 "SyncCreatePlatformFileError_WithoutIndex", | 938 "SyncCreatePlatformFileError_WithoutIndex", |
883 cache_type_, | 939 cache_type_, |
884 -error, -base::File::FILE_ERROR_MAX); | 940 -error, -base::File::FILE_ERROR_MAX); |
885 } | 941 } |
886 while (--i >= 0) | 942 while (--i >= 0) |
(...skipping 25 matching lines...) Expand all Loading... |
912 | 968 |
913 if (sparse_file_open()) | 969 if (sparse_file_open()) |
914 CloseSparseFile(); | 970 CloseSparseFile(); |
915 } | 971 } |
916 | 972 |
917 void SimpleSynchronousEntry::CloseFiles() { | 973 void SimpleSynchronousEntry::CloseFiles() { |
918 for (int i = 0; i < kSimpleEntryFileCount; ++i) | 974 for (int i = 0; i < kSimpleEntryFileCount; ++i) |
919 CloseFile(i); | 975 CloseFile(i); |
920 } | 976 } |
921 | 977 |
| 978 bool SimpleSynchronousEntry::CheckHeaderAndKey(int file_index) { |
| 979 // TODO(gavinp): Frequently we are doing this at the same time as we read from |
| 980 // the beginning of an entry. It might improve performance to make a single |
| 981 // read(2) call rather than two separate reads. On the other hand, it would |
| 982 // mean an extra memory to memory copy. In the case where we are opening an |
| 983 // entry without a key, the kInitialHeaderRead setting means that we are |
| 984 // actually already reading stream 1 data here, and tossing it out. |
| 985 std::vector<char> header_data(key_.empty() ? kInitialHeaderRead |
| 986 : GetHeaderSize(key_.size())); |
| 987 int bytes_read = |
| 988 files_[file_index].Read(0, header_data.data(), header_data.size()); |
| 989 const SimpleFileHeader* header = |
| 990 reinterpret_cast<const SimpleFileHeader*>(header_data.data()); |
| 991 |
| 992 if (bytes_read == -1 || static_cast<size_t>(bytes_read) < sizeof(*header)) { |
| 993 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_HEADER, had_index_); |
| 994 return false; |
| 995 } |
| 996 // This resize will not invalidate iterators since it does not enlarge the |
| 997 // header_data. |
| 998 DCHECK_LE(static_cast<size_t>(bytes_read), header_data.size()); |
| 999 header_data.resize(bytes_read); |
| 1000 |
| 1001 if (header->initial_magic_number != kSimpleInitialMagicNumber) { |
| 1002 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_MAGIC_NUMBER, had_index_); |
| 1003 return false; |
| 1004 } |
| 1005 |
| 1006 if (header->version != kSimpleEntryVersionOnDisk) { |
| 1007 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_VERSION, had_index_); |
| 1008 return false; |
| 1009 } |
| 1010 |
| 1011 size_t expected_header_size = GetHeaderSize(header->key_length); |
| 1012 if (header_data.size() < expected_header_size) { |
| 1013 size_t old_size = header_data.size(); |
| 1014 int bytes_to_read = expected_header_size - old_size; |
| 1015 // This resize will invalidate iterators, since it is enlarging header_data. |
| 1016 header_data.resize(expected_header_size); |
| 1017 int bytes_read = files_[file_index].Read( |
| 1018 old_size, header_data.data() + old_size, bytes_to_read); |
| 1019 if (bytes_read != bytes_to_read) { |
| 1020 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_KEY, had_index_); |
| 1021 return false; |
| 1022 } |
| 1023 header = reinterpret_cast<const SimpleFileHeader*>(header_data.data()); |
| 1024 } |
| 1025 |
| 1026 char* key_data = header_data.data() + sizeof(*header); |
| 1027 if (base::Hash(key_data, header->key_length) != header->key_hash) { |
| 1028 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_KEY_HASH_MISMATCH, had_index_); |
| 1029 return false; |
| 1030 } |
| 1031 |
| 1032 std::string key_from_header(key_data, header->key_length); |
| 1033 if (key_.empty()) { |
| 1034 key_.swap(key_from_header); |
| 1035 } else { |
| 1036 if (key_ != key_from_header) { |
| 1037 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_KEY_MISMATCH, had_index_); |
| 1038 return false; |
| 1039 } |
| 1040 } |
| 1041 |
| 1042 header_and_key_check_needed_[file_index] = false; |
| 1043 return true; |
| 1044 } |
| 1045 |
922 int SimpleSynchronousEntry::InitializeForOpen( | 1046 int SimpleSynchronousEntry::InitializeForOpen( |
923 bool had_index, | |
924 SimpleEntryStat* out_entry_stat, | 1047 SimpleEntryStat* out_entry_stat, |
925 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, | 1048 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, |
926 uint32_t* out_stream_0_crc32) { | 1049 uint32_t* out_stream_0_crc32) { |
927 DCHECK(!initialized_); | 1050 DCHECK(!initialized_); |
928 if (!OpenFiles(had_index, out_entry_stat)) { | 1051 if (!OpenFiles(out_entry_stat)) { |
929 DLOG(WARNING) << "Could not open platform files for entry."; | 1052 DLOG(WARNING) << "Could not open platform files for entry."; |
930 return net::ERR_FAILED; | 1053 return net::ERR_FAILED; |
931 } | 1054 } |
932 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | 1055 for (int i = 0; i < kSimpleEntryFileCount; ++i) { |
933 if (empty_file_omitted_[i]) | 1056 if (empty_file_omitted_[i]) |
934 continue; | 1057 continue; |
935 | 1058 |
936 SimpleFileHeader header; | 1059 if (!key_.empty()) { |
937 int header_read_result = | 1060 header_and_key_check_needed_[i] = true; |
938 files_[i].Read(0, reinterpret_cast<char*>(&header), sizeof(header)); | 1061 } else { |
939 if (header_read_result != sizeof(header)) { | 1062 if (!CheckHeaderAndKey(i)) |
940 DLOG(WARNING) << "Cannot read header from entry."; | 1063 return net::ERR_FAILED; |
941 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_HEADER, had_index); | |
942 return net::ERR_FAILED; | |
943 } | 1064 } |
944 | 1065 |
945 if (header.initial_magic_number != kSimpleInitialMagicNumber) { | |
946 // TODO(gavinp): This seems very bad; for now we log at WARNING, but we | |
947 // should give consideration to not saturating the log with these if that | |
948 // becomes a problem. | |
949 DLOG(WARNING) << "Magic number did not match."; | |
950 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_MAGIC_NUMBER, had_index); | |
951 return net::ERR_FAILED; | |
952 } | |
953 | |
954 if (header.version != kSimpleEntryVersionOnDisk) { | |
955 DLOG(WARNING) << "Unreadable version."; | |
956 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_VERSION, had_index); | |
957 return net::ERR_FAILED; | |
958 } | |
959 | |
960 std::unique_ptr<char[]> key(new char[header.key_length]); | |
961 int key_read_result = files_[i].Read(sizeof(header), key.get(), | |
962 header.key_length); | |
963 if (key_read_result != base::checked_cast<int>(header.key_length)) { | |
964 DLOG(WARNING) << "Cannot read key from entry."; | |
965 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_KEY, had_index); | |
966 return net::ERR_FAILED; | |
967 } | |
968 | |
969 key_ = std::string(key.get(), header.key_length); | |
970 if (i == 0) { | 1066 if (i == 0) { |
971 // File size for stream 0 has been stored temporarily in data_size[1]. | 1067 // File size for stream 0 has been stored temporarily in data_size[1]. |
972 int total_data_size = | 1068 int ret_value_stream_0 = |
973 GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size(1)); | 1069 ReadAndValidateStream0(out_entry_stat->data_size(1), out_entry_stat, |
974 int ret_value_stream_0 = ReadAndValidateStream0( | 1070 stream_0_data, out_stream_0_crc32); |
975 total_data_size, out_entry_stat, stream_0_data, out_stream_0_crc32); | |
976 if (ret_value_stream_0 != net::OK) | 1071 if (ret_value_stream_0 != net::OK) |
977 return ret_value_stream_0; | 1072 return ret_value_stream_0; |
978 } else { | 1073 } else { |
979 out_entry_stat->set_data_size( | 1074 out_entry_stat->set_data_size( |
980 2, GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size(2))); | 1075 2, |
| 1076 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(2))); |
981 if (out_entry_stat->data_size(2) < 0) { | 1077 if (out_entry_stat->data_size(2) < 0) { |
982 DLOG(WARNING) << "Stream 2 file is too small."; | 1078 DLOG(WARNING) << "Stream 2 file is too small."; |
983 return net::ERR_FAILED; | 1079 return net::ERR_FAILED; |
984 } | 1080 } |
985 } | 1081 } |
986 | |
987 if (base::Hash(key.get(), header.key_length) != header.key_hash) { | |
988 DLOG(WARNING) << "Hash mismatch on key."; | |
989 RecordSyncOpenResult( | |
990 cache_type_, OPEN_ENTRY_KEY_HASH_MISMATCH, had_index); | |
991 return net::ERR_FAILED; | |
992 } | |
993 } | 1082 } |
994 | 1083 |
995 int32_t sparse_data_size = 0; | 1084 int32_t sparse_data_size = 0; |
996 if (!OpenSparseFileIfExists(&sparse_data_size)) { | 1085 if (!OpenSparseFileIfExists(&sparse_data_size)) { |
997 RecordSyncOpenResult( | 1086 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SPARSE_OPEN_FAILED, |
998 cache_type_, OPEN_ENTRY_SPARSE_OPEN_FAILED, had_index); | 1087 had_index_); |
999 return net::ERR_FAILED; | 1088 return net::ERR_FAILED; |
1000 } | 1089 } |
1001 out_entry_stat->set_sparse_data_size(sparse_data_size); | 1090 out_entry_stat->set_sparse_data_size(sparse_data_size); |
1002 | 1091 |
1003 bool removed_stream2 = false; | 1092 bool removed_stream2 = false; |
1004 const int stream2_file_index = GetFileIndexFromStreamIndex(2); | 1093 const int stream2_file_index = GetFileIndexFromStreamIndex(2); |
1005 DCHECK(CanOmitEmptyFile(stream2_file_index)); | 1094 DCHECK(CanOmitEmptyFile(stream2_file_index)); |
1006 if (!empty_file_omitted_[stream2_file_index] && | 1095 if (!empty_file_omitted_[stream2_file_index] && |
1007 out_entry_stat->data_size(2) == 0) { | 1096 out_entry_stat->data_size(2) == 0) { |
1008 DVLOG(1) << "Removing empty stream 2 file."; | 1097 DVLOG(1) << "Removing empty stream 2 file."; |
1009 CloseFile(stream2_file_index); | 1098 CloseFile(stream2_file_index); |
1010 DeleteFileForEntryHash(path_, entry_hash_, stream2_file_index); | 1099 DeleteFileForEntryHash(path_, entry_hash_, stream2_file_index); |
1011 empty_file_omitted_[stream2_file_index] = true; | 1100 empty_file_omitted_[stream2_file_index] = true; |
1012 removed_stream2 = true; | 1101 removed_stream2 = true; |
1013 } | 1102 } |
1014 | 1103 |
1015 SIMPLE_CACHE_UMA(BOOLEAN, "EntryOpenedAndStream2Removed", cache_type_, | 1104 SIMPLE_CACHE_UMA(BOOLEAN, "EntryOpenedAndStream2Removed", cache_type_, |
1016 removed_stream2); | 1105 removed_stream2); |
1017 | 1106 |
1018 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index); | 1107 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index_); |
1019 initialized_ = true; | 1108 initialized_ = true; |
1020 return net::OK; | 1109 return net::OK; |
1021 } | 1110 } |
1022 | 1111 |
1023 bool SimpleSynchronousEntry::InitializeCreatedFile( | 1112 bool SimpleSynchronousEntry::InitializeCreatedFile( |
1024 int file_index, | 1113 int file_index, |
1025 CreateEntryResult* out_result) { | 1114 CreateEntryResult* out_result) { |
1026 SimpleFileHeader header; | 1115 SimpleFileHeader header; |
1027 header.initial_magic_number = kSimpleInitialMagicNumber; | 1116 header.initial_magic_number = kSimpleInitialMagicNumber; |
1028 header.version = kSimpleEntryVersionOnDisk; | 1117 header.version = kSimpleEntryVersionOnDisk; |
(...skipping 12 matching lines...) Expand all Loading... |
1041 key_.size()); | 1130 key_.size()); |
1042 if (bytes_written != base::checked_cast<int>(key_.size())) { | 1131 if (bytes_written != base::checked_cast<int>(key_.size())) { |
1043 *out_result = CREATE_ENTRY_CANT_WRITE_KEY; | 1132 *out_result = CREATE_ENTRY_CANT_WRITE_KEY; |
1044 return false; | 1133 return false; |
1045 } | 1134 } |
1046 | 1135 |
1047 return true; | 1136 return true; |
1048 } | 1137 } |
1049 | 1138 |
1050 int SimpleSynchronousEntry::InitializeForCreate( | 1139 int SimpleSynchronousEntry::InitializeForCreate( |
1051 bool had_index, | |
1052 SimpleEntryStat* out_entry_stat) { | 1140 SimpleEntryStat* out_entry_stat) { |
1053 DCHECK(!initialized_); | 1141 DCHECK(!initialized_); |
1054 if (!CreateFiles(had_index, out_entry_stat)) { | 1142 if (!CreateFiles(out_entry_stat)) { |
1055 DLOG(WARNING) << "Could not create platform files."; | 1143 DLOG(WARNING) << "Could not create platform files."; |
1056 return net::ERR_FILE_EXISTS; | 1144 return net::ERR_FILE_EXISTS; |
1057 } | 1145 } |
1058 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | 1146 for (int i = 0; i < kSimpleEntryFileCount; ++i) { |
1059 if (empty_file_omitted_[i]) | 1147 if (empty_file_omitted_[i]) |
1060 continue; | 1148 continue; |
1061 | 1149 |
1062 CreateEntryResult result; | 1150 CreateEntryResult result; |
1063 if (!InitializeCreatedFile(i, &result)) { | 1151 if (!InitializeCreatedFile(i, &result)) { |
1064 RecordSyncCreateResult(result, had_index); | 1152 RecordSyncCreateResult(result, had_index_); |
1065 return net::ERR_FAILED; | 1153 return net::ERR_FAILED; |
1066 } | 1154 } |
1067 } | 1155 } |
1068 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index); | 1156 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index_); |
1069 initialized_ = true; | 1157 initialized_ = true; |
1070 return net::OK; | 1158 return net::OK; |
1071 } | 1159 } |
1072 | 1160 |
1073 int SimpleSynchronousEntry::ReadAndValidateStream0( | 1161 int SimpleSynchronousEntry::ReadAndValidateStream0( |
1074 int total_data_size, | 1162 int file_size, |
1075 SimpleEntryStat* out_entry_stat, | 1163 SimpleEntryStat* out_entry_stat, |
1076 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, | 1164 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, |
1077 uint32_t* out_stream_0_crc32) const { | 1165 uint32_t* out_stream_0_crc32) { |
1078 // Temporarily assign all the data size to stream 1 in order to read the | 1166 // Pretend this file has a null stream zero, and contains the optional key |
1079 // EOF record for stream 0, which contains the size of stream 0. | 1167 // SHA256. This is good enough to read the EOF record on the file, which gives |
| 1168 // the actual size of stream 0. |
| 1169 int total_data_size = GetDataSizeFromFileSize(key_.size(), file_size); |
1080 out_entry_stat->set_data_size(0, 0); | 1170 out_entry_stat->set_data_size(0, 0); |
1081 out_entry_stat->set_data_size(1, total_data_size - sizeof(SimpleFileEOF)); | 1171 out_entry_stat->set_data_size( |
| 1172 1, |
| 1173 total_data_size - sizeof(net::SHA256HashValue) - sizeof(SimpleFileEOF)); |
1082 | 1174 |
1083 bool has_crc32; | 1175 bool has_crc32; |
| 1176 bool has_key_sha256; |
1084 uint32_t read_crc32; | 1177 uint32_t read_crc32; |
1085 int stream_0_size; | 1178 int stream_0_size; |
1086 int ret_value_crc32 = GetEOFRecordData( | 1179 int ret_value_crc32 = |
1087 0, *out_entry_stat, &has_crc32, &read_crc32, &stream_0_size); | 1180 GetEOFRecordData(0, *out_entry_stat, &has_crc32, &has_key_sha256, |
| 1181 &read_crc32, &stream_0_size); |
1088 if (ret_value_crc32 != net::OK) | 1182 if (ret_value_crc32 != net::OK) |
1089 return ret_value_crc32; | 1183 return ret_value_crc32; |
1090 | 1184 // Calculate and set the real values for data size. |
1091 if (stream_0_size > out_entry_stat->data_size(1)) | 1185 int stream_1_size = out_entry_stat->data_size(1) - stream_0_size; |
| 1186 if (!has_key_sha256) |
| 1187 stream_1_size += sizeof(net::SHA256HashValue); |
| 1188 if (stream_1_size < 0) |
1092 return net::ERR_FAILED; | 1189 return net::ERR_FAILED; |
1093 | |
1094 // These are the real values of data size. | |
1095 out_entry_stat->set_data_size(0, stream_0_size); | 1190 out_entry_stat->set_data_size(0, stream_0_size); |
1096 out_entry_stat->set_data_size( | 1191 out_entry_stat->set_data_size(1, stream_1_size); |
1097 1, out_entry_stat->data_size(1) - stream_0_size); | |
1098 | 1192 |
1099 // Put stream 0 data in memory. | 1193 // Put stream 0 data in memory. |
1100 *stream_0_data = new net::GrowableIOBuffer(); | 1194 *stream_0_data = new net::GrowableIOBuffer(); |
1101 (*stream_0_data)->SetCapacity(stream_0_size); | 1195 (*stream_0_data)->SetCapacity(stream_0_size + sizeof(net::SHA256HashValue)); |
1102 int file_offset = out_entry_stat->GetOffsetInFile(key_, 0, 0); | 1196 int file_offset = out_entry_stat->GetOffsetInFile(key_.size(), 0, 0); |
1103 File* file = const_cast<File*>(&files_[0]); | 1197 int read_size = stream_0_size; |
1104 int bytes_read = | 1198 if (has_key_sha256) |
1105 file->Read(file_offset, (*stream_0_data)->data(), stream_0_size); | 1199 read_size += sizeof(net::SHA256HashValue); |
1106 if (bytes_read != stream_0_size) | 1200 if (files_[0].Read(file_offset, (*stream_0_data)->data(), read_size) != |
| 1201 read_size) |
1107 return net::ERR_FAILED; | 1202 return net::ERR_FAILED; |
1108 | 1203 |
1109 // Check the CRC32. | 1204 // Check the CRC32. |
1110 uint32_t expected_crc32 = | 1205 uint32_t expected_crc32 = |
1111 stream_0_size == 0 | 1206 stream_0_size == 0 |
1112 ? crc32(0, Z_NULL, 0) | 1207 ? crc32(0, Z_NULL, 0) |
1113 : crc32(crc32(0, Z_NULL, 0), | 1208 : crc32(crc32(0, Z_NULL, 0), |
1114 reinterpret_cast<const Bytef*>((*stream_0_data)->data()), | 1209 reinterpret_cast<const Bytef*>((*stream_0_data)->data()), |
1115 stream_0_size); | 1210 stream_0_size); |
1116 if (has_crc32 && read_crc32 != expected_crc32) { | 1211 if (has_crc32 && read_crc32 != expected_crc32) { |
1117 DVLOG(1) << "EOF record had bad crc."; | 1212 DVLOG(1) << "EOF record had bad crc."; |
1118 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); | 1213 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); |
1119 return net::ERR_FAILED; | 1214 return net::ERR_FAILED; |
1120 } | 1215 } |
1121 *out_stream_0_crc32 = expected_crc32; | 1216 *out_stream_0_crc32 = expected_crc32; |
| 1217 |
| 1218 // If present, check the key SHA256. |
| 1219 if (has_key_sha256) { |
| 1220 net::SHA256HashValue hash_value; |
| 1221 CalculateSHA256OfKey(key_, &hash_value); |
| 1222 bool matched = |
| 1223 std::memcmp(&hash_value, (*stream_0_data)->data() + stream_0_size, |
| 1224 sizeof(hash_value)) == 0; |
| 1225 if (!matched) { |
| 1226 RecordKeySHA256Result(cache_type_, KeySHA256Result::NO_MATCH); |
| 1227 return net::ERR_FAILED; |
| 1228 } |
| 1229 RecordKeySHA256Result(cache_type_, KeySHA256Result::MATCHED); |
| 1230 } else { |
| 1231 RecordKeySHA256Result(cache_type_, KeySHA256Result::NOT_PRESENT); |
| 1232 } |
| 1233 |
| 1234 // Ensure the key is validated before completion. |
| 1235 if (!has_key_sha256 && header_and_key_check_needed_[0]) |
| 1236 CheckHeaderAndKey(0); |
| 1237 |
1122 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); | 1238 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); |
1123 return net::OK; | 1239 return net::OK; |
1124 } | 1240 } |
1125 | 1241 |
1126 int SimpleSynchronousEntry::GetEOFRecordData(int index, | 1242 int SimpleSynchronousEntry::GetEOFRecordData(int index, |
1127 const SimpleEntryStat& entry_stat, | 1243 const SimpleEntryStat& entry_stat, |
1128 bool* out_has_crc32, | 1244 bool* out_has_crc32, |
| 1245 bool* out_has_key_sha256, |
1129 uint32_t* out_crc32, | 1246 uint32_t* out_crc32, |
1130 int* out_data_size) const { | 1247 int* out_data_size) const { |
1131 SimpleFileEOF eof_record; | 1248 SimpleFileEOF eof_record; |
1132 int file_offset = entry_stat.GetEOFOffsetInFile(key_, index); | 1249 int file_offset = entry_stat.GetEOFOffsetInFile(key_.size(), index); |
1133 int file_index = GetFileIndexFromStreamIndex(index); | 1250 int file_index = GetFileIndexFromStreamIndex(index); |
1134 File* file = const_cast<File*>(&files_[file_index]); | 1251 File* file = const_cast<File*>(&files_[file_index]); |
1135 if (file->Read(file_offset, reinterpret_cast<char*>(&eof_record), | 1252 if (file->Read(file_offset, reinterpret_cast<char*>(&eof_record), |
1136 sizeof(eof_record)) != | 1253 sizeof(eof_record)) != |
1137 sizeof(eof_record)) { | 1254 sizeof(eof_record)) { |
1138 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE); | 1255 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE); |
1139 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; | 1256 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; |
1140 } | 1257 } |
1141 | 1258 |
1142 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) { | 1259 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) { |
1143 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH); | 1260 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH); |
1144 DVLOG(1) << "EOF record had bad magic number."; | 1261 DVLOG(1) << "EOF record had bad magic number."; |
1145 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; | 1262 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; |
1146 } | 1263 } |
1147 | 1264 |
1148 *out_has_crc32 = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) == | 1265 *out_has_crc32 = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) == |
1149 SimpleFileEOF::FLAG_HAS_CRC32; | 1266 SimpleFileEOF::FLAG_HAS_CRC32; |
| 1267 *out_has_key_sha256 = |
| 1268 (eof_record.flags & SimpleFileEOF::FLAG_HAS_KEY_SHA256) == |
| 1269 SimpleFileEOF::FLAG_HAS_KEY_SHA256; |
1150 *out_crc32 = eof_record.data_crc32; | 1270 *out_crc32 = eof_record.data_crc32; |
1151 *out_data_size = eof_record.stream_size; | 1271 *out_data_size = eof_record.stream_size; |
1152 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, *out_has_crc32); | 1272 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, *out_has_crc32); |
1153 return net::OK; | 1273 return net::OK; |
1154 } | 1274 } |
1155 | 1275 |
1156 void SimpleSynchronousEntry::Doom() const { | 1276 void SimpleSynchronousEntry::Doom() const { |
1157 DeleteFilesForEntryHash(path_, entry_hash_); | 1277 DeleteFilesForEntryHash(path_, entry_hash_); |
1158 } | 1278 } |
1159 | 1279 |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1467 range.offset = offset; | 1587 range.offset = offset; |
1468 range.length = len; | 1588 range.length = len; |
1469 range.data_crc32 = data_crc32; | 1589 range.data_crc32 = data_crc32; |
1470 range.file_offset = data_file_offset; | 1590 range.file_offset = data_file_offset; |
1471 sparse_ranges_.insert(std::make_pair(offset, range)); | 1591 sparse_ranges_.insert(std::make_pair(offset, range)); |
1472 | 1592 |
1473 return true; | 1593 return true; |
1474 } | 1594 } |
1475 | 1595 |
1476 } // namespace disk_cache | 1596 } // namespace disk_cache |
OLD | NEW |