Chromium Code Reviews| Index: content/browser/indexed_db/leveldb/leveldb_database.cc |
| diff --git a/content/browser/indexed_db/leveldb/leveldb_database.cc b/content/browser/indexed_db/leveldb/leveldb_database.cc |
| index 7eaa89405cb23782b5c070ca97947a64edb9f3ef..b3548cc0c4c2ccaea1c818a828136a556591a14a 100644 |
| --- a/content/browser/indexed_db/leveldb/leveldb_database.cc |
| +++ b/content/browser/indexed_db/leveldb/leveldb_database.cc |
| @@ -92,9 +92,14 @@ LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db) |
| LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); } |
| -LevelDBDatabase::LevelDBDatabase() {} |
| +LevelDBDatabase::LevelDBDatabase(size_t max_open_iterators) |
| + : iterator_lru_(max_open_iterators) { |
| + DCHECK(max_open_iterators); |
| +} |
| LevelDBDatabase::~LevelDBDatabase() { |
| + LOCAL_HISTOGRAM_COUNTS_10000("Storage.IndexedDB.LevelDB.MaxIterators", |
| + max_iterators_); |
| base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
| this); |
| // db_'s destructor uses comparator_adapter_; order of deletion is important. |
| @@ -288,6 +293,7 @@ static void HistogramLevelDBError(const std::string& histogram_name, |
| leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, |
| const LevelDBComparator* comparator, |
| std::unique_ptr<LevelDBDatabase>* result, |
| + size_t max_open_cursors, |
|
pwnall
2017/03/27 17:08:04
Sorry I caught this so late, but I think this para
dmurph
2017/03/27 21:32:04
Done.
|
| bool* is_disk_full) { |
| IDB_TRACE("LevelDBDatabase::Open"); |
| base::TimeTicks begin_time = base::TimeTicks::Now(); |
| @@ -318,7 +324,7 @@ leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, |
| CheckFreeSpace("Success", file_name); |
| - (*result) = base::WrapUnique(new LevelDBDatabase()); |
| + (*result) = base::WrapUnique(new LevelDBDatabase(max_open_cursors)); |
| (*result)->db_ = std::move(db); |
| (*result)->comparator_adapter_ = std::move(comparator_adapter); |
| (*result)->comparator_ = comparator; |
| @@ -348,8 +354,9 @@ std::unique_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory( |
| return std::unique_ptr<LevelDBDatabase>(); |
| } |
| - std::unique_ptr<LevelDBDatabase> result = |
| - base::WrapUnique(new LevelDBDatabase()); |
| + // Since the database is in-memory, cursor pooling is pointless. |
|
jsbell
2017/03/27 15:35:34
Obsolete comment?
dmurph
2017/03/27 21:32:04
Done.
|
| + std::unique_ptr<LevelDBDatabase> result = base::WrapUnique( |
| + new LevelDBDatabase(kDefaultMaxOpenIteratorsPerDatabase)); |
| result->env_ = std::move(in_memory_env); |
| result->db_ = std::move(db); |
| result->comparator_adapter_ = std::move(comparator_adapter); |
| @@ -433,9 +440,12 @@ std::unique_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator( |
| // performance impact is too great. |
| read_options.snapshot = snapshot ? snapshot->snapshot_ : 0; |
| + num_iterators_++; |
| + max_iterators_ = std::max(max_iterators_, num_iterators_); |
| std::unique_ptr<leveldb::Iterator> i(db_->NewIterator(read_options)); |
| return std::unique_ptr<LevelDBIterator>( |
| - IndexedDBClassFactory::Get()->CreateIteratorImpl(std::move(i))); |
| + IndexedDBClassFactory::Get()->CreateIteratorImpl(std::move(i), this, |
| + read_options.snapshot)); |
| } |
| const LevelDBComparator* LevelDBDatabase::Comparator() const { |
| @@ -479,4 +489,46 @@ bool LevelDBDatabase::OnMemoryDump( |
| return true; |
| } |
| +std::unique_ptr<leveldb::Iterator> LevelDBDatabase::CreateLevelDBIterator( |
| + const leveldb::Snapshot* snapshot) { |
| + leveldb::ReadOptions read_options; |
| + read_options.verify_checksums = true; |
| + read_options.snapshot = snapshot; |
| + return std::unique_ptr<leveldb::Iterator>(db_->NewIterator(read_options)); |
| +} |
| + |
| +LevelDBDatabase::DetachIteratorOnDestruct::DetachIteratorOnDestruct() {} |
| + |
| +LevelDBDatabase::DetachIteratorOnDestruct::DetachIteratorOnDestruct( |
| + LevelDBIterator* it) |
| + : it_(it) {} |
| + |
| +LevelDBDatabase::DetachIteratorOnDestruct::DetachIteratorOnDestruct( |
| + DetachIteratorOnDestruct&& that) { |
| + it_ = that.it_; |
| + that.it_ = nullptr; |
| +}; |
| + |
| +LevelDBDatabase::DetachIteratorOnDestruct::~DetachIteratorOnDestruct() { |
| + if (it_) |
| + it_->Detach(); |
| +} |
| + |
| +void LevelDBDatabase::NotifyIteratorUsed(LevelDBIterator* iter) { |
|
pwnall
2017/03/27 17:08:04
I forgot to ask last time -- is Notify a Chromium*
dmurph
2017/03/27 21:32:04
I think I mostly see On* code being used for inter
|
| + // This line updates the LRU if the item exists. |
| + if (iterator_lru_.Get(iter) != iterator_lru_.end()) |
| + return; |
| + DetachIteratorOnDestruct purger(iter); |
| + iterator_lru_.Put(iter, std::move(purger)); |
| +} |
| + |
| +void LevelDBDatabase::NotifyIteratorDestroyed(LevelDBIterator* iter) { |
| + DCHECK_GT(num_iterators_, 0u); |
| + --num_iterators_; |
| + auto it = iterator_lru_.Peek(iter); |
| + if (it == iterator_lru_.end()) |
| + return; |
| + iterator_lru_.Erase(it); |
| +} |
| + |
| } // namespace content |