Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/indexed_db/leveldb/leveldb_database.h" | 5 #include "content/browser/indexed_db/leveldb/leveldb_database.h" |
| 6 | 6 |
| 7 #include <inttypes.h> | 7 #include <inttypes.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <cerrno> | 10 #include <cerrno> |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 #include "third_party/leveldatabase/env_chromium.h" | 34 #include "third_party/leveldatabase/env_chromium.h" |
| 35 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" | 35 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" |
| 36 #include "third_party/leveldatabase/src/include/leveldb/db.h" | 36 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
| 37 #include "third_party/leveldatabase/src/include/leveldb/env.h" | 37 #include "third_party/leveldatabase/src/include/leveldb/env.h" |
| 38 #include "third_party/leveldatabase/src/include/leveldb/filter_policy.h" | 38 #include "third_party/leveldatabase/src/include/leveldb/filter_policy.h" |
| 39 #include "third_party/leveldatabase/src/include/leveldb/slice.h" | 39 #include "third_party/leveldatabase/src/include/leveldb/slice.h" |
| 40 | 40 |
| 41 using base::StringPiece; | 41 using base::StringPiece; |
| 42 | 42 |
| 43 namespace content { | 43 namespace content { |
| 44 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.
| |
| 44 | 45 |
| 45 // Forcing flushes to disk at the end of a transaction guarantees that the | 46 // Forcing flushes to disk at the end of a transaction guarantees that the |
| 46 // data hit disk, but drastically impacts throughput when the filesystem is | 47 // data hit disk, but drastically impacts throughput when the filesystem is |
| 47 // busy with background compactions. Not syncing trades off reliability for | 48 // busy with background compactions. Not syncing trades off reliability for |
| 48 // performance. Note that background compactions which move data from the | 49 // performance. Note that background compactions which move data from the |
| 49 // log to SSTs are always done with reliable writes. | 50 // log to SSTs are always done with reliable writes. |
| 50 // | 51 // |
| 51 // Sync writes are necessary on Windows for quota calculations; POSIX | 52 // Sync writes are necessary on Windows for quota calculations; POSIX |
| 52 // calculates file sizes correctly even when not synced to disk. | 53 // calculates file sizes correctly even when not synced to disk. |
| 53 #if defined(OS_WIN) | 54 #if defined(OS_WIN) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 const leveldb::Slice& limit) const {} | 86 const leveldb::Slice& limit) const {} |
| 86 | 87 |
| 87 void LevelDBDatabase::ComparatorAdapter::FindShortSuccessor( | 88 void LevelDBDatabase::ComparatorAdapter::FindShortSuccessor( |
| 88 std::string* key) const {} | 89 std::string* key) const {} |
| 89 | 90 |
| 90 LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db) | 91 LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db) |
| 91 : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {} | 92 : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {} |
| 92 | 93 |
| 93 LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); } | 94 LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); } |
| 94 | 95 |
| 95 LevelDBDatabase::LevelDBDatabase() {} | 96 LevelDBDatabase::LevelDBDatabase() |
| 97 : iterator_lru_(kDefaultMaxOpenIteratorsPerDatabase) {} | |
| 98 | |
| 99 LevelDBDatabase::LevelDBDatabase(size_t max_open_iterators) | |
| 100 : iterator_lru_(max_open_iterators) {} | |
| 96 | 101 |
| 97 LevelDBDatabase::~LevelDBDatabase() { | 102 LevelDBDatabase::~LevelDBDatabase() { |
| 103 LOCAL_HISTOGRAM_COUNTS_10000("Storage.IndexedDB.LevelDB.MaxIterators", | |
| 104 max_iterators_); | |
| 98 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( | 105 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
| 99 this); | 106 this); |
| 100 // db_'s destructor uses comparator_adapter_; order of deletion is important. | 107 // db_'s destructor uses comparator_adapter_; order of deletion is important. |
| 101 CloseDatabase(); | 108 CloseDatabase(); |
| 102 comparator_adapter_.reset(); | 109 comparator_adapter_.reset(); |
| 103 env_.reset(); | 110 env_.reset(); |
| 104 } | 111 } |
| 105 | 112 |
| 106 void LevelDBDatabase::CloseDatabase() { | 113 void LevelDBDatabase::CloseDatabase() { |
| 107 if (db_) { | 114 if (db_) { |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 LEVEL_DB_MAX_ERROR, | 285 LEVEL_DB_MAX_ERROR, |
| 279 LEVEL_DB_MAX_ERROR + 1, | 286 LEVEL_DB_MAX_ERROR + 1, |
| 280 base::HistogramBase::kUmaTargetedHistogramFlag) | 287 base::HistogramBase::kUmaTargetedHistogramFlag) |
| 281 ->Add(leveldb_error); | 288 ->Add(leveldb_error); |
| 282 if (s.IsIOError()) | 289 if (s.IsIOError()) |
| 283 ParseAndHistogramIOErrorDetails(histogram_name, s); | 290 ParseAndHistogramIOErrorDetails(histogram_name, s); |
| 284 else | 291 else |
| 285 ParseAndHistogramCorruptionDetails(histogram_name, s); | 292 ParseAndHistogramCorruptionDetails(histogram_name, s); |
| 286 } | 293 } |
| 287 | 294 |
| 295 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.
| |
| 296 const base::FilePath& file_name, | |
| 297 const LevelDBComparator* comparator, | |
| 298 std::unique_ptr<LevelDBDatabase>* result, | |
| 299 size_t max_open_cursors) { | |
| 300 IDB_TRACE("LevelDBDatabase::Open"); | |
| 301 base::TimeTicks begin_time = base::TimeTicks::Now(); | |
| 302 | |
| 303 std::unique_ptr<ComparatorAdapter> comparator_adapter( | |
| 304 base::MakeUnique<ComparatorAdapter>(comparator)); | |
| 305 | |
| 306 std::unique_ptr<leveldb::DB> db; | |
| 307 std::unique_ptr<const leveldb::FilterPolicy> filter_policy; | |
| 308 const leveldb::Status s = OpenDB(comparator_adapter.get(), LevelDBEnv::Get(), | |
| 309 file_name, &db, &filter_policy); | |
| 310 | |
| 311 if (!s.ok()) { | |
| 312 HistogramLevelDBError("WebCore.IndexedDB.LevelDBOpenErrors", s); | |
| 313 LOG(ERROR) << "Failed to open LevelDB database from " | |
| 314 << file_name.AsUTF8Unsafe() << "," << s.ToString(); | |
| 315 return s; | |
| 316 } | |
| 317 | |
| 318 UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime", | |
| 319 base::TimeTicks::Now() - begin_time); | |
| 320 | |
| 321 CheckFreeSpace("Success", file_name); | |
| 322 | |
| 323 (*result) = base::WrapUnique(new LevelDBDatabase(max_open_cursors)); | |
| 324 (*result)->db_ = std::move(db); | |
| 325 (*result)->comparator_adapter_ = std::move(comparator_adapter); | |
| 326 (*result)->comparator_ = comparator; | |
| 327 (*result)->filter_policy_ = std::move(filter_policy); | |
| 328 (*result)->file_name_for_tracing = file_name.BaseName().AsUTF8Unsafe(); | |
| 329 return s; | |
| 330 } | |
| 331 | |
| 288 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, | 332 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, |
| 289 const LevelDBComparator* comparator, | 333 const LevelDBComparator* comparator, |
| 290 std::unique_ptr<LevelDBDatabase>* result, | 334 std::unique_ptr<LevelDBDatabase>* result, |
| 291 bool* is_disk_full) { | 335 bool* is_disk_full) { |
| 292 IDB_TRACE("LevelDBDatabase::Open"); | 336 IDB_TRACE("LevelDBDatabase::Open"); |
| 293 base::TimeTicks begin_time = base::TimeTicks::Now(); | 337 base::TimeTicks begin_time = base::TimeTicks::Now(); |
| 294 | 338 |
| 295 std::unique_ptr<ComparatorAdapter> comparator_adapter( | 339 std::unique_ptr<ComparatorAdapter> comparator_adapter( |
| 296 base::MakeUnique<ComparatorAdapter>(comparator)); | 340 base::MakeUnique<ComparatorAdapter>(comparator)); |
| 297 | 341 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 472 base::trace_event::MemoryAllocatorDump::kUnitsBytes, size); | 516 base::trace_event::MemoryAllocatorDump::kUnitsBytes, size); |
| 473 dump->AddString("file_name", "", file_name_for_tracing); | 517 dump->AddString("file_name", "", file_name_for_tracing); |
| 474 | 518 |
| 475 // Memory is allocated from system allocator (malloc). | 519 // Memory is allocated from system allocator (malloc). |
| 476 pmd->AddSuballocation(dump->guid(), | 520 pmd->AddSuballocation(dump->guid(), |
| 477 base::trace_event::MemoryDumpManager::GetInstance() | 521 base::trace_event::MemoryDumpManager::GetInstance() |
| 478 ->system_allocator_pool_name()); | 522 ->system_allocator_pool_name()); |
| 479 return true; | 523 return true; |
| 480 } | 524 } |
| 481 | 525 |
| 526 void LevelDBDatabase::NotifyIteratorCreated(LevelDBIterator* iter) { | |
| 527 num_iterators_++; | |
| 528 max_iterators_ = std::max(max_iterators_, num_iterators_); | |
| 529 } | |
| 530 | |
| 531 void LevelDBDatabase::NotifyIteratorUsed(LevelDBIterator* iter) { | |
| 532 // This line updates the LRU if the item exists. | |
| 533 if (iterator_lru_.Get(iter) != iterator_lru_.end()) | |
| 534 return; | |
| 535 if (iterator_lru_.size() == iterator_lru_.max_size()) { | |
| 536 auto to_evict_iter = iterator_lru_.rbegin(); | |
| 537 LevelDBIterator* to_evict = to_evict_iter->first; | |
| 538 to_evict->PurgeMemory(); | |
| 539 iterator_lru_.Erase(to_evict_iter); | |
| 540 } | |
| 541 iterator_lru_.Put(iter, iter); | |
| 542 } | |
| 543 | |
| 544 void LevelDBDatabase::NotifyIteratorDestroyed(LevelDBIterator* iter) { | |
| 545 DCHECK_GT(num_iterators_, 0u); | |
| 546 --num_iterators_; | |
| 547 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.
| |
| 548 if (it == iterator_lru_.end()) | |
| 549 return; | |
| 550 iterator_lru_.Erase(it); | |
| 551 } | |
| 482 } // namespace content | 552 } // namespace content |
| OLD | NEW |