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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 const leveldb::Slice& limit) const {} | 85 const leveldb::Slice& limit) const {} |
| 86 | 86 |
| 87 void LevelDBDatabase::ComparatorAdapter::FindShortSuccessor( | 87 void LevelDBDatabase::ComparatorAdapter::FindShortSuccessor( |
| 88 std::string* key) const {} | 88 std::string* key) const {} |
| 89 | 89 |
| 90 LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db) | 90 LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db) |
| 91 : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {} | 91 : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {} |
| 92 | 92 |
| 93 LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); } | 93 LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); } |
| 94 | 94 |
| 95 LevelDBDatabase::LevelDBDatabase() {} | 95 LevelDBDatabase::LevelDBDatabase(size_t max_open_iterators) |
| 96 : iterator_lru_(max_open_iterators) { | |
| 97 DCHECK(max_open_iterators); | |
| 98 } | |
| 96 | 99 |
| 97 LevelDBDatabase::~LevelDBDatabase() { | 100 LevelDBDatabase::~LevelDBDatabase() { |
| 101 LOCAL_HISTOGRAM_COUNTS_10000("Storage.IndexedDB.LevelDB.MaxIterators", | |
| 102 max_iterators_); | |
| 98 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( | 103 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
| 99 this); | 104 this); |
| 100 // db_'s destructor uses comparator_adapter_; order of deletion is important. | 105 // db_'s destructor uses comparator_adapter_; order of deletion is important. |
| 101 CloseDatabase(); | 106 CloseDatabase(); |
| 102 comparator_adapter_.reset(); | 107 comparator_adapter_.reset(); |
| 103 env_.reset(); | 108 env_.reset(); |
| 104 } | 109 } |
| 105 | 110 |
| 106 void LevelDBDatabase::CloseDatabase() { | 111 void LevelDBDatabase::CloseDatabase() { |
| 107 if (db_) { | 112 if (db_) { |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 281 ->Add(leveldb_error); | 286 ->Add(leveldb_error); |
| 282 if (s.IsIOError()) | 287 if (s.IsIOError()) |
| 283 ParseAndHistogramIOErrorDetails(histogram_name, s); | 288 ParseAndHistogramIOErrorDetails(histogram_name, s); |
| 284 else | 289 else |
| 285 ParseAndHistogramCorruptionDetails(histogram_name, s); | 290 ParseAndHistogramCorruptionDetails(histogram_name, s); |
| 286 } | 291 } |
| 287 | 292 |
| 288 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, | 293 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, |
| 289 const LevelDBComparator* comparator, | 294 const LevelDBComparator* comparator, |
| 290 std::unique_ptr<LevelDBDatabase>* result, | 295 std::unique_ptr<LevelDBDatabase>* result, |
| 296 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.
| |
| 291 bool* is_disk_full) { | 297 bool* is_disk_full) { |
| 292 IDB_TRACE("LevelDBDatabase::Open"); | 298 IDB_TRACE("LevelDBDatabase::Open"); |
| 293 base::TimeTicks begin_time = base::TimeTicks::Now(); | 299 base::TimeTicks begin_time = base::TimeTicks::Now(); |
| 294 | 300 |
| 295 std::unique_ptr<ComparatorAdapter> comparator_adapter( | 301 std::unique_ptr<ComparatorAdapter> comparator_adapter( |
| 296 base::MakeUnique<ComparatorAdapter>(comparator)); | 302 base::MakeUnique<ComparatorAdapter>(comparator)); |
| 297 | 303 |
| 298 std::unique_ptr<leveldb::DB> db; | 304 std::unique_ptr<leveldb::DB> db; |
| 299 std::unique_ptr<const leveldb::FilterPolicy> filter_policy; | 305 std::unique_ptr<const leveldb::FilterPolicy> filter_policy; |
| 300 const leveldb::Status s = OpenDB(comparator_adapter.get(), LevelDBEnv::Get(), | 306 const leveldb::Status s = OpenDB(comparator_adapter.get(), LevelDBEnv::Get(), |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 311 LOG(ERROR) << "Failed to open LevelDB database from " | 317 LOG(ERROR) << "Failed to open LevelDB database from " |
| 312 << file_name.AsUTF8Unsafe() << "," << s.ToString(); | 318 << file_name.AsUTF8Unsafe() << "," << s.ToString(); |
| 313 return s; | 319 return s; |
| 314 } | 320 } |
| 315 | 321 |
| 316 UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime", | 322 UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime", |
| 317 base::TimeTicks::Now() - begin_time); | 323 base::TimeTicks::Now() - begin_time); |
| 318 | 324 |
| 319 CheckFreeSpace("Success", file_name); | 325 CheckFreeSpace("Success", file_name); |
| 320 | 326 |
| 321 (*result) = base::WrapUnique(new LevelDBDatabase()); | 327 (*result) = base::WrapUnique(new LevelDBDatabase(max_open_cursors)); |
| 322 (*result)->db_ = std::move(db); | 328 (*result)->db_ = std::move(db); |
| 323 (*result)->comparator_adapter_ = std::move(comparator_adapter); | 329 (*result)->comparator_adapter_ = std::move(comparator_adapter); |
| 324 (*result)->comparator_ = comparator; | 330 (*result)->comparator_ = comparator; |
| 325 (*result)->filter_policy_ = std::move(filter_policy); | 331 (*result)->filter_policy_ = std::move(filter_policy); |
| 326 (*result)->file_name_for_tracing = file_name.BaseName().AsUTF8Unsafe(); | 332 (*result)->file_name_for_tracing = file_name.BaseName().AsUTF8Unsafe(); |
| 327 | 333 |
| 328 return s; | 334 return s; |
| 329 } | 335 } |
| 330 | 336 |
| 331 std::unique_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory( | 337 std::unique_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory( |
| 332 const LevelDBComparator* comparator) { | 338 const LevelDBComparator* comparator) { |
| 333 std::unique_ptr<ComparatorAdapter> comparator_adapter( | 339 std::unique_ptr<ComparatorAdapter> comparator_adapter( |
| 334 base::MakeUnique<ComparatorAdapter>(comparator)); | 340 base::MakeUnique<ComparatorAdapter>(comparator)); |
| 335 std::unique_ptr<leveldb::Env> in_memory_env( | 341 std::unique_ptr<leveldb::Env> in_memory_env( |
| 336 leveldb::NewMemEnv(LevelDBEnv::Get())); | 342 leveldb::NewMemEnv(LevelDBEnv::Get())); |
| 337 | 343 |
| 338 std::unique_ptr<leveldb::DB> db; | 344 std::unique_ptr<leveldb::DB> db; |
| 339 std::unique_ptr<const leveldb::FilterPolicy> filter_policy; | 345 std::unique_ptr<const leveldb::FilterPolicy> filter_policy; |
| 340 const leveldb::Status s = OpenDB(comparator_adapter.get(), | 346 const leveldb::Status s = OpenDB(comparator_adapter.get(), |
| 341 in_memory_env.get(), | 347 in_memory_env.get(), |
| 342 base::FilePath(), | 348 base::FilePath(), |
| 343 &db, | 349 &db, |
| 344 &filter_policy); | 350 &filter_policy); |
| 345 | 351 |
| 346 if (!s.ok()) { | 352 if (!s.ok()) { |
| 347 LOG(ERROR) << "Failed to open in-memory LevelDB database: " << s.ToString(); | 353 LOG(ERROR) << "Failed to open in-memory LevelDB database: " << s.ToString(); |
| 348 return std::unique_ptr<LevelDBDatabase>(); | 354 return std::unique_ptr<LevelDBDatabase>(); |
| 349 } | 355 } |
| 350 | 356 |
| 351 std::unique_ptr<LevelDBDatabase> result = | 357 // 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.
| |
| 352 base::WrapUnique(new LevelDBDatabase()); | 358 std::unique_ptr<LevelDBDatabase> result = base::WrapUnique( |
| 359 new LevelDBDatabase(kDefaultMaxOpenIteratorsPerDatabase)); | |
| 353 result->env_ = std::move(in_memory_env); | 360 result->env_ = std::move(in_memory_env); |
| 354 result->db_ = std::move(db); | 361 result->db_ = std::move(db); |
| 355 result->comparator_adapter_ = std::move(comparator_adapter); | 362 result->comparator_adapter_ = std::move(comparator_adapter); |
| 356 result->comparator_ = comparator; | 363 result->comparator_ = comparator; |
| 357 result->filter_policy_ = std::move(filter_policy); | 364 result->filter_policy_ = std::move(filter_policy); |
| 358 result->file_name_for_tracing = "in-memory-database"; | 365 result->file_name_for_tracing = "in-memory-database"; |
| 359 | 366 |
| 360 return result; | 367 return result; |
| 361 } | 368 } |
| 362 | 369 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 426 return s; | 433 return s; |
| 427 } | 434 } |
| 428 | 435 |
| 429 std::unique_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator( | 436 std::unique_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator( |
| 430 const LevelDBSnapshot* snapshot) { | 437 const LevelDBSnapshot* snapshot) { |
| 431 leveldb::ReadOptions read_options; | 438 leveldb::ReadOptions read_options; |
| 432 read_options.verify_checksums = true; // TODO(jsbell): Disable this if the | 439 read_options.verify_checksums = true; // TODO(jsbell): Disable this if the |
| 433 // performance impact is too great. | 440 // performance impact is too great. |
| 434 read_options.snapshot = snapshot ? snapshot->snapshot_ : 0; | 441 read_options.snapshot = snapshot ? snapshot->snapshot_ : 0; |
| 435 | 442 |
| 443 num_iterators_++; | |
| 444 max_iterators_ = std::max(max_iterators_, num_iterators_); | |
| 436 std::unique_ptr<leveldb::Iterator> i(db_->NewIterator(read_options)); | 445 std::unique_ptr<leveldb::Iterator> i(db_->NewIterator(read_options)); |
| 437 return std::unique_ptr<LevelDBIterator>( | 446 return std::unique_ptr<LevelDBIterator>( |
| 438 IndexedDBClassFactory::Get()->CreateIteratorImpl(std::move(i))); | 447 IndexedDBClassFactory::Get()->CreateIteratorImpl(std::move(i), this, |
| 448 read_options.snapshot)); | |
| 439 } | 449 } |
| 440 | 450 |
| 441 const LevelDBComparator* LevelDBDatabase::Comparator() const { | 451 const LevelDBComparator* LevelDBDatabase::Comparator() const { |
| 442 return comparator_; | 452 return comparator_; |
| 443 } | 453 } |
| 444 | 454 |
| 445 void LevelDBDatabase::Compact(const base::StringPiece& start, | 455 void LevelDBDatabase::Compact(const base::StringPiece& start, |
| 446 const base::StringPiece& stop) { | 456 const base::StringPiece& stop) { |
| 447 IDB_TRACE("LevelDBDatabase::Compact"); | 457 IDB_TRACE("LevelDBDatabase::Compact"); |
| 448 const leveldb::Slice start_slice = MakeSlice(start); | 458 const leveldb::Slice start_slice = MakeSlice(start); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 472 base::trace_event::MemoryAllocatorDump::kUnitsBytes, size); | 482 base::trace_event::MemoryAllocatorDump::kUnitsBytes, size); |
| 473 dump->AddString("file_name", "", file_name_for_tracing); | 483 dump->AddString("file_name", "", file_name_for_tracing); |
| 474 | 484 |
| 475 // Memory is allocated from system allocator (malloc). | 485 // Memory is allocated from system allocator (malloc). |
| 476 pmd->AddSuballocation(dump->guid(), | 486 pmd->AddSuballocation(dump->guid(), |
| 477 base::trace_event::MemoryDumpManager::GetInstance() | 487 base::trace_event::MemoryDumpManager::GetInstance() |
| 478 ->system_allocator_pool_name()); | 488 ->system_allocator_pool_name()); |
| 479 return true; | 489 return true; |
| 480 } | 490 } |
| 481 | 491 |
| 492 std::unique_ptr<leveldb::Iterator> LevelDBDatabase::CreateLevelDBIterator( | |
| 493 const leveldb::Snapshot* snapshot) { | |
| 494 leveldb::ReadOptions read_options; | |
| 495 read_options.verify_checksums = true; | |
| 496 read_options.snapshot = snapshot; | |
| 497 return std::unique_ptr<leveldb::Iterator>(db_->NewIterator(read_options)); | |
| 498 } | |
| 499 | |
| 500 LevelDBDatabase::DetachIteratorOnDestruct::DetachIteratorOnDestruct() {} | |
| 501 | |
| 502 LevelDBDatabase::DetachIteratorOnDestruct::DetachIteratorOnDestruct( | |
| 503 LevelDBIterator* it) | |
| 504 : it_(it) {} | |
| 505 | |
| 506 LevelDBDatabase::DetachIteratorOnDestruct::DetachIteratorOnDestruct( | |
| 507 DetachIteratorOnDestruct&& that) { | |
| 508 it_ = that.it_; | |
| 509 that.it_ = nullptr; | |
| 510 }; | |
| 511 | |
| 512 LevelDBDatabase::DetachIteratorOnDestruct::~DetachIteratorOnDestruct() { | |
| 513 if (it_) | |
| 514 it_->Detach(); | |
| 515 } | |
| 516 | |
| 517 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
| |
| 518 // This line updates the LRU if the item exists. | |
| 519 if (iterator_lru_.Get(iter) != iterator_lru_.end()) | |
| 520 return; | |
| 521 DetachIteratorOnDestruct purger(iter); | |
| 522 iterator_lru_.Put(iter, std::move(purger)); | |
| 523 } | |
| 524 | |
| 525 void LevelDBDatabase::NotifyIteratorDestroyed(LevelDBIterator* iter) { | |
| 526 DCHECK_GT(num_iterators_, 0u); | |
| 527 --num_iterators_; | |
| 528 auto it = iterator_lru_.Peek(iter); | |
| 529 if (it == iterator_lru_.end()) | |
| 530 return; | |
| 531 iterator_lru_.Erase(it); | |
| 532 } | |
| 533 | |
| 482 } // namespace content | 534 } // namespace content |
| OLD | NEW |