| 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..f157f5ef29d708506f8e6f00677732f1f23d56d3 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.
|
| @@ -287,6 +292,7 @@ static void HistogramLevelDBError(const std::string& histogram_name,
|
|
|
| leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name,
|
| const LevelDBComparator* comparator,
|
| + size_t max_open_cursors,
|
| std::unique_ptr<LevelDBDatabase>* result,
|
| bool* is_disk_full) {
|
| IDB_TRACE("LevelDBDatabase::Open");
|
| @@ -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,8 @@ std::unique_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory(
|
| return std::unique_ptr<LevelDBDatabase>();
|
| }
|
|
|
| - std::unique_ptr<LevelDBDatabase> result =
|
| - base::WrapUnique(new LevelDBDatabase());
|
| + 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 +439,14 @@ 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_);
|
| + // Iterator isn't added to lru cache until it is used, as memory isn't loaded
|
| + // for the iterator until it's first Seek call.
|
| 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 +490,34 @@ 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() {
|
| + if (it_)
|
| + it_->Detach();
|
| +}
|
| +
|
| +void LevelDBDatabase::OnIteratorUsed(LevelDBIterator* iter) {
|
| + // 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::OnIteratorDestroyed(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
|
|
|