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> |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 | 139 |
140 } // namespace | 140 } // namespace |
141 | 141 |
142 namespace disk_cache { | 142 namespace disk_cache { |
143 | 143 |
144 using simple_util::ConvertEntryHashKeyToHexString; | 144 using simple_util::ConvertEntryHashKeyToHexString; |
145 using simple_util::GetEntryHashKey; | 145 using simple_util::GetEntryHashKey; |
146 using simple_util::GetFilenameFromEntryHashAndIndex; | 146 using simple_util::GetFilenameFromEntryHashAndIndex; |
147 using simple_util::GetDataSizeFromKeyAndFileSize; | 147 using simple_util::GetDataSizeFromKeyAndFileSize; |
148 using simple_util::GetFileSizeFromKeyAndDataSize; | 148 using simple_util::GetFileSizeFromKeyAndDataSize; |
149 using simple_util::GetFileOffsetFromKeyAndDataOffset; | 149 using simple_util::GetFileIndexFromStreamIndex; |
150 using simple_util::GetMaximumDataOffset; | |
151 using simple_util::GetFileOffsetFromDataOffset; | |
150 | 152 |
151 SimpleEntryStat::SimpleEntryStat() {} | 153 SimpleEntryStat::SimpleEntryStat() {} |
152 | 154 |
153 SimpleEntryStat::SimpleEntryStat(base::Time last_used_p, | 155 SimpleEntryStat::SimpleEntryStat(base::Time last_used_p, |
154 base::Time last_modified_p, | 156 base::Time last_modified_p, |
155 const int32 data_size_p[]) | 157 const int32 data_size_p[]) |
156 : last_used(last_used_p), | 158 : last_used(last_used_p), |
157 last_modified(last_modified_p) { | 159 last_modified(last_modified_p) { |
158 memcpy(data_size, data_size_p, sizeof(data_size)); | 160 memcpy(data_size, data_size_p, sizeof(data_size)); |
159 } | 161 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
199 // static | 201 // static |
200 void SimpleSynchronousEntry::OpenEntry( | 202 void SimpleSynchronousEntry::OpenEntry( |
201 net::CacheType cache_type, | 203 net::CacheType cache_type, |
202 const FilePath& path, | 204 const FilePath& path, |
203 const uint64 entry_hash, | 205 const uint64 entry_hash, |
204 bool had_index, | 206 bool had_index, |
205 SimpleEntryCreationResults *out_results) { | 207 SimpleEntryCreationResults *out_results) { |
206 SimpleSynchronousEntry* sync_entry = | 208 SimpleSynchronousEntry* sync_entry = |
207 new SimpleSynchronousEntry(cache_type, path, "", entry_hash); | 209 new SimpleSynchronousEntry(cache_type, path, "", entry_hash); |
208 out_results->result = sync_entry->InitializeForOpen( | 210 out_results->result = sync_entry->InitializeForOpen( |
209 had_index, &out_results->entry_stat); | 211 had_index, &out_results->entry_stat, &out_results->stream_0_data); |
210 if (out_results->result != net::OK) { | 212 if (out_results->result != net::OK) { |
211 sync_entry->Doom(); | 213 sync_entry->Doom(); |
212 delete sync_entry; | 214 delete sync_entry; |
213 out_results->sync_entry = NULL; | 215 out_results->sync_entry = NULL; |
216 out_results->stream_0_data = NULL; | |
214 return; | 217 return; |
215 } | 218 } |
216 out_results->sync_entry = sync_entry; | 219 out_results->sync_entry = sync_entry; |
217 } | 220 } |
218 | 221 |
219 // static | 222 // static |
220 void SimpleSynchronousEntry::CreateEntry( | 223 void SimpleSynchronousEntry::CreateEntry( |
221 net::CacheType cache_type, | 224 net::CacheType cache_type, |
222 const FilePath& path, | 225 const FilePath& path, |
223 const std::string& key, | 226 const std::string& key, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
272 const FilePath& path) { | 275 const FilePath& path) { |
273 const size_t did_delete_count = std::count_if( | 276 const size_t did_delete_count = std::count_if( |
274 key_hashes->begin(), key_hashes->end(), std::bind1st( | 277 key_hashes->begin(), key_hashes->end(), std::bind1st( |
275 std::ptr_fun(SimpleSynchronousEntry::DeleteFilesForEntryHash), path)); | 278 std::ptr_fun(SimpleSynchronousEntry::DeleteFilesForEntryHash), path)); |
276 return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED; | 279 return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED; |
277 } | 280 } |
278 | 281 |
279 void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op, | 282 void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op, |
280 net::IOBuffer* out_buf, | 283 net::IOBuffer* out_buf, |
281 uint32* out_crc32, | 284 uint32* out_crc32, |
282 base::Time* out_last_used, | 285 SimpleEntryStat* out_entry_stat, |
283 int* out_result) const { | 286 int* out_result) const { |
284 DCHECK(initialized_); | 287 DCHECK(initialized_); |
285 int64 file_offset = | 288 int64 file_offset = GetFileOffsetFromDataOffset( |
286 GetFileOffsetFromKeyAndDataOffset(key_, in_entry_op.offset); | 289 key_, |
287 int bytes_read = ReadPlatformFile(files_[in_entry_op.index], | 290 in_entry_op.offset, |
288 file_offset, | 291 in_entry_op.index, |
289 out_buf->data(), | 292 out_entry_stat->data_size[1]); |
290 in_entry_op.buf_len); | 293 int file_index = GetFileIndexFromStreamIndex(in_entry_op.index); |
294 int bytes_read = ReadPlatformFile( | |
295 files_[file_index], file_offset, out_buf->data(), in_entry_op.buf_len); | |
291 if (bytes_read > 0) { | 296 if (bytes_read > 0) { |
292 *out_last_used = Time::Now(); | 297 out_entry_stat->last_used = Time::Now(); |
293 *out_crc32 = crc32(crc32(0L, Z_NULL, 0), | 298 *out_crc32 = crc32(crc32(0L, Z_NULL, 0), |
294 reinterpret_cast<const Bytef*>(out_buf->data()), | 299 reinterpret_cast<const Bytef*>(out_buf->data()), |
295 bytes_read); | 300 bytes_read); |
296 } | 301 } |
297 if (bytes_read >= 0) { | 302 if (bytes_read >= 0) { |
298 *out_result = bytes_read; | 303 *out_result = bytes_read; |
299 } else { | 304 } else { |
300 *out_result = net::ERR_CACHE_READ_FAILURE; | 305 *out_result = net::ERR_CACHE_READ_FAILURE; |
301 Doom(); | 306 Doom(); |
302 } | 307 } |
303 } | 308 } |
304 | 309 |
305 void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op, | 310 void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op, |
306 net::IOBuffer* in_buf, | 311 net::IOBuffer* in_buf, |
307 SimpleEntryStat* out_entry_stat, | 312 SimpleEntryStat* out_entry_stat, |
308 int* out_result) const { | 313 int* out_result) const { |
309 DCHECK(initialized_); | 314 DCHECK(initialized_); |
310 int index = in_entry_op.index; | 315 int index = in_entry_op.index; |
316 int file_index = GetFileIndexFromStreamIndex(index); | |
311 int offset = in_entry_op.offset; | 317 int offset = in_entry_op.offset; |
312 int buf_len = in_entry_op.buf_len; | 318 int buf_len = in_entry_op.buf_len; |
313 int truncate = in_entry_op.truncate; | 319 int truncate = in_entry_op.truncate; |
314 | 320 const int64 file_offset = GetFileOffsetFromDataOffset( |
321 key_, offset, index, out_entry_stat->data_size[1]); | |
315 bool extending_by_write = offset + buf_len > out_entry_stat->data_size[index]; | 322 bool extending_by_write = offset + buf_len > out_entry_stat->data_size[index]; |
316 if (extending_by_write) { | 323 if (extending_by_write) { |
317 // We are extending the file, and need to insure the EOF record is zeroed. | 324 // The EOF record and the eventual stream afterward need to be zeroed out. |
318 const int64 file_eof_offset = GetFileOffsetFromKeyAndDataOffset( | 325 const int64 file_eof_offset = GetFileOffsetFromDataOffset( |
319 key_, out_entry_stat->data_size[index]); | 326 key_, out_entry_stat->data_size[index], |
320 if (!TruncatePlatformFile(files_[index], file_eof_offset)) { | 327 index, out_entry_stat->data_size[1]); |
328 if (!TruncatePlatformFile(files_[file_index], file_eof_offset)) { | |
321 RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE); | 329 RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE); |
322 Doom(); | 330 Doom(); |
323 *out_result = net::ERR_CACHE_WRITE_FAILURE; | 331 *out_result = net::ERR_CACHE_WRITE_FAILURE; |
324 return; | 332 return; |
325 } | 333 } |
326 } | 334 } |
327 const int64 file_offset = GetFileOffsetFromKeyAndDataOffset(key_, offset); | |
328 if (buf_len > 0) { | 335 if (buf_len > 0) { |
329 if (WritePlatformFile( | 336 if (WritePlatformFile( |
330 files_[index], file_offset, in_buf->data(), buf_len) != buf_len) { | 337 files_[file_index], file_offset, in_buf->data(), buf_len) != |
338 buf_len) { | |
331 RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE); | 339 RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE); |
332 Doom(); | 340 Doom(); |
333 *out_result = net::ERR_CACHE_WRITE_FAILURE; | 341 *out_result = net::ERR_CACHE_WRITE_FAILURE; |
334 return; | 342 return; |
335 } | 343 } |
336 } | 344 } |
337 if (!truncate && (buf_len > 0 || !extending_by_write)) { | 345 if (!truncate && (buf_len > 0 || !extending_by_write)) { |
338 out_entry_stat->data_size[index] = | 346 out_entry_stat->data_size[index] = |
339 std::max(out_entry_stat->data_size[index], offset + buf_len); | 347 std::max(out_entry_stat->data_size[index], offset + buf_len); |
340 } else { | 348 } else { |
341 if (!TruncatePlatformFile(files_[index], file_offset + buf_len)) { | 349 out_entry_stat->data_size[index] = offset + buf_len; |
350 int file_max_offset = GetFileOffsetFromDataOffset( | |
351 key_, | |
352 GetMaximumDataOffset(file_index, out_entry_stat->data_size), | |
353 index, | |
354 out_entry_stat->data_size[1]); | |
355 if (!TruncatePlatformFile(files_[file_index], file_max_offset)) { | |
342 RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE); | 356 RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE); |
343 Doom(); | 357 Doom(); |
344 *out_result = net::ERR_CACHE_WRITE_FAILURE; | 358 *out_result = net::ERR_CACHE_WRITE_FAILURE; |
345 return; | 359 return; |
346 } | 360 } |
347 out_entry_stat->data_size[index] = offset + buf_len; | |
348 } | 361 } |
349 | 362 |
350 RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS); | 363 RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS); |
351 out_entry_stat->last_used = out_entry_stat->last_modified = Time::Now(); | 364 out_entry_stat->last_used = out_entry_stat->last_modified = Time::Now(); |
352 *out_result = buf_len; | 365 *out_result = buf_len; |
353 } | 366 } |
354 | 367 |
355 void SimpleSynchronousEntry::CheckEOFRecord(int index, | 368 void SimpleSynchronousEntry::CheckEOFRecord(int index, |
356 int32 data_size, | 369 const int32 data_size[], |
357 uint32 expected_crc32, | 370 uint32 expected_crc32, |
358 int* out_result) const { | 371 int* out_result) const { |
359 DCHECK(initialized_); | 372 DCHECK(initialized_); |
360 | 373 *out_result = CheckEOFRecordInternal(index, data_size, expected_crc32); |
361 SimpleFileEOF eof_record; | 374 if (*out_result != net::OK) |
362 int64 file_offset = GetFileOffsetFromKeyAndDataOffset(key_, data_size); | |
363 if (ReadPlatformFile(files_[index], | |
364 file_offset, | |
365 reinterpret_cast<char*>(&eof_record), | |
366 sizeof(eof_record)) != sizeof(eof_record)) { | |
367 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE); | |
368 Doom(); | 375 Doom(); |
369 *out_result = net::ERR_CACHE_CHECKSUM_READ_FAILURE; | |
370 return; | |
371 } | |
372 | |
373 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) { | |
374 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH); | |
375 DLOG(INFO) << "eof record had bad magic number."; | |
376 Doom(); | |
377 *out_result = net::ERR_CACHE_CHECKSUM_READ_FAILURE; | |
378 return; | |
379 } | |
380 | |
381 const bool has_crc = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) == | |
382 SimpleFileEOF::FLAG_HAS_CRC32; | |
383 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, has_crc); | |
384 if (has_crc && eof_record.data_crc32 != expected_crc32) { | |
385 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); | |
386 DLOG(INFO) << "eof record had bad crc."; | |
387 Doom(); | |
388 *out_result = net::ERR_CACHE_CHECKSUM_MISMATCH; | |
389 return; | |
390 } | |
391 | |
392 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); | |
393 *out_result = net::OK; | |
394 } | 376 } |
395 | 377 |
396 void SimpleSynchronousEntry::Close( | 378 void SimpleSynchronousEntry::Close( |
397 const SimpleEntryStat& entry_stat, | 379 const SimpleEntryStat& entry_stat, |
398 scoped_ptr<std::vector<CRCRecord> > crc32s_to_write) { | 380 scoped_ptr<std::vector<CRCRecord> > crc32s_to_write, |
381 net::GrowableIOBuffer* stream_0_data) { | |
382 if (!stream_0_data) { | |
383 if (entry_stat.data_size[0]) | |
384 Doom(); | |
385 } else { | |
386 // Write stream 0 data. | |
387 int stream_0_offset = | |
388 GetFileOffsetFromDataOffset(key_, 0, 0, entry_stat.data_size[1]); | |
389 if (WritePlatformFile(files_[0], | |
390 stream_0_offset, | |
391 stream_0_data->data(), | |
392 entry_stat.data_size[0]) != entry_stat.data_size[0]) { | |
393 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); | |
394 DLOG(INFO) << "Could not write stream 0 data."; | |
395 Doom(); | |
396 } | |
397 } | |
398 // Write updated header for stream 0 and stream 1 file. | |
399 if (WriteHeader(0, entry_stat.data_size[0], entry_stat.data_size[1]) != | |
400 net::OK) { | |
401 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); | |
402 DLOG(INFO) << "Could not write updated header."; | |
403 Doom(); | |
404 } | |
405 | |
399 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); | 406 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); |
400 it != crc32s_to_write->end(); ++it) { | 407 it != crc32s_to_write->end(); ++it) { |
401 SimpleFileEOF eof_record; | 408 SimpleFileEOF eof_record; |
409 int index = it->index; | |
402 eof_record.final_magic_number = kSimpleFinalMagicNumber; | 410 eof_record.final_magic_number = kSimpleFinalMagicNumber; |
403 eof_record.flags = 0; | 411 eof_record.flags = 0; |
404 if (it->has_crc32) | 412 if (it->has_crc32) |
405 eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32; | 413 eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32; |
406 eof_record.data_crc32 = it->data_crc32; | 414 eof_record.data_crc32 = it->data_crc32; |
407 int64 file_offset = GetFileOffsetFromKeyAndDataOffset( | 415 int file_index = GetFileIndexFromStreamIndex(index); |
408 key_, entry_stat.data_size[it->index]); | 416 int64 file_offset = GetFileOffsetFromDataOffset( |
409 if (WritePlatformFile(files_[it->index], | 417 key_, entry_stat.data_size[index], index, entry_stat.data_size[1]); |
418 if (WritePlatformFile(files_[file_index], | |
410 file_offset, | 419 file_offset, |
411 reinterpret_cast<const char*>(&eof_record), | 420 reinterpret_cast<const char*>(&eof_record), |
412 sizeof(eof_record)) != sizeof(eof_record)) { | 421 sizeof(eof_record)) != sizeof(eof_record)) { |
413 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); | 422 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); |
414 DLOG(INFO) << "Could not write eof record."; | 423 DLOG(INFO) << "Could not write eof record."; |
415 Doom(); | 424 Doom(); |
416 break; | 425 break; |
417 } | 426 } |
418 const int64 file_size = file_offset + sizeof(eof_record); | 427 } |
428 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | |
429 bool did_close_file = ClosePlatformFile(files_[i]); | |
430 CHECK(did_close_file); | |
431 const int64 file_size = GetFileSizeFromKeyAndDataSize( | |
432 key_, GetMaximumDataOffset(i, entry_stat.data_size)); | |
419 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, | 433 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, |
420 "LastClusterSize", cache_type_, | 434 "LastClusterSize", cache_type_, |
421 file_size % 4096, 0, 4097, 50); | 435 file_size % 4096, 0, 4097, 50); |
422 const int64 cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0; | 436 const int64 cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0; |
423 SIMPLE_CACHE_UMA(PERCENTAGE, | 437 SIMPLE_CACHE_UMA(PERCENTAGE, |
424 "LastClusterLossPercent", cache_type_, | 438 "LastClusterLossPercent", cache_type_, |
425 cluster_loss * 100 / (cluster_loss + file_size)); | 439 cluster_loss * 100 / (cluster_loss + file_size)); |
426 } | 440 } |
427 | |
428 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | |
429 bool did_close_file = ClosePlatformFile(files_[i]); | |
430 CHECK(did_close_file); | |
431 } | |
432 RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS); | 441 RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS); |
433 have_open_files_ = false; | 442 have_open_files_ = false; |
434 delete this; | 443 delete this; |
435 } | 444 } |
436 | 445 |
437 SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type, | 446 SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type, |
438 const FilePath& path, | 447 const FilePath& path, |
439 const std::string& key, | 448 const std::string& key, |
440 const uint64 entry_hash) | 449 const uint64 entry_hash) |
441 : cache_type_(cache_type), | 450 : cache_type_(cache_type), |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
510 DLOG_IF(INFO, !did_close) << "Could not close file " | 519 DLOG_IF(INFO, !did_close) << "Could not close file " |
511 << filename.MaybeAsASCII(); | 520 << filename.MaybeAsASCII(); |
512 } | 521 } |
513 return false; | 522 return false; |
514 } | 523 } |
515 } | 524 } |
516 | 525 |
517 have_open_files_ = true; | 526 have_open_files_ = true; |
518 if (create) { | 527 if (create) { |
519 out_entry_stat->last_modified = out_entry_stat->last_used = Time::Now(); | 528 out_entry_stat->last_modified = out_entry_stat->last_used = Time::Now(); |
520 for (int i = 0; i < kSimpleEntryFileCount; ++i) | 529 for (int i = 0; i < kSimpleEntryStreamCount; ++i) |
521 out_entry_stat->data_size[i] = 0; | 530 out_entry_stat->data_size[i] = 0; |
522 } else { | 531 } else { |
523 base::TimeDelta entry_age = base::Time::Now() - base::Time::UnixEpoch(); | 532 base::TimeDelta entry_age = base::Time::Now() - base::Time::UnixEpoch(); |
524 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | 533 for (int i = 0; i < kSimpleEntryFileCount; ++i) { |
525 PlatformFileInfo file_info; | 534 PlatformFileInfo file_info; |
526 bool success = GetPlatformFileInfo(files_[i], &file_info); | 535 bool success = GetPlatformFileInfo(files_[i], &file_info); |
527 base::Time file_last_modified; | 536 base::Time file_last_modified; |
528 if (!success) { | 537 if (!success) { |
529 DLOG(WARNING) << "Could not get platform file info."; | 538 DLOG(WARNING) << "Could not get platform file info."; |
530 continue; | 539 continue; |
531 } | 540 } |
532 out_entry_stat->last_used = file_info.last_accessed; | 541 out_entry_stat->last_used = file_info.last_accessed; |
533 if (simple_util::GetMTime(path_, &file_last_modified)) | 542 if (simple_util::GetMTime(path_, &file_last_modified)) |
534 out_entry_stat->last_modified = file_last_modified; | 543 out_entry_stat->last_modified = file_last_modified; |
535 else | 544 else |
536 out_entry_stat->last_modified = file_info.last_modified; | 545 out_entry_stat->last_modified = file_info.last_modified; |
537 | 546 |
538 base::TimeDelta stream_age = | 547 base::TimeDelta stream_age = |
539 base::Time::Now() - out_entry_stat->last_modified; | 548 base::Time::Now() - out_entry_stat->last_modified; |
540 if (stream_age < entry_age) | 549 if (stream_age < entry_age) |
541 entry_age = stream_age; | 550 entry_age = stream_age; |
542 | 551 |
543 // Keep the file size in |data size_| briefly until the key is initialized | 552 // Keep the file size in |data size_| temporarily until the data sizes are |
544 // properly. | 553 // initialized correctly. |
545 out_entry_stat->data_size[i] = file_info.size; | 554 out_entry_stat->data_size[i + 1] = file_info.size; |
546 } | 555 } |
547 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, | 556 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, |
548 "SyncOpenEntryAge", cache_type_, | 557 "SyncOpenEntryAge", cache_type_, |
549 entry_age.InHours(), 1, 1000, 50); | 558 entry_age.InHours(), 1, 1000, 50); |
550 } | 559 } |
551 | 560 |
552 return true; | 561 return true; |
553 } | 562 } |
554 | 563 |
555 void SimpleSynchronousEntry::CloseFiles() { | 564 void SimpleSynchronousEntry::CloseFiles() { |
556 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | 565 for (int i = 0; i < kSimpleEntryFileCount; ++i) { |
557 DCHECK_NE(kInvalidPlatformFileValue, files_[i]); | 566 DCHECK_NE(kInvalidPlatformFileValue, files_[i]); |
558 bool did_close = ClosePlatformFile(files_[i]); | 567 bool did_close = ClosePlatformFile(files_[i]); |
559 DCHECK(did_close); | 568 DCHECK(did_close); |
560 } | 569 } |
561 } | 570 } |
562 | 571 |
563 int SimpleSynchronousEntry::InitializeForOpen(bool had_index, | 572 int SimpleSynchronousEntry::InitializeForOpen( |
564 SimpleEntryStat* out_entry_stat) { | 573 bool had_index, |
574 SimpleEntryStat* out_entry_stat, | |
575 scoped_refptr<net::GrowableIOBuffer>* stream_0_data) { | |
565 DCHECK(!initialized_); | 576 DCHECK(!initialized_); |
566 if (!OpenOrCreateFiles(false, had_index, out_entry_stat)) | 577 if (!OpenOrCreateFiles(false, had_index, out_entry_stat)) |
567 return net::ERR_FAILED; | 578 return net::ERR_FAILED; |
568 | 579 |
569 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | 580 for (int i = 0; i < kSimpleEntryFileCount; ++i) { |
570 SimpleFileHeader header; | 581 SimpleFileHeader header; |
571 int header_read_result = | 582 int header_read_result = |
572 ReadPlatformFile(files_[i], 0, reinterpret_cast<char*>(&header), | 583 ReadPlatformFile(files_[i], 0, reinterpret_cast<char*>(&header), |
573 sizeof(header)); | 584 sizeof(header)); |
574 if (header_read_result != sizeof(header)) { | 585 if (header_read_result != sizeof(header)) { |
(...skipping 20 matching lines...) Expand all Loading... | |
595 scoped_ptr<char[]> key(new char[header.key_length]); | 606 scoped_ptr<char[]> key(new char[header.key_length]); |
596 int key_read_result = ReadPlatformFile(files_[i], sizeof(header), | 607 int key_read_result = ReadPlatformFile(files_[i], sizeof(header), |
597 key.get(), header.key_length); | 608 key.get(), header.key_length); |
598 if (key_read_result != implicit_cast<int>(header.key_length)) { | 609 if (key_read_result != implicit_cast<int>(header.key_length)) { |
599 DLOG(WARNING) << "Cannot read key from entry."; | 610 DLOG(WARNING) << "Cannot read key from entry."; |
600 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_KEY, had_index); | 611 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_KEY, had_index); |
601 return net::ERR_FAILED; | 612 return net::ERR_FAILED; |
602 } | 613 } |
603 | 614 |
604 key_ = std::string(key.get(), header.key_length); | 615 key_ = std::string(key.get(), header.key_length); |
605 out_entry_stat->data_size[i] = | 616 // The data size needs to be updated. For stream 0 and 1 it is included in |
606 GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size[i]); | 617 // the header, for stream 2 it is computed from the file size temporarily |
607 if (out_entry_stat->data_size[i] < 0) { | 618 // stored in |out_entry_stat|. |
608 // This entry can't possibly be valid, as it does not have enough space to | 619 int data_size_current_file = 0; |
609 // store a valid SimpleFileEOF record. | 620 int min_data_size = 0; |
621 if (i == 0) { | |
622 // File size for stream 0 has been stored temporarily in data_size[1]. | |
623 data_size_current_file = | |
624 GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size[1]); | |
625 min_data_size = | |
626 header.stream_0_size + header.stream_1_size + sizeof(SimpleFileEOF); | |
627 out_entry_stat->data_size[0] = header.stream_0_size; | |
pasko
2013/09/13 19:09:21
Keeping in mind what index is for what would be ha
clamy
2013/09/16 15:01:17
- I am not sure about the GetDataSize(stream_index
| |
628 out_entry_stat->data_size[1] = header.stream_1_size; | |
629 } else { | |
630 out_entry_stat->data_size[2] = | |
631 GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size[2]); | |
632 data_size_current_file = out_entry_stat->data_size[2]; | |
633 } | |
634 if (data_size_current_file < min_data_size) | |
610 return net::ERR_FAILED; | 635 return net::ERR_FAILED; |
611 } | |
612 | 636 |
613 if (base::Hash(key.get(), header.key_length) != header.key_hash) { | 637 if (base::Hash(key.get(), header.key_length) != header.key_hash) { |
614 DLOG(WARNING) << "Hash mismatch on key."; | 638 DLOG(WARNING) << "Hash mismatch on key."; |
615 RecordSyncOpenResult( | 639 RecordSyncOpenResult( |
616 cache_type_, OPEN_ENTRY_KEY_HASH_MISMATCH, had_index); | 640 cache_type_, OPEN_ENTRY_KEY_HASH_MISMATCH, had_index); |
617 return net::ERR_FAILED; | 641 return net::ERR_FAILED; |
618 } | 642 } |
643 | |
644 // Stream 0 needs to be read and put in memory | |
645 if (i == 0) { | |
646 *stream_0_data = NULL; | |
647 if (header.stream_0_size == 0) | |
648 break; | |
649 int ret_value_stream_0 = | |
650 ReadAndValidateStream0(out_entry_stat->data_size, stream_0_data); | |
651 if (ret_value_stream_0 != net::OK) | |
652 return ret_value_stream_0; | |
653 } | |
619 } | 654 } |
620 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index); | 655 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index); |
621 initialized_ = true; | 656 initialized_ = true; |
622 return net::OK; | 657 return net::OK; |
623 } | 658 } |
624 | 659 |
625 int SimpleSynchronousEntry::InitializeForCreate( | 660 int SimpleSynchronousEntry::InitializeForCreate( |
626 bool had_index, | 661 bool had_index, |
627 SimpleEntryStat* out_entry_stat) { | 662 SimpleEntryStat* out_entry_stat) { |
628 DCHECK(!initialized_); | 663 DCHECK(!initialized_); |
629 if (!OpenOrCreateFiles(true, had_index, out_entry_stat)) { | 664 if (!OpenOrCreateFiles(true, had_index, out_entry_stat)) { |
630 DLOG(WARNING) << "Could not create platform files."; | 665 DLOG(WARNING) << "Could not create platform files."; |
631 return net::ERR_FILE_EXISTS; | 666 return net::ERR_FILE_EXISTS; |
632 } | 667 } |
633 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | 668 for (int i = 0; i < kSimpleEntryFileCount; ++i) { |
634 SimpleFileHeader header; | 669 if (WriteHeader(i, 0, 0) != net::OK) { |
635 header.initial_magic_number = kSimpleInitialMagicNumber; | |
636 header.version = kSimpleVersion; | |
637 | |
638 header.key_length = key_.size(); | |
639 header.key_hash = base::Hash(key_); | |
640 | |
641 if (WritePlatformFile(files_[i], 0, reinterpret_cast<char*>(&header), | |
642 sizeof(header)) != sizeof(header)) { | |
643 DLOG(WARNING) << "Could not write headers to new cache entry."; | |
644 RecordSyncCreateResult( | 670 RecordSyncCreateResult( |
645 cache_type_, CREATE_ENTRY_CANT_WRITE_HEADER, had_index); | 671 cache_type_, CREATE_ENTRY_CANT_WRITE_HEADER, had_index); |
646 return net::ERR_FAILED; | 672 return net::ERR_FAILED; |
647 } | 673 } |
648 | 674 |
649 if (WritePlatformFile(files_[i], sizeof(header), key_.data(), | 675 if (WritePlatformFile( |
650 key_.size()) != implicit_cast<int>(key_.size())) { | 676 files_[i], sizeof(SimpleFileHeader), key_.data(), key_.size()) != |
677 implicit_cast<int>(key_.size())) { | |
651 DLOG(WARNING) << "Could not write keys to new cache entry."; | 678 DLOG(WARNING) << "Could not write keys to new cache entry."; |
652 RecordSyncCreateResult( | 679 RecordSyncCreateResult( |
653 cache_type_, CREATE_ENTRY_CANT_WRITE_KEY, had_index); | 680 cache_type_, CREATE_ENTRY_CANT_WRITE_KEY, had_index); |
654 return net::ERR_FAILED; | 681 return net::ERR_FAILED; |
655 } | 682 } |
656 } | 683 } |
657 RecordSyncCreateResult(cache_type_, CREATE_ENTRY_SUCCESS, had_index); | 684 RecordSyncCreateResult(cache_type_, CREATE_ENTRY_SUCCESS, had_index); |
658 initialized_ = true; | 685 initialized_ = true; |
659 return net::OK; | 686 return net::OK; |
660 } | 687 } |
661 | 688 |
689 int SimpleSynchronousEntry::ReadAndValidateStream0( | |
690 int data_size[], | |
691 scoped_refptr<net::GrowableIOBuffer>* stream_0_data) const { | |
692 *stream_0_data = new net::GrowableIOBuffer(); | |
693 (*stream_0_data)->SetCapacity(data_size[0]); | |
694 int64 file_offset = GetFileOffsetFromDataOffset(key_, 0, 0, data_size[1]); | |
695 int bytes_read = ReadPlatformFile( | |
696 files_[0], file_offset, (*stream_0_data)->data(), data_size[0]); | |
697 if (bytes_read != data_size[0]) | |
698 return net::ERR_FAILED; | |
699 // Check the CRC32. | |
700 uint32 expected_crc32 = | |
701 crc32(crc32(0L, Z_NULL, 0), | |
702 reinterpret_cast<const Bytef*>((*stream_0_data)->data()), | |
703 data_size[0]); | |
704 return CheckEOFRecordInternal(0, data_size, expected_crc32); | |
705 } | |
706 | |
707 int SimpleSynchronousEntry::WriteHeader(int file_index, | |
708 int stream_0_size, | |
709 int stream_1_size) const { | |
710 SimpleFileHeader header; | |
711 header.initial_magic_number = kSimpleInitialMagicNumber; | |
712 header.version = kSimpleVersion; | |
713 | |
714 header.key_length = key_.size(); | |
715 header.key_hash = base::Hash(key_); | |
716 header.stream_0_size = stream_0_size; | |
717 header.stream_1_size = stream_1_size; | |
718 | |
719 if (WritePlatformFile(files_[file_index], | |
720 0, | |
721 reinterpret_cast<char*>(&header), | |
722 sizeof(header)) != sizeof(header)) { | |
723 DLOG(WARNING) << "Could not write cache file header to cache entry."; | |
724 return net::ERR_FAILED; | |
725 } | |
726 return net::OK; | |
727 } | |
728 | |
729 int SimpleSynchronousEntry::CheckEOFRecordInternal( | |
730 int index, | |
731 const int data_size[], | |
732 uint32 expected_crc32) const { | |
733 SimpleFileEOF eof_record; | |
734 int64 file_offset = | |
735 GetFileOffsetFromDataOffset(key_, data_size[index], index, data_size[1]); | |
736 int file_index = GetFileIndexFromStreamIndex(index); | |
737 if (ReadPlatformFile(files_[file_index], | |
738 file_offset, | |
739 reinterpret_cast<char*>(&eof_record), | |
740 sizeof(eof_record)) != sizeof(eof_record)) { | |
741 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE); | |
742 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; | |
743 } | |
744 | |
745 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) { | |
746 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH); | |
747 DLOG(INFO) << "Eof record had bad magic number."; | |
748 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; | |
749 } | |
750 | |
751 const bool has_crc = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) == | |
752 SimpleFileEOF::FLAG_HAS_CRC32; | |
753 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, has_crc); | |
754 if (has_crc && eof_record.data_crc32 != expected_crc32) { | |
755 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); | |
756 DLOG(INFO) << "Eof record had bad crc."; | |
757 return net::ERR_CACHE_CHECKSUM_MISMATCH; | |
758 } | |
759 | |
760 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); | |
761 return net::OK; | |
762 } | |
763 | |
662 void SimpleSynchronousEntry::Doom() const { | 764 void SimpleSynchronousEntry::Doom() const { |
663 // TODO(gavinp): Consider if we should guard against redundant Doom() calls. | 765 // TODO(gavinp): Consider if we should guard against redundant Doom() calls. |
664 DeleteFilesForEntryHash(path_, entry_hash_); | 766 DeleteFilesForEntryHash(path_, entry_hash_); |
665 } | 767 } |
666 | 768 |
667 } // namespace disk_cache | 769 } // namespace disk_cache |
OLD | NEW |