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..64ff33ab46c4d22e36e6c255255df92e14a574cf 100644 |
| --- a/content/browser/indexed_db/leveldb/leveldb_database.cc |
| +++ b/content/browser/indexed_db/leveldb/leveldb_database.cc |
| @@ -92,9 +92,13 @@ LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db) |
| LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); } |
| -LevelDBDatabase::LevelDBDatabase() {} |
| +LevelDBDatabase::LevelDBDatabase(size_t max_open_iterators) |
| + : eviction_enabled_(max_open_iterators != NO_CURSOR_EVICTION), |
| + iterator_lru_(max_open_iterators) {} |
|
pwnall
2017/03/24 09:16:02
Shouldn't the MRUCache be initialized with NO_AUTO
dmurph
2017/03/24 23:33:39
Creating our own struct so we do correct eviction.
|
| 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 +292,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, |
| bool* is_disk_full) { |
| IDB_TRACE("LevelDBDatabase::Open"); |
| base::TimeTicks begin_time = base::TimeTicks::Now(); |
| @@ -318,7 +323,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 +353,9 @@ std::unique_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory( |
| return std::unique_ptr<LevelDBDatabase>(); |
| } |
| + // Since the database is in-memory, cursor pooling is pointless. |
| std::unique_ptr<LevelDBDatabase> result = |
| - base::WrapUnique(new LevelDBDatabase()); |
| + base::WrapUnique(new LevelDBDatabase(NO_CURSOR_EVICTION)); |
| result->env_ = std::move(in_memory_env); |
| result->db_ = std::move(db); |
| result->comparator_adapter_ = std::move(comparator_adapter); |
| @@ -433,9 +439,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)); |
|
pwnall
2017/03/24 09:16:02
Why doesn't the newly created iterator get added t
dmurph
2017/03/24 23:33:39
We don't actually allocated memory in the iterator
pwnall
2017/03/27 17:08:03
I would at the very least document the assumption.
dmurph
2017/03/27 21:32:04
Done.
|
| } |
| const LevelDBComparator* LevelDBDatabase::Comparator() const { |
| @@ -479,4 +488,35 @@ 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)); |
| +} |
| + |
| +void LevelDBDatabase::NotifyIteratorUsed(LevelDBIterator* iter) { |
| + // This line updates the LRU if the item exists. |
| + if (!eviction_enabled_ || iterator_lru_.Get(iter) != iterator_lru_.end()) |
| + return; |
| + if (iterator_lru_.size() == iterator_lru_.max_size()) { |
| + auto to_evict_iter = iterator_lru_.rbegin(); |
| + LevelDBIterator* to_evict = to_evict_iter->first; |
| + to_evict->PurgeMemory(); |
| + iterator_lru_.Erase(to_evict_iter); |
| + } |
| + iterator_lru_.Put(iter, iter); |
| +} |
| + |
| +void LevelDBDatabase::NotifyIteratorDestroyed(LevelDBIterator* iter) { |
| + DCHECK_GT(num_iterators_, 0u); |
| + --num_iterators_; |
| + if (!eviction_enabled_) |
| + return; |
| + auto it = iterator_lru_.Peek(iter); |
| + if (it == iterator_lru_.end()) |
| + return; |
| + iterator_lru_.Erase(it); |
| +} |
| } // namespace content |