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