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

Side by Side Diff: net/disk_cache/sparse_control.cc

Issue 155590: Disk cache: Add support for having a sparse entry block that... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « net/disk_cache/sparse_control.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/disk_cache/sparse_control.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698