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..8804a680b1ee856d5ae45194c4feadefce188495 100644 |
| --- a/content/browser/indexed_db/leveldb/leveldb_database.cc |
| +++ b/content/browser/indexed_db/leveldb/leveldb_database.cc |
| @@ -41,6 +41,7 @@ |
| using base::StringPiece; |
| namespace content { |
| +static const size_t kDefaultMaxOpenIteratorsPerDatabase = 50; |
|
jsbell
2017/03/22 23:55:32
We should note that this applies only to iterators
dmurph
2017/03/23 20:56:48
Done.
|
| // Forcing flushes to disk at the end of a transaction guarantees that the |
| // data hit disk, but drastically impacts throughput when the filesystem is |
| @@ -92,9 +93,15 @@ LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db) |
| LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); } |
| -LevelDBDatabase::LevelDBDatabase() {} |
| +LevelDBDatabase::LevelDBDatabase() |
| + : iterator_lru_(kDefaultMaxOpenIteratorsPerDatabase) {} |
| + |
| +LevelDBDatabase::LevelDBDatabase(size_t max_open_iterators) |
| + : iterator_lru_(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. |
| @@ -285,6 +292,43 @@ static void HistogramLevelDBError(const std::string& histogram_name, |
| ParseAndHistogramCorruptionDetails(histogram_name, s); |
| } |
| +leveldb::Status LevelDBDatabase::OpenForTesting( |
|
jsbell
2017/03/22 23:55:32
Too much duplicated code. :( Can we refactor?
I d
dmurph
2017/03/23 20:56:48
Done.
|
| + const base::FilePath& file_name, |
| + const LevelDBComparator* comparator, |
| + std::unique_ptr<LevelDBDatabase>* result, |
| + size_t max_open_cursors) { |
| + IDB_TRACE("LevelDBDatabase::Open"); |
| + base::TimeTicks begin_time = base::TimeTicks::Now(); |
| + |
| + std::unique_ptr<ComparatorAdapter> comparator_adapter( |
| + base::MakeUnique<ComparatorAdapter>(comparator)); |
| + |
| + std::unique_ptr<leveldb::DB> db; |
| + std::unique_ptr<const leveldb::FilterPolicy> filter_policy; |
| + const leveldb::Status s = OpenDB(comparator_adapter.get(), LevelDBEnv::Get(), |
| + file_name, &db, &filter_policy); |
| + |
| + if (!s.ok()) { |
| + HistogramLevelDBError("WebCore.IndexedDB.LevelDBOpenErrors", s); |
| + LOG(ERROR) << "Failed to open LevelDB database from " |
| + << file_name.AsUTF8Unsafe() << "," << s.ToString(); |
| + return s; |
| + } |
| + |
| + UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime", |
| + base::TimeTicks::Now() - begin_time); |
| + |
| + CheckFreeSpace("Success", file_name); |
| + |
| + (*result) = base::WrapUnique(new LevelDBDatabase(max_open_cursors)); |
| + (*result)->db_ = std::move(db); |
| + (*result)->comparator_adapter_ = std::move(comparator_adapter); |
| + (*result)->comparator_ = comparator; |
| + (*result)->filter_policy_ = std::move(filter_policy); |
| + (*result)->file_name_for_tracing = file_name.BaseName().AsUTF8Unsafe(); |
| + return s; |
| +} |
| + |
| leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, |
| const LevelDBComparator* comparator, |
| std::unique_ptr<LevelDBDatabase>* result, |
| @@ -479,4 +523,30 @@ bool LevelDBDatabase::OnMemoryDump( |
| return true; |
| } |
| +void LevelDBDatabase::NotifyIteratorCreated(LevelDBIterator* iter) { |
| + num_iterators_++; |
| + max_iterators_ = std::max(max_iterators_, num_iterators_); |
| +} |
| + |
| +void LevelDBDatabase::NotifyIteratorUsed(LevelDBIterator* iter) { |
| + // This line updates the LRU if the item exists. |
| + if (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_; |
| + auto it = iterator_lru_.Get(iter); |
|
jsbell
2017/03/22 23:55:32
Peek() instead of Get(), since we don't need to me
dmurph
2017/03/23 20:56:47
Done.
|
| + if (it == iterator_lru_.end()) |
| + return; |
| + iterator_lru_.Erase(it); |
| +} |
| } // namespace content |