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 |