Index: content/browser/indexed_db/leveldb/leveldb_transaction.cc |
diff --git a/content/browser/indexed_db/leveldb/leveldb_transaction.cc b/content/browser/indexed_db/leveldb/leveldb_transaction.cc |
index 1722549384aeec3bb98b4a0d8afc4ac75507d778..feb6ec3be73358c958c31e6ee2e485ff4366dd40 100644 |
--- a/content/browser/indexed_db/leveldb/leveldb_transaction.cc |
+++ b/content/browser/indexed_db/leveldb/leveldb_transaction.cc |
@@ -41,7 +41,11 @@ LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db) |
LevelDBTransaction::Record::Record() {} |
LevelDBTransaction::Record::~Record() {} |
-LevelDBTransaction::~LevelDBTransaction() {} |
+LevelDBTransaction::~LevelDBTransaction() { |
+ for (TransactionIterator* iter : iterators_) { |
+ db_->NotifyIteratorDestroyed(iter); |
+ } |
+} |
void LevelDBTransaction::Set(const StringPiece& key, |
std::string* value, |
@@ -248,6 +252,7 @@ bool LevelDBTransaction::TransactionIterator::IsValid() const { |
} |
leveldb::Status LevelDBTransaction::TransactionIterator::SeekToLast() { |
+ LoadDBIteratorIfEvicted(); |
leveldb::Status s = data_iterator_->SeekToLast(); |
DCHECK(s.ok()); |
s = db_iterator_->SeekToLast(); |
@@ -262,6 +267,7 @@ leveldb::Status LevelDBTransaction::TransactionIterator::SeekToLast() { |
leveldb::Status LevelDBTransaction::TransactionIterator::Seek( |
const StringPiece& target) { |
+ LoadDBIteratorIfEvicted(); |
leveldb::Status s = data_iterator_->Seek(target); |
DCHECK(s.ok()); |
s = db_iterator_->Seek(target); |
@@ -275,6 +281,7 @@ leveldb::Status LevelDBTransaction::TransactionIterator::Seek( |
} |
leveldb::Status LevelDBTransaction::TransactionIterator::Next() { |
+ LoadDBIteratorIfEvicted(); |
DCHECK(IsValid()); |
if (data_changed_) |
RefreshDataIterator(); |
@@ -311,6 +318,7 @@ leveldb::Status LevelDBTransaction::TransactionIterator::Next() { |
} |
leveldb::Status LevelDBTransaction::TransactionIterator::Prev() { |
+ LoadDBIteratorIfEvicted(); |
DCHECK(IsValid()); |
leveldb::Status s; |
if (data_changed_) |
@@ -354,6 +362,9 @@ StringPiece LevelDBTransaction::TransactionIterator::Key() const { |
DCHECK(IsValid()); |
if (data_changed_) |
RefreshDataIterator(); |
+ if (current_ == db_iterator_.get() && is_evicted_) { |
+ return key_after_eviction_; |
+ } |
return current_->Key(); |
} |
@@ -361,9 +372,20 @@ StringPiece LevelDBTransaction::TransactionIterator::Value() const { |
DCHECK(IsValid()); |
if (data_changed_) |
RefreshDataIterator(); |
+ if (current_ == db_iterator_.get()) { |
+ const_cast<LevelDBTransaction::TransactionIterator*>(this) |
+ ->LoadDBIteratorIfEvicted(); |
+ } |
return current_->Value(); |
} |
+void LevelDBTransaction::TransactionIterator::EvictWorkingMemory() { |
+ DCHECK(!is_evicted_); |
+ is_evicted_ = true; |
+ key_after_eviction_ = db_iterator_->Key().as_string(); |
+ db_iterator_.reset(); |
+} |
+ |
void LevelDBTransaction::TransactionIterator::DataChanged() { |
data_changed_ = true; |
} |
@@ -411,14 +433,28 @@ void LevelDBTransaction::TransactionIterator::RefreshDataIterator() const { |
} |
bool LevelDBTransaction::TransactionIterator::DataIteratorIsLower() const { |
+ DCHECK(!is_evicted_); |
return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) < 0; |
} |
bool LevelDBTransaction::TransactionIterator::DataIteratorIsHigher() const { |
+ DCHECK(!is_evicted_); |
return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) > 0; |
} |
+void LevelDBTransaction::TransactionIterator::LoadDBIteratorIfEvicted() { |
+ transaction_->db_->NotifyIteratorUsed(this); |
+ if (!is_evicted_) |
+ return; |
+ |
+ db_iterator_ = transaction_->db_->CreateIterator(&transaction_->snapshot_); |
+ db_iterator_->Seek(key_after_eviction_); |
+ key_after_eviction_.clear(); |
+ is_evicted_ = false; |
+} |
+ |
void LevelDBTransaction::TransactionIterator::HandleConflictsAndDeletes() { |
+ LoadDBIteratorIfEvicted(); |
bool loop = true; |
while (loop) { |
@@ -452,6 +488,7 @@ void LevelDBTransaction::TransactionIterator::HandleConflictsAndDeletes() { |
void |
LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() { |
+ DCHECK(!is_evicted_); |
LevelDBIterator* smallest = nullptr; |
if (data_iterator_->IsValid()) |
@@ -489,6 +526,7 @@ void LevelDBTransaction::RegisterIterator(TransactionIterator* iterator) { |
void LevelDBTransaction::UnregisterIterator(TransactionIterator* iterator) { |
DCHECK(iterators_.find(iterator) != iterators_.end()); |
iterators_.erase(iterator); |
+ db_->NotifyIteratorDestroyed(iterator); |
} |
void LevelDBTransaction::NotifyIterators() { |