Chromium Code Reviews| 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 } |
| 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 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |