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