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 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_SERVICES_STORAGE_INDEXED_DB_TRANSACTIONAL_LEVELDB_TRANSACTIONAL_LEVELDB_DATABASE_H_ 6 #define COMPONENTS_SERVICES_STORAGE_INDEXED_DB_TRANSACTIONAL_LEVELDB_TRANSACTIONAL_LEVELDB_DATABASE_H_ 7 8 #include <memory> 9 #include <string> 10 11 #include "base/containers/flat_set.h" 12 #include "base/containers/mru_cache.h" 13 #include "base/files/file_path.h" 14 #include "base/gtest_prod_util.h" 15 #include "base/macros.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/sequenced_task_runner.h" 18 #include "base/strings/string_piece.h" 19 #include "base/time/clock.h" 20 #include "base/trace_event/memory_dump_provider.h" 21 #include "components/services/storage/indexed_db/leveldb/leveldb_state.h" 22 #include "third_party/leveldatabase/src/include/leveldb/options.h" 23 #include "third_party/leveldatabase/src/include/leveldb/status.h" 24 25 namespace leveldb { 26 class DB; 27 class Env; 28 class Snapshot; 29 } // namespace leveldb 30 31 namespace content { 32 class TransactionalLevelDBDatabase; 33 class TransactionalLevelDBFactory; 34 class TransactionalLevelDBIterator; 35 class TransactionalLevelDBTransaction; 36 class LevelDBScopes; 37 class LevelDBWriteBatch; 38 39 // This class manages the acquisition and release of a leveldb snapshot. 40 class LevelDBSnapshot { 41 public: 42 explicit LevelDBSnapshot(TransactionalLevelDBDatabase* db); 43 ~LevelDBSnapshot(); 44 snapshot()45 const leveldb::Snapshot* snapshot() const { return snapshot_; } 46 47 private: 48 leveldb::DB* db_; 49 const leveldb::Snapshot* snapshot_; 50 51 DISALLOW_COPY_AND_ASSIGN(LevelDBSnapshot); 52 }; 53 54 class TransactionalLevelDBDatabase 55 : public base::trace_event::MemoryDumpProvider { 56 public: 57 // Necessary because every iterator hangs onto leveldb blocks which can be 58 // large. See https://crbug/696055. 59 static const size_t kDefaultMaxOpenIteratorsPerDatabase = 50; 60 61 ~TransactionalLevelDBDatabase() override; 62 63 leveldb::Status Put(const base::StringPiece& key, std::string* value); 64 leveldb::Status Remove(const base::StringPiece& key); 65 virtual leveldb::Status Get(const base::StringPiece& key, 66 std::string* value, 67 bool* found); 68 virtual leveldb::Status Write(LevelDBWriteBatch* write_batch); 69 70 // This iterator will stay up-to-date with changes made to this database 71 // object (as in, automatically reload when values are modified), but not 72 // from any transactions. 73 // LevelDBIterator must not outlive the LevelDBDatabase. 74 // Note: Use DefaultReadOptions() and then adjust any values afterwards. 75 std::unique_ptr<TransactionalLevelDBIterator> CreateIterator( 76 leveldb::ReadOptions options); 77 78 void Compact(const base::StringPiece& start, const base::StringPiece& stop); 79 void CompactAll(); 80 81 leveldb::ReadOptions DefaultReadOptions(); 82 83 // base::trace_event::MemoryDumpProvider implementation. 84 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, 85 base::trace_event::ProcessMemoryDump* pmd) override; 86 leveldb_state()87 LevelDBState* leveldb_state() { return level_db_state_.get(); } db()88 leveldb::DB* db() { return level_db_state_->db(); } env()89 leveldb::Env* env() { return level_db_state_->in_memory_env(); } scopes()90 LevelDBScopes* scopes() { return scopes_.get(); } LastModified()91 base::Time LastModified() const { return last_modified_; } 92 class_factory()93 TransactionalLevelDBFactory* class_factory() const { return class_factory_; } 94 95 void SetClockForTesting(std::unique_ptr<base::Clock> clock); 96 97 private: 98 friend class DefaultTransactionalLevelDBFactory; 99 friend class LevelDBSnapshot; 100 friend class TransactionalLevelDBIterator; 101 friend class TransactionalLevelDBTransaction; 102 friend class LevelDBTestDatabase; 103 FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, DeleteFailsIfDirectoryLocked); 104 class IteratorNotifier; 105 106 // |max_open_cursors| cannot be 0. 107 // All calls to this class should be done on |task_runner|. 108 TransactionalLevelDBDatabase( 109 scoped_refptr<LevelDBState> level_db_state, 110 std::unique_ptr<LevelDBScopes> leveldb_scopes, 111 TransactionalLevelDBFactory* factory, 112 scoped_refptr<base::SequencedTaskRunner> task_runner, 113 size_t max_open_iterators); 114 115 void EvictAllIterators(); 116 117 void OnIteratorUsed(TransactionalLevelDBIterator* iterator); 118 void OnIteratorLoaded(TransactionalLevelDBIterator* iterator); 119 void OnIteratorEvicted(TransactionalLevelDBIterator* iterator); 120 void OnIteratorDestroyed(TransactionalLevelDBIterator* iterator); 121 122 void CloseDatabase(); 123 124 // This iterator will stay up-to-date with changes from this |txn| (as 125 // in, automatically reload when values are modified), but not any other 126 // transactions or the database. 127 // LevelDBIterator must not outlive the LevelDBDatabase. 128 // Note: Use DefaultReadOptions() and then adjust any values afterwards. 129 std::unique_ptr<TransactionalLevelDBIterator> CreateIterator( 130 base::WeakPtr<TransactionalLevelDBTransaction> txn, 131 leveldb::ReadOptions options); 132 133 scoped_refptr<LevelDBState> level_db_state_; 134 std::unique_ptr<LevelDBScopes> scopes_; 135 TransactionalLevelDBFactory* class_factory_; 136 base::Time last_modified_; 137 std::unique_ptr<base::Clock> clock_; 138 139 // Contains all iterators created by this database directly through 140 // |CreateIterator| WITHOUT a transaction. Iterators created with a 141 // transaction will not be added to this list. Raw pointers are safe here 142 // because the destructor of TransactionalLevelDBIterator removes itself from 143 // its associated database. |db_only_loaded_iterators_| have loaded 144 // leveldb::Iterators, and |db_only_evicted_iterators_| have had their 145 // leveldb::Iterator evicted. It is performant to have 146 // |db_only_loaded_iterators_| as a flat_set, as the iterator pooling feature 147 // of TransactionalLevelDBDatabase ensures a maximum number of 148 // kDefaultMaxOpenIteratorsPerDatabase loaded iterators. 149 base::flat_set<TransactionalLevelDBIterator*> db_only_loaded_iterators_; 150 std::set<TransactionalLevelDBIterator*> db_only_evicted_iterators_; 151 bool is_evicting_all_loaded_iterators_ = false; 152 153 struct DetachIteratorOnDestruct { 154 DetachIteratorOnDestruct() = default; 155 explicit DetachIteratorOnDestruct(TransactionalLevelDBIterator* it); 156 DetachIteratorOnDestruct(DetachIteratorOnDestruct&& that); 157 ~DetachIteratorOnDestruct(); 158 159 TransactionalLevelDBIterator* it = nullptr; 160 161 DISALLOW_COPY_AND_ASSIGN(DetachIteratorOnDestruct); 162 }; 163 // Despite the type name, this object uses LRU eviction. Raw pointers are safe 164 // here because the destructor of TransactionalLevelDBIterator removes itself 165 // from its associated database. 166 base::HashingMRUCache<TransactionalLevelDBIterator*, DetachIteratorOnDestruct> 167 iterator_lru_; 168 169 // Recorded for UMA reporting. 170 uint32_t num_iterators_ = 0; 171 uint32_t max_iterators_ = 0; 172 173 base::WeakPtrFactory<TransactionalLevelDBDatabase> 174 weak_factory_for_iterators_{this}; 175 }; 176 177 } // namespace content 178 179 #endif // COMPONENTS_SERVICES_STORAGE_INDEXED_DB_TRANSACTIONAL_LEVELDB_TRANSACTIONAL_LEVELDB_DATABASE_H_ 180