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

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: Changes in the crc32 handling 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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 134
135 void RecordCloseResult(net::CacheType cache_type, CloseResult result) { 135 void RecordCloseResult(net::CacheType cache_type, CloseResult result) {
136 SIMPLE_CACHE_UMA(ENUMERATION, 136 SIMPLE_CACHE_UMA(ENUMERATION,
137 "SyncCloseResult", cache_type, result, WRITE_RESULT_MAX); 137 "SyncCloseResult", cache_type, result, WRITE_RESULT_MAX);
138 } 138 }
139 139
140 } // namespace 140 } // namespace
141 141
142 namespace disk_cache { 142 namespace disk_cache {
143 143
144 using simple_util::ConvertEntryHashKeyToHexString;
145 using simple_util::GetEntryHashKey; 144 using simple_util::GetEntryHashKey;
146 using simple_util::GetFilenameFromEntryHashAndIndex; 145 using simple_util::GetFilenameFromEntryHashAndFileIndex;
147 using simple_util::GetDataSizeFromKeyAndFileSize; 146 using simple_util::GetDataSizeFromKeyAndFileSize;
148 using simple_util::GetFileSizeFromKeyAndDataSize; 147 using simple_util::GetFileSizeFromKeyAndDataSize;
149 using simple_util::GetFileOffsetFromKeyAndDataOffset; 148 using simple_util::GetFileIndexFromStreamIndex;
150 149
151 SimpleEntryStat::SimpleEntryStat() {} 150 SimpleEntryStat::SimpleEntryStat(base::Time last_used,
151 base::Time last_modified,
152 const int32 data_size[])
153 : last_used_(last_used),
154 last_modified_(last_modified) {
155 memcpy(data_size_, data_size, sizeof(data_size_));
156 }
152 157
153 SimpleEntryStat::SimpleEntryStat(base::Time last_used_p, 158 int SimpleEntryStat::GetOffsetInFile(const std::string& key,
154 base::Time last_modified_p, 159 int offset,
155 const int32 data_size_p[]) 160 int stream_index) const {
156 : last_used(last_used_p), 161 const int64 headers_size = sizeof(SimpleFileHeader) + key.size();
157 last_modified(last_modified_p) { 162 const int64 additional_offset =
158 memcpy(data_size, data_size_p, sizeof(data_size)); 163 stream_index == 0 ? data_size_[1] + sizeof(SimpleFileEOF) : 0;
164 return headers_size + offset + additional_offset;
165 }
166
167 int SimpleEntryStat::GetEOFOffsetInFile(const std::string& key,
168 int stream_index) const {
169 return GetOffsetInFile(key, data_size_[stream_index], stream_index);
170 }
171
172 int SimpleEntryStat::GetLastEOFOffsetInFile(const std::string& key,
173 int stream_index) const {
174 const int file_index = GetFileIndexFromStreamIndex(stream_index);
175 const int eof_data_offset =
176 file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF)
177 : data_size_[2];
178 return GetOffsetInFile(key, eof_data_offset, stream_index);
179 }
180
181 int SimpleEntryStat::GetFileSize(const std::string& key, int file_index) const {
182 const int total_data_size =
183 file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF)
184 : data_size_[2];
185 return GetFileSizeFromKeyAndDataSize(key, total_data_size);
159 } 186 }
160 187
161 SimpleEntryCreationResults::SimpleEntryCreationResults( 188 SimpleEntryCreationResults::SimpleEntryCreationResults(
162 SimpleEntryStat entry_stat) 189 SimpleEntryStat entry_stat)
163 : sync_entry(NULL), 190 : sync_entry(NULL),
164 entry_stat(entry_stat), 191 entry_stat(entry_stat),
192 stream_0_crc32(crc32(0, Z_NULL, 0)),
165 result(net::OK) { 193 result(net::OK) {
166 } 194 }
167 195
168 SimpleEntryCreationResults::~SimpleEntryCreationResults() { 196 SimpleEntryCreationResults::~SimpleEntryCreationResults() {
169 } 197 }
170 198
171 SimpleSynchronousEntry::CRCRecord::CRCRecord() : index(-1), 199 SimpleSynchronousEntry::CRCRecord::CRCRecord() : index(-1),
172 has_crc32(false), 200 has_crc32(false),
173 data_crc32(0) { 201 data_crc32(0) {
174 } 202 }
(...skipping 23 matching lines...) Expand all
198 226
199 // static 227 // static
200 void SimpleSynchronousEntry::OpenEntry( 228 void SimpleSynchronousEntry::OpenEntry(
201 net::CacheType cache_type, 229 net::CacheType cache_type,
202 const FilePath& path, 230 const FilePath& path,
203 const uint64 entry_hash, 231 const uint64 entry_hash,
204 bool had_index, 232 bool had_index,
205 SimpleEntryCreationResults *out_results) { 233 SimpleEntryCreationResults *out_results) {
206 SimpleSynchronousEntry* sync_entry = 234 SimpleSynchronousEntry* sync_entry =
207 new SimpleSynchronousEntry(cache_type, path, "", entry_hash); 235 new SimpleSynchronousEntry(cache_type, path, "", entry_hash);
208 out_results->result = sync_entry->InitializeForOpen( 236 out_results->result =
209 had_index, &out_results->entry_stat); 237 sync_entry->InitializeForOpen(had_index,
238 &out_results->entry_stat,
239 &out_results->stream_0_data,
240 &out_results->stream_0_crc32);
210 if (out_results->result != net::OK) { 241 if (out_results->result != net::OK) {
211 sync_entry->Doom(); 242 sync_entry->Doom();
212 delete sync_entry; 243 delete sync_entry;
213 out_results->sync_entry = NULL; 244 out_results->sync_entry = NULL;
245 out_results->stream_0_data = NULL;
214 return; 246 return;
215 } 247 }
216 out_results->sync_entry = sync_entry; 248 out_results->sync_entry = sync_entry;
217 } 249 }
218 250
219 // static 251 // static
220 void SimpleSynchronousEntry::CreateEntry( 252 void SimpleSynchronousEntry::CreateEntry(
221 net::CacheType cache_type, 253 net::CacheType cache_type,
222 const FilePath& path, 254 const FilePath& path,
223 const std::string& key, 255 const std::string& key,
(...skipping 15 matching lines...) Expand all
239 out_results->sync_entry = sync_entry; 271 out_results->sync_entry = sync_entry;
240 } 272 }
241 273
242 // TODO(gavinp): Move this function to its correct location in this .cc file. 274 // TODO(gavinp): Move this function to its correct location in this .cc file.
243 // static 275 // static
244 bool SimpleSynchronousEntry::DeleteFilesForEntryHash( 276 bool SimpleSynchronousEntry::DeleteFilesForEntryHash(
245 const FilePath& path, 277 const FilePath& path,
246 const uint64 entry_hash) { 278 const uint64 entry_hash) {
247 bool result = true; 279 bool result = true;
248 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 280 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
249 FilePath to_delete = path.AppendASCII( 281 FilePath to_delete =
250 GetFilenameFromEntryHashAndIndex(entry_hash, i)); 282 path.AppendASCII(GetFilenameFromEntryHashAndFileIndex(entry_hash, i));
251 if (!base::DeleteFile(to_delete, false)) { 283 if (!base::DeleteFile(to_delete, false)) {
252 result = false; 284 result = false;
253 DLOG(ERROR) << "Could not delete " << to_delete.MaybeAsASCII(); 285 DLOG(ERROR) << "Could not delete " << to_delete.MaybeAsASCII();
254 } 286 }
255 } 287 }
256 return result; 288 return result;
257 } 289 }
258 290
259 // static 291 // static
260 int SimpleSynchronousEntry::DoomEntry( 292 int SimpleSynchronousEntry::DoomEntry(
(...skipping 11 matching lines...) Expand all
272 const FilePath& path) { 304 const FilePath& path) {
273 const size_t did_delete_count = std::count_if( 305 const size_t did_delete_count = std::count_if(
274 key_hashes->begin(), key_hashes->end(), std::bind1st( 306 key_hashes->begin(), key_hashes->end(), std::bind1st(
275 std::ptr_fun(SimpleSynchronousEntry::DeleteFilesForEntryHash), path)); 307 std::ptr_fun(SimpleSynchronousEntry::DeleteFilesForEntryHash), path));
276 return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED; 308 return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED;
277 } 309 }
278 310
279 void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op, 311 void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op,
280 net::IOBuffer* out_buf, 312 net::IOBuffer* out_buf,
281 uint32* out_crc32, 313 uint32* out_crc32,
282 base::Time* out_last_used, 314 SimpleEntryStat* out_entry_stat,
283 int* out_result) const { 315 int* out_result) const {
284 DCHECK(initialized_); 316 DCHECK(initialized_);
285 int64 file_offset = 317 DCHECK_NE(0, in_entry_op.index);
286 GetFileOffsetFromKeyAndDataOffset(key_, in_entry_op.offset); 318 const int64 file_offset = out_entry_stat->GetOffsetInFile(
287 int bytes_read = ReadPlatformFile(files_[in_entry_op.index], 319 key_, in_entry_op.offset, in_entry_op.index);
288 file_offset, 320 int file_index = GetFileIndexFromStreamIndex(in_entry_op.index);
289 out_buf->data(), 321 int bytes_read = ReadPlatformFile(
290 in_entry_op.buf_len); 322 files_[file_index], file_offset, out_buf->data(), in_entry_op.buf_len);
291 if (bytes_read > 0) { 323 if (bytes_read > 0) {
292 *out_last_used = Time::Now(); 324 out_entry_stat->set_last_used(Time::Now());
293 *out_crc32 = crc32(crc32(0L, Z_NULL, 0), 325 *out_crc32 = crc32(crc32(0L, Z_NULL, 0),
294 reinterpret_cast<const Bytef*>(out_buf->data()), 326 reinterpret_cast<const Bytef*>(out_buf->data()),
295 bytes_read); 327 bytes_read);
296 } 328 }
297 if (bytes_read >= 0) { 329 if (bytes_read >= 0) {
298 *out_result = bytes_read; 330 *out_result = bytes_read;
299 } else { 331 } else {
300 *out_result = net::ERR_CACHE_READ_FAILURE; 332 *out_result = net::ERR_CACHE_READ_FAILURE;
301 Doom(); 333 Doom();
302 } 334 }
303 } 335 }
304 336
305 void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op, 337 void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op,
306 net::IOBuffer* in_buf, 338 net::IOBuffer* in_buf,
307 SimpleEntryStat* out_entry_stat, 339 SimpleEntryStat* out_entry_stat,
308 int* out_result) const { 340 int* out_result) const {
309 DCHECK(initialized_); 341 DCHECK(initialized_);
342 DCHECK_NE(0, in_entry_op.index);
310 int index = in_entry_op.index; 343 int index = in_entry_op.index;
344 int file_index = GetFileIndexFromStreamIndex(index);
311 int offset = in_entry_op.offset; 345 int offset = in_entry_op.offset;
312 int buf_len = in_entry_op.buf_len; 346 int buf_len = in_entry_op.buf_len;
313 int truncate = in_entry_op.truncate; 347 int truncate = in_entry_op.truncate;
314 348 const int64 file_offset = out_entry_stat->GetOffsetInFile(
315 bool extending_by_write = offset + buf_len > out_entry_stat->data_size[index]; 349 key_, in_entry_op.offset, in_entry_op.index);
350 bool extending_by_write = offset + buf_len > out_entry_stat->data_size(index);
316 if (extending_by_write) { 351 if (extending_by_write) {
317 // We are extending the file, and need to insure the EOF record is zeroed. 352 // The EOF record and the eventual stream afterward need to be zeroed out.
318 const int64 file_eof_offset = GetFileOffsetFromKeyAndDataOffset( 353 const int64 file_eof_offset =
319 key_, out_entry_stat->data_size[index]); 354 out_entry_stat->GetEOFOffsetInFile(key_, index);
320 if (!TruncatePlatformFile(files_[index], file_eof_offset)) { 355 if (!TruncatePlatformFile(files_[file_index], file_eof_offset)) {
321 RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE); 356 RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE);
322 Doom(); 357 Doom();
323 *out_result = net::ERR_CACHE_WRITE_FAILURE; 358 *out_result = net::ERR_CACHE_WRITE_FAILURE;
324 return; 359 return;
325 } 360 }
326 } 361 }
327 const int64 file_offset = GetFileOffsetFromKeyAndDataOffset(key_, offset);
328 if (buf_len > 0) { 362 if (buf_len > 0) {
329 if (WritePlatformFile( 363 if (WritePlatformFile(
330 files_[index], file_offset, in_buf->data(), buf_len) != buf_len) { 364 files_[file_index], file_offset, in_buf->data(), buf_len) !=
365 buf_len) {
331 RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE); 366 RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE);
332 Doom(); 367 Doom();
333 *out_result = net::ERR_CACHE_WRITE_FAILURE; 368 *out_result = net::ERR_CACHE_WRITE_FAILURE;
334 return; 369 return;
335 } 370 }
336 } 371 }
337 if (!truncate && (buf_len > 0 || !extending_by_write)) { 372 if (!truncate && (buf_len > 0 || !extending_by_write)) {
338 out_entry_stat->data_size[index] = 373 out_entry_stat->set_data_size(
339 std::max(out_entry_stat->data_size[index], offset + buf_len); 374 index, std::max(out_entry_stat->data_size(index), offset + buf_len));
340 } else { 375 } else {
341 if (!TruncatePlatformFile(files_[index], file_offset + buf_len)) { 376 out_entry_stat->set_data_size(index, offset + buf_len);
377 int file_eof_offset = out_entry_stat->GetLastEOFOffsetInFile(key_, index);
378 if (!TruncatePlatformFile(files_[file_index], file_eof_offset)) {
342 RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE); 379 RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE);
343 Doom(); 380 Doom();
344 *out_result = net::ERR_CACHE_WRITE_FAILURE; 381 *out_result = net::ERR_CACHE_WRITE_FAILURE;
345 return; 382 return;
346 } 383 }
347 out_entry_stat->data_size[index] = offset + buf_len;
348 } 384 }
349 385
350 RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS); 386 RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS);
351 out_entry_stat->last_used = out_entry_stat->last_modified = Time::Now(); 387 base::Time modification_time = Time::Now();
388 out_entry_stat->set_last_used(modification_time);
389 out_entry_stat->set_last_modified(modification_time);
352 *out_result = buf_len; 390 *out_result = buf_len;
353 } 391 }
354 392
355 void SimpleSynchronousEntry::CheckEOFRecord(int index, 393 void SimpleSynchronousEntry::CheckEOFRecord(int index,
356 int32 data_size, 394 const SimpleEntryStat& entry_stat,
357 uint32 expected_crc32, 395 uint32 expected_crc32,
358 int* out_result) const { 396 int* out_result) const {
359 DCHECK(initialized_); 397 DCHECK(initialized_);
360 398 uint32 crc32;
361 SimpleFileEOF eof_record; 399 bool has_crc32;
362 int64 file_offset = GetFileOffsetFromKeyAndDataOffset(key_, data_size); 400 int stream_size;
363 if (ReadPlatformFile(files_[index], 401 *out_result =
364 file_offset, 402 GetEOFRecordData(index, entry_stat, &has_crc32, &crc32, &stream_size);
365 reinterpret_cast<char*>(&eof_record), 403 if (*out_result != net::OK) {
366 sizeof(eof_record)) != sizeof(eof_record)) {
367 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE);
368 Doom(); 404 Doom();
369 *out_result = net::ERR_CACHE_CHECKSUM_READ_FAILURE;
370 return; 405 return;
371 } 406 }
372 407 if (has_crc32 && crc32 != expected_crc32) {
373 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) { 408 DLOG(INFO) << "EOF record had bad crc.";
374 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH); 409 *out_result = net::ERR_CACHE_CHECKSUM_MISMATCH;
375 DLOG(INFO) << "eof record had bad magic number."; 410 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
376 Doom(); 411 Doom();
377 *out_result = net::ERR_CACHE_CHECKSUM_READ_FAILURE;
378 return; 412 return;
379 } 413 }
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); 414 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
393 *out_result = net::OK;
394 } 415 }
395 416
396 void SimpleSynchronousEntry::Close( 417 void SimpleSynchronousEntry::Close(
397 const SimpleEntryStat& entry_stat, 418 const SimpleEntryStat& entry_stat,
398 scoped_ptr<std::vector<CRCRecord> > crc32s_to_write) { 419 scoped_ptr<std::vector<CRCRecord> > crc32s_to_write,
420 net::GrowableIOBuffer* stream_0_data) {
421 DCHECK(stream_0_data);
422 // Write stream 0 data.
423 int stream_0_offset = entry_stat.GetOffsetInFile(key_, 0, 0);
424 if (WritePlatformFile(files_[0],
425 stream_0_offset,
426 stream_0_data->data(),
427 entry_stat.data_size(0)) != entry_stat.data_size(0)) {
428 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
429 DLOG(INFO) << "Could not write stream 0 data.";
430 Doom();
431 }
432
399 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); 433 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin();
400 it != crc32s_to_write->end(); ++it) { 434 it != crc32s_to_write->end(); ++it) {
401 SimpleFileEOF eof_record; 435 SimpleFileEOF eof_record;
436 int index = it->index;
437 eof_record.stream_size = entry_stat.data_size(index);
402 eof_record.final_magic_number = kSimpleFinalMagicNumber; 438 eof_record.final_magic_number = kSimpleFinalMagicNumber;
403 eof_record.flags = 0; 439 eof_record.flags = 0;
404 if (it->has_crc32) 440 if (it->has_crc32)
405 eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32; 441 eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32;
406 eof_record.data_crc32 = it->data_crc32; 442 eof_record.data_crc32 = it->data_crc32;
407 int64 file_offset = GetFileOffsetFromKeyAndDataOffset( 443 int file_index = GetFileIndexFromStreamIndex(index);
408 key_, entry_stat.data_size[it->index]); 444 int eof_offset = entry_stat.GetEOFOffsetInFile(key_, index);
409 if (WritePlatformFile(files_[it->index], 445 // If stream 0 changed size, the file needs to be resized, otherwise the
410 file_offset, 446 // next open will yield wrong stream sizes. On stream 1 and stream 2 proper
447 // resizing of the file is handled in SimpleSynchronousEntry::WriteData.
pasko 2013/09/18 16:53:56 Nice comment. WriteData() (with parentheses) looks
clamy 2013/09/18 17:20:46 Done.
448 if (index == 0 && !TruncatePlatformFile(files_[file_index], eof_offset)) {
449 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
450 DLOG(INFO) << "Could not truncate stream 0 file.";
451 Doom();
452 break;
453 }
454 if (WritePlatformFile(files_[file_index],
455 eof_offset,
411 reinterpret_cast<const char*>(&eof_record), 456 reinterpret_cast<const char*>(&eof_record),
412 sizeof(eof_record)) != sizeof(eof_record)) { 457 sizeof(eof_record)) != sizeof(eof_record)) {
413 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); 458 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
414 DLOG(INFO) << "Could not write eof record."; 459 DLOG(INFO) << "Could not write eof record.";
415 Doom(); 460 Doom();
416 break; 461 break;
417 } 462 }
418 const int64 file_size = file_offset + sizeof(eof_record); 463 }
464 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
465 bool did_close_file = ClosePlatformFile(files_[i]);
466 DCHECK(did_close_file);
467 const int64 file_size = entry_stat.GetFileSize(key_, i);
419 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, 468 SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
420 "LastClusterSize", cache_type_, 469 "LastClusterSize", cache_type_,
421 file_size % 4096, 0, 4097, 50); 470 file_size % 4096, 0, 4097, 50);
422 const int64 cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0; 471 const int64 cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0;
423 SIMPLE_CACHE_UMA(PERCENTAGE, 472 SIMPLE_CACHE_UMA(PERCENTAGE,
424 "LastClusterLossPercent", cache_type_, 473 "LastClusterLossPercent", cache_type_,
425 cluster_loss * 100 / (cluster_loss + file_size)); 474 cluster_loss * 100 / (cluster_loss + file_size));
426 } 475 }
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); 476 RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS);
433 have_open_files_ = false; 477 have_open_files_ = false;
434 delete this; 478 delete this;
435 } 479 }
436 480
437 SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type, 481 SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type,
438 const FilePath& path, 482 const FilePath& path,
439 const std::string& key, 483 const std::string& key,
440 const uint64 entry_hash) 484 const uint64 entry_hash)
441 : cache_type_(cache_type), 485 : cache_type_(cache_type),
(...skipping 11 matching lines...) Expand all
453 DCHECK(!(have_open_files_ && initialized_)); 497 DCHECK(!(have_open_files_ && initialized_));
454 if (have_open_files_) 498 if (have_open_files_)
455 CloseFiles(); 499 CloseFiles();
456 } 500 }
457 501
458 bool SimpleSynchronousEntry::OpenOrCreateFiles( 502 bool SimpleSynchronousEntry::OpenOrCreateFiles(
459 bool create, 503 bool create,
460 bool had_index, 504 bool had_index,
461 SimpleEntryStat* out_entry_stat) { 505 SimpleEntryStat* out_entry_stat) {
462 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 506 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
463 FilePath filename = path_.AppendASCII( 507 FilePath filename =
464 GetFilenameFromEntryHashAndIndex(entry_hash_, i)); 508 path_.AppendASCII(GetFilenameFromEntryHashAndFileIndex(entry_hash_, i));
465 int flags = PLATFORM_FILE_READ | PLATFORM_FILE_WRITE; 509 int flags = PLATFORM_FILE_READ | PLATFORM_FILE_WRITE;
466 if (create) 510 if (create)
467 flags |= PLATFORM_FILE_CREATE; 511 flags |= PLATFORM_FILE_CREATE;
468 else 512 else
469 flags |= PLATFORM_FILE_OPEN; 513 flags |= PLATFORM_FILE_OPEN;
470 PlatformFileError error; 514 PlatformFileError error;
471 files_[i] = CreatePlatformFile(filename, flags, NULL, &error); 515 files_[i] = CreatePlatformFile(filename, flags, NULL, &error);
472 if (error != PLATFORM_FILE_OK) { 516 if (error != PLATFORM_FILE_OK) {
473 // TODO(ttuttle,gavinp): Remove one each of these triplets of histograms. 517 // TODO(ttuttle,gavinp): Remove one each of these triplets of histograms.
474 // We can calculate the third as the sum or difference of the other two. 518 // We can calculate the third as the sum or difference of the other two.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 bool ALLOW_UNUSED did_close = ClosePlatformFile(files_[i]); 553 bool ALLOW_UNUSED did_close = ClosePlatformFile(files_[i]);
510 DLOG_IF(INFO, !did_close) << "Could not close file " 554 DLOG_IF(INFO, !did_close) << "Could not close file "
511 << filename.MaybeAsASCII(); 555 << filename.MaybeAsASCII();
512 } 556 }
513 return false; 557 return false;
514 } 558 }
515 } 559 }
516 560
517 have_open_files_ = true; 561 have_open_files_ = true;
518 if (create) { 562 if (create) {
519 out_entry_stat->last_modified = out_entry_stat->last_used = Time::Now(); 563 base::Time creation_time = Time::Now();
520 for (int i = 0; i < kSimpleEntryFileCount; ++i) 564 out_entry_stat->set_last_modified(creation_time);
521 out_entry_stat->data_size[i] = 0; 565 out_entry_stat->set_last_used(creation_time);
566 for (int i = 0; i < kSimpleEntryStreamCount; ++i)
567 out_entry_stat->set_data_size(i, 0);
522 } else { 568 } else {
523 base::TimeDelta entry_age = base::Time::Now() - base::Time::UnixEpoch(); 569 base::TimeDelta entry_age = base::Time::Now() - base::Time::UnixEpoch();
524 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 570 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
525 PlatformFileInfo file_info; 571 PlatformFileInfo file_info;
526 bool success = GetPlatformFileInfo(files_[i], &file_info); 572 bool success = GetPlatformFileInfo(files_[i], &file_info);
527 base::Time file_last_modified; 573 base::Time file_last_modified;
528 if (!success) { 574 if (!success) {
529 DLOG(WARNING) << "Could not get platform file info."; 575 DLOG(WARNING) << "Could not get platform file info.";
530 continue; 576 continue;
531 } 577 }
532 out_entry_stat->last_used = file_info.last_accessed; 578 out_entry_stat->set_last_used(file_info.last_accessed);
533 if (simple_util::GetMTime(path_, &file_last_modified)) 579 if (simple_util::GetMTime(path_, &file_last_modified))
534 out_entry_stat->last_modified = file_last_modified; 580 out_entry_stat->set_last_modified(file_last_modified);
535 else 581 else
536 out_entry_stat->last_modified = file_info.last_modified; 582 out_entry_stat->set_last_modified(file_info.last_modified);
537 583
538 base::TimeDelta stream_age = 584 base::TimeDelta stream_age =
539 base::Time::Now() - out_entry_stat->last_modified; 585 base::Time::Now() - out_entry_stat->last_modified();
540 if (stream_age < entry_age) 586 if (stream_age < entry_age)
541 entry_age = stream_age; 587 entry_age = stream_age;
542 588
543 // Keep the file size in |data size_| briefly until the key is initialized 589 // Two things prevent from knowing the right values for |data_size|:
544 // properly. 590 // 1) The key is not known, hence its length is unknown.
545 out_entry_stat->data_size[i] = file_info.size; 591 // 2) Stream 0 and stream 1 are in the same file, and the exact size for
592 // each will only be known when reading the EOF record for stream 0.
593 //
594 // The size for file 0 and 1 is temporarily kept in
595 // |data_size(1)| and |data_size(2)| respectively. Reading the key in
596 // InitializeForOpen yields the data size for each file. In the case of
597 // file hash_1, this is the total size of stream 2, and is assigned to
598 // data_size(2). In the case of file 0, it is the combined size of stream
599 // 0, stream 1 and one EOF record. The exact distribution of sizes between
600 // stream 1 and stream 0 is only determined after reading the EOF record
601 // for stream 0 in ReadAndValidateStream0.
602 out_entry_stat->set_data_size(i + 1, file_info.size);
546 } 603 }
547 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, 604 SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
548 "SyncOpenEntryAge", cache_type_, 605 "SyncOpenEntryAge", cache_type_,
549 entry_age.InHours(), 1, 1000, 50); 606 entry_age.InHours(), 1, 1000, 50);
550 } 607 }
551 608
552 return true; 609 return true;
553 } 610 }
554 611
555 void SimpleSynchronousEntry::CloseFiles() { 612 void SimpleSynchronousEntry::CloseFiles() {
556 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 613 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
557 DCHECK_NE(kInvalidPlatformFileValue, files_[i]); 614 DCHECK_NE(kInvalidPlatformFileValue, files_[i]);
558 bool did_close = ClosePlatformFile(files_[i]); 615 bool did_close = ClosePlatformFile(files_[i]);
559 DCHECK(did_close); 616 DCHECK(did_close);
560 } 617 }
561 } 618 }
562 619
563 int SimpleSynchronousEntry::InitializeForOpen(bool had_index, 620 int SimpleSynchronousEntry::InitializeForOpen(
564 SimpleEntryStat* out_entry_stat) { 621 bool had_index,
622 SimpleEntryStat* out_entry_stat,
623 scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
624 uint32* out_stream_0_crc32) {
565 DCHECK(!initialized_); 625 DCHECK(!initialized_);
566 if (!OpenOrCreateFiles(false, had_index, out_entry_stat)) 626 if (!OpenOrCreateFiles(false, had_index, out_entry_stat))
567 return net::ERR_FAILED; 627 return net::ERR_FAILED;
568
569 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 628 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
570 SimpleFileHeader header; 629 SimpleFileHeader header;
571 int header_read_result = 630 int header_read_result =
572 ReadPlatformFile(files_[i], 0, reinterpret_cast<char*>(&header), 631 ReadPlatformFile(files_[i], 0, reinterpret_cast<char*>(&header),
573 sizeof(header)); 632 sizeof(header));
574 if (header_read_result != sizeof(header)) { 633 if (header_read_result != sizeof(header)) {
575 DLOG(WARNING) << "Cannot read header from entry."; 634 DLOG(WARNING) << "Cannot read header from entry.";
576 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_HEADER, had_index); 635 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_HEADER, had_index);
577 return net::ERR_FAILED; 636 return net::ERR_FAILED;
578 } 637 }
(...skipping 16 matching lines...) Expand all
595 scoped_ptr<char[]> key(new char[header.key_length]); 654 scoped_ptr<char[]> key(new char[header.key_length]);
596 int key_read_result = ReadPlatformFile(files_[i], sizeof(header), 655 int key_read_result = ReadPlatformFile(files_[i], sizeof(header),
597 key.get(), header.key_length); 656 key.get(), header.key_length);
598 if (key_read_result != implicit_cast<int>(header.key_length)) { 657 if (key_read_result != implicit_cast<int>(header.key_length)) {
599 DLOG(WARNING) << "Cannot read key from entry."; 658 DLOG(WARNING) << "Cannot read key from entry.";
600 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_KEY, had_index); 659 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_KEY, had_index);
601 return net::ERR_FAILED; 660 return net::ERR_FAILED;
602 } 661 }
603 662
604 key_ = std::string(key.get(), header.key_length); 663 key_ = std::string(key.get(), header.key_length);
605 out_entry_stat->data_size[i] = 664 if (i == 0) {
606 GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size[i]); 665 // File size for stream 0 has been stored temporarily in data_size[1].
607 if (out_entry_stat->data_size[i] < 0) { 666 int total_data_size =
608 // This entry can't possibly be valid, as it does not have enough space to 667 GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size(1));
609 // store a valid SimpleFileEOF record. 668 int ret_value_stream_0 = ReadAndValidateStream0(
610 return net::ERR_FAILED; 669 total_data_size, out_entry_stat, stream_0_data, out_stream_0_crc32);
670 if (ret_value_stream_0 != net::OK)
671 return ret_value_stream_0;
672 } else {
673 out_entry_stat->set_data_size(
674 2, GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size(2)));
675 if (out_entry_stat->data_size(2) < 0)
676 return net::ERR_FAILED;
611 } 677 }
612 678
613 if (base::Hash(key.get(), header.key_length) != header.key_hash) { 679 if (base::Hash(key.get(), header.key_length) != header.key_hash) {
614 DLOG(WARNING) << "Hash mismatch on key."; 680 DLOG(WARNING) << "Hash mismatch on key.";
615 RecordSyncOpenResult( 681 RecordSyncOpenResult(
616 cache_type_, OPEN_ENTRY_KEY_HASH_MISMATCH, had_index); 682 cache_type_, OPEN_ENTRY_KEY_HASH_MISMATCH, had_index);
617 return net::ERR_FAILED; 683 return net::ERR_FAILED;
618 } 684 }
619 } 685 }
620 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index); 686 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index);
(...skipping 10 matching lines...) Expand all
631 return net::ERR_FILE_EXISTS; 697 return net::ERR_FILE_EXISTS;
632 } 698 }
633 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 699 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
634 SimpleFileHeader header; 700 SimpleFileHeader header;
635 header.initial_magic_number = kSimpleInitialMagicNumber; 701 header.initial_magic_number = kSimpleInitialMagicNumber;
636 header.version = kSimpleVersion; 702 header.version = kSimpleVersion;
637 703
638 header.key_length = key_.size(); 704 header.key_length = key_.size();
639 header.key_hash = base::Hash(key_); 705 header.key_hash = base::Hash(key_);
640 706
641 if (WritePlatformFile(files_[i], 0, reinterpret_cast<char*>(&header), 707 if (WritePlatformFile(
642 sizeof(header)) != sizeof(header)) { 708 files_[i], 0, reinterpret_cast<char*>(&header), sizeof(header)) !=
643 DLOG(WARNING) << "Could not write headers to new cache entry."; 709 sizeof(header)) {
710 DLOG(WARNING) << "Could not write cache file header to cache entry.";
644 RecordSyncCreateResult( 711 RecordSyncCreateResult(
645 cache_type_, CREATE_ENTRY_CANT_WRITE_HEADER, had_index); 712 cache_type_, CREATE_ENTRY_CANT_WRITE_HEADER, had_index);
646 return net::ERR_FAILED; 713 return net::ERR_FAILED;
647 } 714 }
648 715
649 if (WritePlatformFile(files_[i], sizeof(header), key_.data(), 716 if (WritePlatformFile(
650 key_.size()) != implicit_cast<int>(key_.size())) { 717 files_[i], sizeof(SimpleFileHeader), key_.data(), key_.size()) !=
718 implicit_cast<int>(key_.size())) {
651 DLOG(WARNING) << "Could not write keys to new cache entry."; 719 DLOG(WARNING) << "Could not write keys to new cache entry.";
652 RecordSyncCreateResult( 720 RecordSyncCreateResult(
653 cache_type_, CREATE_ENTRY_CANT_WRITE_KEY, had_index); 721 cache_type_, CREATE_ENTRY_CANT_WRITE_KEY, had_index);
654 return net::ERR_FAILED; 722 return net::ERR_FAILED;
655 } 723 }
656 } 724 }
657 RecordSyncCreateResult(cache_type_, CREATE_ENTRY_SUCCESS, had_index); 725 RecordSyncCreateResult(cache_type_, CREATE_ENTRY_SUCCESS, had_index);
658 initialized_ = true; 726 initialized_ = true;
659 return net::OK; 727 return net::OK;
660 } 728 }
661 729
730 int SimpleSynchronousEntry::ReadAndValidateStream0(
731 int total_data_size,
732 SimpleEntryStat* out_entry_stat,
733 scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
734 uint32* out_stream_0_crc32) const {
735 // Temporarily assign all the data size to stream 1 in order to read the
736 // EOF record for stream 0, which contains the size of stream 0.
737 out_entry_stat->set_data_size(0, 0);
738 out_entry_stat->set_data_size(1, total_data_size - sizeof(SimpleFileEOF));
739
740 bool has_crc32;
741 uint32 read_crc32;
742 int stream_0_size;
743 int ret_value_crc32 = GetEOFRecordData(
744 0, *out_entry_stat, &has_crc32, &read_crc32, &stream_0_size);
745 if (ret_value_crc32 != net::OK)
746 return ret_value_crc32;
747
748 if (stream_0_size > out_entry_stat->data_size(1))
749 return net::ERR_FAILED;
750
751 // These are the real values of data size.
752 out_entry_stat->set_data_size(0, stream_0_size);
753 out_entry_stat->set_data_size(
754 1, out_entry_stat->data_size(1) - stream_0_size);
755
756 // Put stream 0 data in memory.
757 *stream_0_data = new net::GrowableIOBuffer();
758 (*stream_0_data)->SetCapacity(stream_0_size);
759 int file_offset = out_entry_stat->GetOffsetInFile(key_, 0, 0);
760 int bytes_read = ReadPlatformFile(
761 files_[0], file_offset, (*stream_0_data)->data(), stream_0_size);
762 if (bytes_read != stream_0_size)
763 return net::ERR_FAILED;
764
765 // Check the CRC32.
766 uint32 expected_crc32 =
767 stream_0_size == 0
768 ? crc32(0, Z_NULL, 0)
769 : crc32(crc32(0, Z_NULL, 0),
770 reinterpret_cast<const Bytef*>((*stream_0_data)->data()),
771 stream_0_size);
772 if (has_crc32 && read_crc32 != expected_crc32) {
773 DLOG(INFO) << "EOF record had bad crc.";
774 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
775 return net::ERR_FAILED;
776 }
777 *out_stream_0_crc32 = read_crc32;
778 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
779 return net::OK;
780 }
781
782 int SimpleSynchronousEntry::GetEOFRecordData(int index,
783 const SimpleEntryStat& entry_stat,
784 bool* out_has_crc32,
785 uint32* out_crc32,
786 int* out_data_size) const {
787 SimpleFileEOF eof_record;
788 int file_offset = entry_stat.GetEOFOffsetInFile(key_, index);
789 int file_index = GetFileIndexFromStreamIndex(index);
790 if (ReadPlatformFile(files_[file_index],
791 file_offset,
792 reinterpret_cast<char*>(&eof_record),
793 sizeof(eof_record)) != sizeof(eof_record)) {
794 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE);
795 return net::ERR_CACHE_CHECKSUM_READ_FAILURE;
796 }
797
798 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) {
799 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH);
800 DLOG(INFO) << "EOF record had bad magic number.";
801 return net::ERR_CACHE_CHECKSUM_READ_FAILURE;
802 }
803
804 *out_has_crc32 = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) ==
805 SimpleFileEOF::FLAG_HAS_CRC32;
806 *out_crc32 = eof_record.data_crc32;
807 *out_data_size = eof_record.stream_size;
808 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, *out_has_crc32);
809 return net::OK;
810 }
811
662 void SimpleSynchronousEntry::Doom() const { 812 void SimpleSynchronousEntry::Doom() const {
663 // TODO(gavinp): Consider if we should guard against redundant Doom() calls. 813 // TODO(gavinp): Consider if we should guard against redundant Doom() calls.
664 DeleteFilesForEntryHash(path_, entry_hash_); 814 DeleteFilesForEntryHash(path_, entry_hash_);
665 } 815 }
666 816
667 } // namespace disk_cache 817 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698