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 |