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 "content/browser/indexed_db/indexed_db_backing_store.h" | 5 #include "content/browser/indexed_db/indexed_db_backing_store.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 // though that may be costly. Still, database/directory deletion should always | 558 // though that may be costly. Still, database/directory deletion should always |
559 // clean things up, and we can write an fsck that will do a full correction if | 559 // clean things up, and we can write an fsck that will do a full correction if |
560 // need be. | 560 // need be. |
561 | 561 |
562 // Read and decode the specified blob journal via the supplied transaction. | 562 // Read and decode the specified blob journal via the supplied transaction. |
563 // The key must be either the primary journal key or live journal key. | 563 // The key must be either the primary journal key or live journal key. |
564 template <typename TransactionType> | 564 template <typename TransactionType> |
565 static leveldb::Status GetBlobJournal(const StringPiece& key, | 565 static leveldb::Status GetBlobJournal(const StringPiece& key, |
566 TransactionType* transaction, | 566 TransactionType* transaction, |
567 BlobJournalType* journal) { | 567 BlobJournalType* journal) { |
| 568 IDB_TRACE("IndexedDBBackingStore::GetBlobJournal"); |
568 std::string data; | 569 std::string data; |
569 bool found = false; | 570 bool found = false; |
570 leveldb::Status s = transaction->Get(key, &data, &found); | 571 leveldb::Status s = transaction->Get(key, &data, &found); |
571 if (!s.ok()) { | 572 if (!s.ok()) { |
572 INTERNAL_READ_ERROR(READ_BLOB_JOURNAL); | 573 INTERNAL_READ_ERROR(READ_BLOB_JOURNAL); |
573 return s; | 574 return s; |
574 } | 575 } |
575 journal->clear(); | 576 journal->clear(); |
576 if (!found || data.empty()) | 577 if (!found || data.empty()) |
577 return leveldb::Status::OK(); | 578 return leveldb::Status::OK(); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 return AppendBlobsToBlobJournal(transaction, LiveBlobJournalKey::Encode(), | 660 return AppendBlobsToBlobJournal(transaction, LiveBlobJournalKey::Encode(), |
660 journal); | 661 journal); |
661 } | 662 } |
662 | 663 |
663 // Append a database to the specified blob journal via the supplied transaction. | 664 // Append a database to the specified blob journal via the supplied transaction. |
664 // The key must be either the primary journal key or live journal key. | 665 // The key must be either the primary journal key or live journal key. |
665 static leveldb::Status MergeDatabaseIntoBlobJournal( | 666 static leveldb::Status MergeDatabaseIntoBlobJournal( |
666 LevelDBDirectTransaction* transaction, | 667 LevelDBDirectTransaction* transaction, |
667 const std::string& key, | 668 const std::string& key, |
668 int64 database_id) { | 669 int64 database_id) { |
| 670 IDB_TRACE("IndexedDBBackingStore::MergeDatabaseIntoBlobJournal"); |
669 BlobJournalType journal; | 671 BlobJournalType journal; |
670 leveldb::Status s = GetBlobJournal(key, transaction, &journal); | 672 leveldb::Status s = GetBlobJournal(key, transaction, &journal); |
671 if (!s.ok()) | 673 if (!s.ok()) |
672 return s; | 674 return s; |
673 journal.push_back( | 675 journal.push_back( |
674 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey)); | 676 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey)); |
675 UpdateBlobJournal(transaction, key, journal); | 677 UpdateBlobJournal(transaction, key, journal); |
676 return leveldb::Status::OK(); | 678 return leveldb::Status::OK(); |
677 } | 679 } |
678 | 680 |
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1467 s = GetIDBDatabaseMetaData(name, &metadata, &success); | 1469 s = GetIDBDatabaseMetaData(name, &metadata, &success); |
1468 if (!s.ok()) | 1470 if (!s.ok()) |
1469 return s; | 1471 return s; |
1470 if (!success) | 1472 if (!success) |
1471 return leveldb::Status::OK(); | 1473 return leveldb::Status::OK(); |
1472 | 1474 |
1473 const std::string start_key = DatabaseMetaDataKey::Encode( | 1475 const std::string start_key = DatabaseMetaDataKey::Encode( |
1474 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME); | 1476 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME); |
1475 const std::string stop_key = DatabaseMetaDataKey::Encode( | 1477 const std::string stop_key = DatabaseMetaDataKey::Encode( |
1476 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME); | 1478 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME); |
1477 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); | 1479 { |
1478 for (s = it->Seek(start_key); | 1480 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase.DeleteEntries"); |
1479 s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; | 1481 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); |
1480 s = it->Next()) | 1482 for (s = it->Seek(start_key); |
1481 transaction->Remove(it->Key()); | 1483 s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; |
| 1484 s = it->Next()) |
| 1485 transaction->Remove(it->Key()); |
| 1486 } |
1482 if (!s.ok()) { | 1487 if (!s.ok()) { |
1483 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); | 1488 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); |
1484 return s; | 1489 return s; |
1485 } | 1490 } |
1486 | 1491 |
1487 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); | 1492 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); |
1488 transaction->Remove(key); | 1493 transaction->Remove(key); |
1489 | 1494 |
1490 bool need_cleanup = false; | 1495 bool need_cleanup = false; |
1491 if (active_blob_registry()->MarkDeletedCheckIfUsed( | 1496 if (active_blob_registry()->MarkDeletedCheckIfUsed( |
(...skipping 1193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2685 return base::DeleteFile(path, false); | 2690 return base::DeleteFile(path, false); |
2686 } | 2691 } |
2687 | 2692 |
2688 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) const { | 2693 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) const { |
2689 FilePath path = GetBlobDirectoryName(blob_path_, database_id); | 2694 FilePath path = GetBlobDirectoryName(blob_path_, database_id); |
2690 return base::DeleteFile(path, true); | 2695 return base::DeleteFile(path, true); |
2691 } | 2696 } |
2692 | 2697 |
2693 leveldb::Status IndexedDBBackingStore::CleanUpBlobJournalEntries( | 2698 leveldb::Status IndexedDBBackingStore::CleanUpBlobJournalEntries( |
2694 const BlobJournalType& journal) const { | 2699 const BlobJournalType& journal) const { |
| 2700 IDB_TRACE("IndexedDBBackingStore::CleanUpBlobJournalEntries"); |
2695 if (journal.empty()) | 2701 if (journal.empty()) |
2696 return leveldb::Status::OK(); | 2702 return leveldb::Status::OK(); |
2697 for (const auto& entry : journal) { | 2703 for (const auto& entry : journal) { |
2698 int64 database_id = entry.first; | 2704 int64 database_id = entry.first; |
2699 int64 blob_key = entry.second; | 2705 int64 blob_key = entry.second; |
2700 DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); | 2706 DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); |
2701 if (blob_key == DatabaseMetaDataKey::kAllBlobsKey) { | 2707 if (blob_key == DatabaseMetaDataKey::kAllBlobsKey) { |
2702 if (!RemoveBlobDirectory(database_id)) | 2708 if (!RemoveBlobDirectory(database_id)) |
2703 return IOErrorStatus(); | 2709 return IOErrorStatus(); |
2704 } else { | 2710 } else { |
2705 DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key)); | 2711 DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key)); |
2706 if (!RemoveBlobFile(database_id, blob_key)) | 2712 if (!RemoveBlobFile(database_id, blob_key)) |
2707 return IOErrorStatus(); | 2713 return IOErrorStatus(); |
2708 } | 2714 } |
2709 } | 2715 } |
2710 return leveldb::Status::OK(); | 2716 return leveldb::Status::OK(); |
2711 } | 2717 } |
2712 | 2718 |
2713 leveldb::Status IndexedDBBackingStore::CleanUpBlobJournal( | 2719 leveldb::Status IndexedDBBackingStore::CleanUpBlobJournal( |
2714 const std::string& level_db_key) const { | 2720 const std::string& level_db_key) const { |
| 2721 IDB_TRACE("IndexedDBBackingStore::CleanUpBlobJournal"); |
2715 DCHECK(!committing_transaction_count_); | 2722 DCHECK(!committing_transaction_count_); |
2716 leveldb::Status s; | 2723 leveldb::Status s; |
2717 scoped_refptr<LevelDBTransaction> journal_transaction = | 2724 scoped_refptr<LevelDBTransaction> journal_transaction = |
2718 IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get()); | 2725 IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get()); |
2719 BlobJournalType journal; | 2726 BlobJournalType journal; |
2720 | 2727 |
2721 s = GetBlobJournal(level_db_key, journal_transaction.get(), &journal); | 2728 s = GetBlobJournal(level_db_key, journal_transaction.get(), &journal); |
2722 if (!s.ok()) | 2729 if (!s.ok()) |
2723 return s; | 2730 return s; |
2724 if (journal.empty()) | 2731 if (journal.empty()) |
(...skipping 1491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4216 leveldb::Status s; | 4223 leveldb::Status s; |
4217 | 4224 |
4218 DCHECK(committing_); | 4225 DCHECK(committing_); |
4219 committing_ = false; | 4226 committing_ = false; |
4220 DCHECK_GT(backing_store_->committing_transaction_count_, 0UL); | 4227 DCHECK_GT(backing_store_->committing_transaction_count_, 0UL); |
4221 --backing_store_->committing_transaction_count_; | 4228 --backing_store_->committing_transaction_count_; |
4222 | 4229 |
4223 BlobJournalType primary_journal, live_journal, saved_primary_journal, | 4230 BlobJournalType primary_journal, live_journal, saved_primary_journal, |
4224 dead_blobs; | 4231 dead_blobs; |
4225 if (!blob_change_map_.empty()) { | 4232 if (!blob_change_map_.empty()) { |
| 4233 IDB_TRACE("IndexedDBBackingStore::Transaction.BlobJournal"); |
4226 // Read the persisted states of the primary/live blob journals, | 4234 // Read the persisted states of the primary/live blob journals, |
4227 // so that they can be updated correctly by the transaction. | 4235 // so that they can be updated correctly by the transaction. |
4228 scoped_refptr<LevelDBTransaction> journal_transaction = | 4236 scoped_refptr<LevelDBTransaction> journal_transaction = |
4229 IndexedDBClassFactory::Get()->CreateLevelDBTransaction( | 4237 IndexedDBClassFactory::Get()->CreateLevelDBTransaction( |
4230 backing_store_->db_.get()); | 4238 backing_store_->db_.get()); |
4231 s = GetPrimaryBlobJournal(journal_transaction.get(), &primary_journal); | 4239 s = GetPrimaryBlobJournal(journal_transaction.get(), &primary_journal); |
4232 if (!s.ok()) | 4240 if (!s.ok()) |
4233 return s; | 4241 return s; |
4234 s = GetLiveBlobJournal(journal_transaction.get(), &live_journal); | 4242 s = GetLiveBlobJournal(journal_transaction.get(), &live_journal); |
4235 if (!s.ok()) | 4243 if (!s.ok()) |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4310 } | 4318 } |
4311 | 4319 |
4312 | 4320 |
4313 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper | 4321 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper |
4314 : public IndexedDBBackingStore::BlobWriteCallback { | 4322 : public IndexedDBBackingStore::BlobWriteCallback { |
4315 public: | 4323 public: |
4316 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction, | 4324 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction, |
4317 scoped_refptr<BlobWriteCallback> callback) | 4325 scoped_refptr<BlobWriteCallback> callback) |
4318 : transaction_(transaction), callback_(callback) {} | 4326 : transaction_(transaction), callback_(callback) {} |
4319 void Run(bool succeeded) override { | 4327 void Run(bool succeeded) override { |
| 4328 IDB_ASYNC_TRACE_END("IndexedDBBackingStore::Transaction::WriteNewBlobs", |
| 4329 transaction_); |
4320 callback_->Run(succeeded); | 4330 callback_->Run(succeeded); |
4321 if (succeeded) // Else it's already been deleted during rollback. | 4331 if (succeeded) // Else it's already been deleted during rollback. |
4322 transaction_->chained_blob_writer_ = NULL; | 4332 transaction_->chained_blob_writer_ = NULL; |
4323 } | 4333 } |
4324 | 4334 |
4325 private: | 4335 private: |
4326 ~BlobWriteCallbackWrapper() override {} | 4336 ~BlobWriteCallbackWrapper() override {} |
4327 friend class base::RefCounted<IndexedDBBackingStore::BlobWriteCallback>; | 4337 friend class base::RefCounted<IndexedDBBackingStore::BlobWriteCallback>; |
4328 | 4338 |
4329 IndexedDBBackingStore::Transaction* transaction_; | 4339 IndexedDBBackingStore::Transaction* transaction_; |
4330 scoped_refptr<BlobWriteCallback> callback_; | 4340 scoped_refptr<BlobWriteCallback> callback_; |
4331 | 4341 |
4332 DISALLOW_COPY_AND_ASSIGN(BlobWriteCallbackWrapper); | 4342 DISALLOW_COPY_AND_ASSIGN(BlobWriteCallbackWrapper); |
4333 }; | 4343 }; |
4334 | 4344 |
4335 void IndexedDBBackingStore::Transaction::WriteNewBlobs( | 4345 void IndexedDBBackingStore::Transaction::WriteNewBlobs( |
4336 BlobEntryKeyValuePairVec* new_blob_entries, | 4346 BlobEntryKeyValuePairVec* new_blob_entries, |
4337 WriteDescriptorVec* new_files_to_write, | 4347 WriteDescriptorVec* new_files_to_write, |
4338 scoped_refptr<BlobWriteCallback> callback) { | 4348 scoped_refptr<BlobWriteCallback> callback) { |
| 4349 IDB_ASYNC_TRACE_BEGIN("IndexedDBBackingStore::Transaction::WriteNewBlobs", |
| 4350 this); |
4339 DCHECK_GT(new_files_to_write->size(), 0UL); | 4351 DCHECK_GT(new_files_to_write->size(), 0UL); |
4340 DCHECK_GT(database_id_, 0); | 4352 DCHECK_GT(database_id_, 0); |
4341 for (auto& blob_entry_iter : *new_blob_entries) { | 4353 for (auto& blob_entry_iter : *new_blob_entries) { |
4342 // Add the new blob-table entry for each blob to the main transaction, or | 4354 // Add the new blob-table entry for each blob to the main transaction, or |
4343 // remove any entry that may exist if there's no new one. | 4355 // remove any entry that may exist if there's no new one. |
4344 if (blob_entry_iter.second.empty()) | 4356 if (blob_entry_iter.second.empty()) |
4345 transaction_->Remove(blob_entry_iter.first.Encode()); | 4357 transaction_->Remove(blob_entry_iter.first.Encode()); |
4346 else | 4358 else |
4347 transaction_->Put(blob_entry_iter.first.Encode(), | 4359 transaction_->Put(blob_entry_iter.first.Encode(), |
4348 &blob_entry_iter.second); | 4360 &blob_entry_iter.second); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4493 | 4505 |
4494 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( | 4506 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( |
4495 const WriteDescriptor& other) = default; | 4507 const WriteDescriptor& other) = default; |
4496 IndexedDBBackingStore::Transaction::WriteDescriptor::~WriteDescriptor() = | 4508 IndexedDBBackingStore::Transaction::WriteDescriptor::~WriteDescriptor() = |
4497 default; | 4509 default; |
4498 IndexedDBBackingStore::Transaction::WriteDescriptor& | 4510 IndexedDBBackingStore::Transaction::WriteDescriptor& |
4499 IndexedDBBackingStore::Transaction::WriteDescriptor:: | 4511 IndexedDBBackingStore::Transaction::WriteDescriptor:: |
4500 operator=(const WriteDescriptor& other) = default; | 4512 operator=(const WriteDescriptor& other) = default; |
4501 | 4513 |
4502 } // namespace content | 4514 } // namespace content |
OLD | NEW |