OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/sparse_control.h" | 5 #include "net/disk_cache/sparse_control.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
10 #include "base/time.h" | 10 #include "base/time.h" |
11 #include "net/base/io_buffer.h" | 11 #include "net/base/io_buffer.h" |
12 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
13 #include "net/disk_cache/backend_impl.h" | 13 #include "net/disk_cache/backend_impl.h" |
14 #include "net/disk_cache/entry_impl.h" | 14 #include "net/disk_cache/entry_impl.h" |
15 #include "net/disk_cache/file.h" | 15 #include "net/disk_cache/file.h" |
16 | 16 |
17 using base::Time; | 17 using base::Time; |
18 | 18 |
19 namespace { | 19 namespace { |
20 | 20 |
21 // Stream of the sparse data index. | 21 // Stream of the sparse data index. |
22 const int kSparseIndex = 2; | 22 const int kSparseIndex = 2; |
23 | 23 |
24 // Stream of the sparse data. | 24 // Stream of the sparse data. |
25 const int kSparseData = 1; | 25 const int kSparseData = 1; |
26 | 26 |
27 // We can have up to 64k children. | 27 // We can have up to 64k children. |
28 const int kMaxMapSize = 8 * 1024; | 28 const int kMaxMapSize = 8 * 1024; |
29 | 29 |
| 30 // The maximum number of bytes that a child can store. |
| 31 const int kMaxEntrySize = 0x100000; |
| 32 |
| 33 // The size of each data block (tracked by the child allocation bitmap). |
| 34 const int kBlockSize = 1024; |
| 35 |
30 // Returns the name of of a child entry given the base_name and signature of the | 36 // Returns the name of of a child entry given the base_name and signature of the |
31 // parent and the child_id. | 37 // parent and the child_id. |
32 // If the entry is called entry_name, child entries will be named something | 38 // If the entry is called entry_name, child entries will be named something |
33 // like Range_entry_name:XXX:YYY where XXX is the entry signature and YYY is the | 39 // like Range_entry_name:XXX:YYY where XXX is the entry signature and YYY is the |
34 // number of the particular child. | 40 // number of the particular child. |
35 std::string GenerateChildName(const std::string& base_name, int64 signature, | 41 std::string GenerateChildName(const std::string& base_name, int64 signature, |
36 int64 child_id) { | 42 int64 child_id) { |
37 return StringPrintf("Range_%s:%llx:%llx", base_name.c_str(), signature, | 43 return StringPrintf("Range_%s:%llx:%llx", base_name.c_str(), signature, |
38 child_id); | 44 child_id); |
39 } | 45 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 } | 123 } |
118 std::string child_name = GenerateChildName(name_, signature_, child_id); | 124 std::string child_name = GenerateChildName(name_, signature_, child_id); |
119 backend_->DoomEntry(child_name); | 125 backend_->DoomEntry(child_name); |
120 children_map_.Set(child_id, false); | 126 children_map_.Set(child_id, false); |
121 | 127 |
122 // Post a task to delete the next child. | 128 // Post a task to delete the next child. |
123 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 129 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
124 this, &ChildrenDeleter::DeleteChildren)); | 130 this, &ChildrenDeleter::DeleteChildren)); |
125 } | 131 } |
126 | 132 |
127 } | 133 } // namespace. |
128 | 134 |
129 namespace disk_cache { | 135 namespace disk_cache { |
130 | 136 |
131 SparseControl::~SparseControl() { | 137 SparseControl::~SparseControl() { |
132 if (child_) | 138 if (child_) |
133 CloseChild(); | 139 CloseChild(); |
134 if (init_) | 140 if (init_) |
135 WriteSparseData(); | 141 WriteSparseData(); |
136 } | 142 } |
137 | 143 |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 std::string key = GenerateChildKey(); | 335 std::string key = GenerateChildKey(); |
330 if (child_) { | 336 if (child_) { |
331 // Keep using the same child or open another one?. | 337 // Keep using the same child or open another one?. |
332 if (key == child_->GetKey()) | 338 if (key == child_->GetKey()) |
333 return true; | 339 return true; |
334 CloseChild(); | 340 CloseChild(); |
335 } | 341 } |
336 | 342 |
337 // Se if we are tracking this child. | 343 // Se if we are tracking this child. |
338 bool child_present = ChildPresent(); | 344 bool child_present = ChildPresent(); |
339 if (!child_present) { | 345 if (!child_present || !entry_->backend_->OpenEntry(key, &child_)) |
340 if (kReadOperation == operation_) | 346 return ContinueWithoutChild(key); |
341 return false; | |
342 if (kGetRangeOperation == operation_) | |
343 return true; | |
344 } | |
345 | |
346 if (!child_present || !entry_->backend_->OpenEntry(key, &child_)) { | |
347 if (!entry_->backend_->CreateEntry(key, &child_)) { | |
348 child_ = NULL; | |
349 result_ = net::ERR_CACHE_READ_FAILURE; | |
350 return false; | |
351 } | |
352 // Write signature. | |
353 InitChildData(); | |
354 return true; | |
355 } | |
356 | 347 |
357 EntryImpl* child = static_cast<EntryImpl*>(child_); | 348 EntryImpl* child = static_cast<EntryImpl*>(child_); |
358 if (!(CHILD_ENTRY & child->GetEntryFlags())) { | 349 if (!(CHILD_ENTRY & child->GetEntryFlags()) || |
359 result_ = net::ERR_CACHE_OPERATION_NOT_SUPPORTED; | 350 child->GetDataSize(kSparseIndex) < |
360 return false; | 351 static_cast<int>(sizeof(child_data_))) |
361 } | 352 return KillChildAndContinue(key, false); |
362 | 353 |
363 scoped_refptr<net::WrappedIOBuffer> buf = | 354 scoped_refptr<net::WrappedIOBuffer> buf = |
364 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)); | 355 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)); |
365 | 356 |
366 // Read signature. | 357 // Read signature. |
367 int rv = child_->ReadData(kSparseIndex, 0, buf, sizeof(child_data_), NULL); | 358 int rv = child_->ReadData(kSparseIndex, 0, buf, sizeof(child_data_), NULL); |
368 if (rv != sizeof(child_data_)) { | 359 if (rv != sizeof(child_data_)) |
369 result_ = net::ERR_CACHE_READ_FAILURE; | 360 return KillChildAndContinue(key, true); // This is a fatal failure. |
370 return false; | |
371 } | |
372 | 361 |
373 // TODO(rvargas): Proper error handling and check magic etc. | 362 if (child_data_.header.signature != sparse_header_.signature || |
374 if (child_data_.header.signature != sparse_header_.signature) { | 363 child_data_.header.magic != kIndexMagic) |
375 result_ = net::ERR_CACHE_READ_FAILURE; | 364 return KillChildAndContinue(key, false); |
376 return false; | 365 |
| 366 if (child_data_.header.last_block_len < 0 || |
| 367 child_data_.header.last_block_len > kBlockSize) { |
| 368 // Make sure this values are always within range. |
| 369 child_data_.header.last_block_len = 0; |
| 370 child_data_.header.last_block = -1; |
377 } | 371 } |
378 | 372 |
379 return true; | 373 return true; |
380 } | 374 } |
381 | 375 |
382 void SparseControl::CloseChild() { | 376 void SparseControl::CloseChild() { |
383 scoped_refptr<net::WrappedIOBuffer> buf = | 377 scoped_refptr<net::WrappedIOBuffer> buf = |
384 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)); | 378 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)); |
385 | 379 |
386 // Save the allocation bitmap before closing the child entry. | 380 // Save the allocation bitmap before closing the child entry. |
387 int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_), | 381 int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_), |
388 NULL, false); | 382 NULL, false); |
389 if (rv != sizeof(child_data_)) | 383 if (rv != sizeof(child_data_)) |
390 DLOG(ERROR) << "Failed to save child data"; | 384 DLOG(ERROR) << "Failed to save child data"; |
391 child_->Close(); | 385 child_->Close(); |
392 child_ = NULL; | 386 child_ = NULL; |
393 } | 387 } |
394 | 388 |
395 std::string SparseControl::GenerateChildKey() { | 389 std::string SparseControl::GenerateChildKey() { |
396 return GenerateChildName(entry_->GetKey(), sparse_header_.signature, | 390 return GenerateChildName(entry_->GetKey(), sparse_header_.signature, |
397 offset_ >> 20); | 391 offset_ >> 20); |
398 } | 392 } |
399 | 393 |
| 394 // We are deleting the child because something went wrong. |
| 395 bool SparseControl::KillChildAndContinue(const std::string& key, bool fatal) { |
| 396 SetChildBit(false); |
| 397 child_->Doom(); |
| 398 child_->Close(); |
| 399 child_ = NULL; |
| 400 if (fatal) { |
| 401 result_ = net::ERR_CACHE_READ_FAILURE; |
| 402 return false; |
| 403 } |
| 404 return ContinueWithoutChild(key); |
| 405 } |
| 406 |
| 407 // We were not able to open this child; see what we can do. |
| 408 bool SparseControl::ContinueWithoutChild(const std::string& key) { |
| 409 if (kReadOperation == operation_) |
| 410 return false; |
| 411 if (kGetRangeOperation == operation_) |
| 412 return true; |
| 413 |
| 414 if (!entry_->backend_->CreateEntry(key, &child_)) { |
| 415 child_ = NULL; |
| 416 result_ = net::ERR_CACHE_READ_FAILURE; |
| 417 return false; |
| 418 } |
| 419 // Write signature. |
| 420 InitChildData(); |
| 421 return true; |
| 422 } |
| 423 |
400 bool SparseControl::ChildPresent() { | 424 bool SparseControl::ChildPresent() { |
401 int child_bit = static_cast<int>(offset_ >> 20); | 425 int child_bit = static_cast<int>(offset_ >> 20); |
402 if (children_map_.Size() <= child_bit) | 426 if (children_map_.Size() <= child_bit) |
403 return false; | 427 return false; |
404 | 428 |
405 return children_map_.Get(child_bit); | 429 return children_map_.Get(child_bit); |
406 } | 430 } |
407 | 431 |
408 void SparseControl::SetChildBit() { | 432 void SparseControl::SetChildBit(bool value) { |
409 int child_bit = static_cast<int>(offset_ >> 20); | 433 int child_bit = static_cast<int>(offset_ >> 20); |
410 | 434 |
411 // We may have to increase the bitmap of child entries. | 435 // We may have to increase the bitmap of child entries. |
412 if (children_map_.Size() <= child_bit) | 436 if (children_map_.Size() <= child_bit) |
413 children_map_.Resize(Bitmap::RequiredArraySize(child_bit + 1) * 32, true); | 437 children_map_.Resize(Bitmap::RequiredArraySize(child_bit + 1) * 32, true); |
414 | 438 |
415 children_map_.Set(child_bit, true); | 439 children_map_.Set(child_bit, value); |
416 } | 440 } |
417 | 441 |
418 void SparseControl::WriteSparseData() { | 442 void SparseControl::WriteSparseData() { |
419 scoped_refptr<net::IOBuffer> buf = new net::WrappedIOBuffer( | 443 scoped_refptr<net::IOBuffer> buf = new net::WrappedIOBuffer( |
420 reinterpret_cast<const char*>(children_map_.GetMap())); | 444 reinterpret_cast<const char*>(children_map_.GetMap())); |
421 | 445 |
422 int len = children_map_.ArraySize() * 4; | 446 int len = children_map_.ArraySize() * 4; |
423 int rv = entry_->WriteData(kSparseIndex, sizeof(sparse_header_), buf, len, | 447 int rv = entry_->WriteData(kSparseIndex, sizeof(sparse_header_), buf, len, |
424 NULL, false); | 448 NULL, false); |
425 if (rv != len) { | 449 if (rv != len) { |
426 DLOG(ERROR) << "Unable to save sparse map"; | 450 DLOG(ERROR) << "Unable to save sparse map"; |
427 } | 451 } |
428 } | 452 } |
429 | 453 |
430 bool SparseControl::VerifyRange() { | 454 bool SparseControl::VerifyRange() { |
431 DCHECK_GE(result_, 0); | 455 DCHECK_GE(result_, 0); |
432 | 456 |
433 child_offset_ = static_cast<int>(offset_) & 0xfffff; | 457 child_offset_ = static_cast<int>(offset_) & (kMaxEntrySize - 1); |
434 child_len_ = std::min(buf_len_, 0x100000 - child_offset_); | 458 child_len_ = std::min(buf_len_, kMaxEntrySize - child_offset_); |
435 | 459 |
436 // We can write to (or get info from) anywhere in this child. | 460 // We can write to (or get info from) anywhere in this child. |
437 if (operation_ != kReadOperation) | 461 if (operation_ != kReadOperation) |
438 return true; | 462 return true; |
439 | 463 |
440 // Check that there are no holes in this range. | 464 // Check that there are no holes in this range. |
441 int last_bit = (child_offset_ + child_len_ + 1023) >> 10; | 465 int last_bit = (child_offset_ + child_len_ + 1023) >> 10; |
442 int start = child_offset_ >> 10; | 466 int start = child_offset_ >> 10; |
443 if (child_map_.FindNextBit(&start, last_bit, false)) { | 467 if (child_map_.FindNextBit(&start, last_bit, false)) { |
444 // Something is not here. | 468 // Something is not here. |
445 if (start == child_offset_ >> 10) | 469 DCHECK_GE(child_data_.header.last_block_len, 0); |
446 return false; | 470 DCHECK_LT(child_data_.header.last_block_len, kMaxEntrySize); |
| 471 int partial_block_len = PartialBlockLength(start); |
| 472 if (start == child_offset_ >> 10) { |
| 473 // It looks like we don't have anything. |
| 474 if (partial_block_len <= (child_offset_ & (kBlockSize - 1))) |
| 475 return false; |
| 476 } |
447 | 477 |
448 // We have the first part. | 478 // We have the first part. |
449 // TODO(rvargas): Avoid coming back here again after the actual read. | |
450 child_len_ = (start << 10) - child_offset_; | 479 child_len_ = (start << 10) - child_offset_; |
| 480 if (partial_block_len) { |
| 481 // We may have a few extra bytes. |
| 482 child_len_ = std::min(child_len_ + partial_block_len, buf_len_); |
| 483 } |
| 484 // There is no need to read more after this one. |
| 485 buf_len_ = child_len_; |
451 } | 486 } |
452 return true; | 487 return true; |
453 } | 488 } |
454 | 489 |
455 void SparseControl::UpdateRange(int result) { | 490 void SparseControl::UpdateRange(int result) { |
456 if (result <= 0 || operation_ != kWriteOperation) | 491 if (result <= 0 || operation_ != kWriteOperation) |
457 return; | 492 return; |
458 | 493 |
| 494 DCHECK_GE(child_data_.header.last_block_len, 0); |
| 495 DCHECK_LT(child_data_.header.last_block_len, kMaxEntrySize); |
| 496 |
459 // Write the bitmap. | 497 // Write the bitmap. |
460 int last_bit = (child_offset_ + result + 1023) >> 10; | 498 int first_bit = child_offset_ >> 10; |
461 child_map_.SetRange(child_offset_ >> 10, last_bit, true); | 499 int block_offset = child_offset_ & (kBlockSize - 1); |
| 500 if (block_offset && (child_data_.header.last_block != first_bit || |
| 501 child_data_.header.last_block_len < block_offset)) { |
| 502 // The first block is not completely filled; ignore it. |
| 503 first_bit++; |
| 504 } |
462 | 505 |
463 // TODO(rvargas): Keep track of partial writes so that we don't consider the | 506 int last_bit = (child_offset_ + result) >> 10; |
464 // whole block to be present. | 507 block_offset = (child_offset_ + result) & (kBlockSize - 1); |
| 508 |
| 509 if (block_offset && !child_map_.Get(last_bit)) { |
| 510 // The last block is not completely filled; save it for later. |
| 511 child_data_.header.last_block = last_bit; |
| 512 child_data_.header.last_block_len = block_offset; |
| 513 } else { |
| 514 child_data_.header.last_block = -1; |
| 515 } |
| 516 |
| 517 child_map_.SetRange(first_bit, last_bit, true); |
| 518 } |
| 519 |
| 520 int SparseControl::PartialBlockLength(int block_index) const { |
| 521 if (block_index == child_data_.header.last_block) |
| 522 return child_data_.header.last_block_len; |
| 523 |
| 524 // This may be the last stored index. |
| 525 int entry_len = child_->GetDataSize(kSparseData); |
| 526 if (block_index == entry_len >> 10) |
| 527 return entry_len & (kBlockSize - 1); |
| 528 |
| 529 // This is really empty. |
| 530 return 0; |
465 } | 531 } |
466 | 532 |
467 void SparseControl::InitChildData() { | 533 void SparseControl::InitChildData() { |
468 // We know the real type of child_. | 534 // We know the real type of child_. |
469 EntryImpl* child = static_cast<EntryImpl*>(child_); | 535 EntryImpl* child = static_cast<EntryImpl*>(child_); |
470 child->SetEntryFlags(CHILD_ENTRY); | 536 child->SetEntryFlags(CHILD_ENTRY); |
471 | 537 |
472 memset(&child_data_, 0, sizeof(child_data_)); | 538 memset(&child_data_, 0, sizeof(child_data_)); |
473 child_data_.header = sparse_header_; | 539 child_data_.header = sparse_header_; |
474 | 540 |
475 scoped_refptr<net::WrappedIOBuffer> buf = | 541 scoped_refptr<net::WrappedIOBuffer> buf = |
476 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)); | 542 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)); |
477 | 543 |
478 int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_), | 544 int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_), |
479 NULL, false); | 545 NULL, false); |
480 if (rv != sizeof(child_data_)) | 546 if (rv != sizeof(child_data_)) |
481 DLOG(ERROR) << "Failed to save child data"; | 547 DLOG(ERROR) << "Failed to save child data"; |
482 SetChildBit(); | 548 SetChildBit(true); |
483 } | 549 } |
484 | 550 |
485 void SparseControl::DoChildrenIO() { | 551 void SparseControl::DoChildrenIO() { |
486 while (DoChildIO()) continue; | 552 while (DoChildIO()) continue; |
487 | 553 |
488 if (pending_ && finished_) | 554 if (pending_ && finished_) |
489 DoUserCallback(); | 555 DoUserCallback(); |
490 } | 556 } |
491 | 557 |
492 bool SparseControl::DoChildIO() { | 558 bool SparseControl::DoChildIO() { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 if (!pending_) { | 591 if (!pending_) { |
526 pending_ = true; | 592 pending_ = true; |
527 // The child will protect himself against closing the entry while IO is in | 593 // The child will protect himself against closing the entry while IO is in |
528 // progress. However, this entry can still be closed, and that would not | 594 // progress. However, this entry can still be closed, and that would not |
529 // be a good thing for us, so we increase the refcount until we're | 595 // be a good thing for us, so we increase the refcount until we're |
530 // finished doing sparse stuff. | 596 // finished doing sparse stuff. |
531 entry_->AddRef(); | 597 entry_->AddRef(); |
532 } | 598 } |
533 return false; | 599 return false; |
534 } | 600 } |
| 601 if (!rv) |
| 602 return false; |
535 | 603 |
536 DoChildIOCompleted(rv); | 604 DoChildIOCompleted(rv); |
537 return true; | 605 return true; |
538 } | 606 } |
539 | 607 |
540 int SparseControl::DoGetAvailableRange() { | 608 int SparseControl::DoGetAvailableRange() { |
541 if (!child_) | 609 if (!child_) |
542 return child_len_; // Move on to the next child. | 610 return child_len_; // Move on to the next child. |
543 | 611 |
544 // Check that there are no holes in this range. | 612 // Check that there are no holes in this range. |
545 int last_bit = (child_offset_ + child_len_ + 1023) >> 10; | 613 int last_bit = (child_offset_ + child_len_ + 1023) >> 10; |
546 int start = child_offset_ >> 10; | 614 int start = child_offset_ >> 10; |
| 615 int partial_start_bytes = PartialBlockLength(start); |
547 int bits_found = child_map_.FindBits(&start, last_bit, true); | 616 int bits_found = child_map_.FindBits(&start, last_bit, true); |
548 | 617 |
549 if (!bits_found) | 618 // We don't care if there is a partial block in the middle of the range. |
| 619 int block_offset = child_offset_ & (kBlockSize - 1); |
| 620 if (!bits_found && partial_start_bytes <= block_offset) |
550 return child_len_; | 621 return child_len_; |
551 | 622 |
552 // We are done. Just break the loop and reset result_ to our real result. | 623 // We are done. Just break the loop and reset result_ to our real result. |
553 range_found_ = true; | 624 range_found_ = true; |
554 | 625 |
555 // start now points to the first 1. Lets see if we have zeros before it. | 626 // start now points to the first 1. Lets see if we have zeros before it. |
556 int empty_start = (start << 10) - child_offset_; | 627 int empty_start = (start << 10) - child_offset_; |
557 | 628 |
| 629 int bytes_found = bits_found << 10; |
| 630 bytes_found += PartialBlockLength(start + bits_found); |
| 631 |
558 // If the user is searching past the end of this child, bits_found is the | 632 // If the user is searching past the end of this child, bits_found is the |
559 // right result; otherwise, we have some empty space at the start of this | 633 // right result; otherwise, we have some empty space at the start of this |
560 // query that we have to substarct from the range that we searched. | 634 // query that we have to substarct from the range that we searched. |
561 result_ = std::min(bits_found << 10, child_len_ - empty_start); | 635 result_ = std::min(bytes_found, child_len_ - empty_start); |
| 636 |
| 637 if (!bits_found) { |
| 638 result_ = std::min(partial_start_bytes - block_offset, child_len_); |
| 639 empty_start = 0; |
| 640 } |
562 | 641 |
563 // Only update offset_ when this query found zeros at the start. | 642 // Only update offset_ when this query found zeros at the start. |
564 if (empty_start) | 643 if (empty_start) |
565 offset_ += empty_start; | 644 offset_ += empty_start; |
566 | 645 |
567 // This will actually break the loop. | 646 // This will actually break the loop. |
568 buf_len_ = 0; | 647 buf_len_ = 0; |
569 return 0; | 648 return 0; |
570 } | 649 } |
571 | 650 |
(...skipping 29 matching lines...) Expand all Loading... |
601 net::CompletionCallback* c = user_callback_; | 680 net::CompletionCallback* c = user_callback_; |
602 user_callback_ = NULL; | 681 user_callback_ = NULL; |
603 user_buf_ = NULL; | 682 user_buf_ = NULL; |
604 pending_ = false; | 683 pending_ = false; |
605 operation_ = kNoOperation; | 684 operation_ = kNoOperation; |
606 entry_->Release(); // Don't touch object after this line. | 685 entry_->Release(); // Don't touch object after this line. |
607 c->Run(result_); | 686 c->Run(result_); |
608 } | 687 } |
609 | 688 |
610 } // namespace disk_cache | 689 } // namespace disk_cache |
OLD | NEW |