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

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

Issue 23983005: SimpleCache: merge the first and second stream in one file (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Switched to GrowableIOBuffer Created 7 years, 3 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>
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698