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

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

Powered by Google App Engine
This is Rietveld 408576698