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

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

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

Powered by Google App Engine
This is Rietveld 408576698