[go: nahoru, domu]

blob: 89fa64ea846057bba9d4c179adb6df44edf224c2 [file] [log] [blame]
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// 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 "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/strings/string_piece.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/clock.h"
#include "base/time/time.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 {
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> 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(const base::StringPiece& key, std::string* value);
leveldb::Status Remove(const base::StringPiece& key);
virtual leveldb::Status Get(const base::StringPiece& 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(const base::StringPiece& start, const base::StringPiece& 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(); }
base::Time LastModified() const { return last_modified_; }
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_;
base::Time last_modified_;
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<TransactionalLevelDBIterator*> db_only_loaded_iterators_;
std::set<TransactionalLevelDBIterator*> 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
#endif // COMPONENTS_SERVICES_STORAGE_INDEXED_DB_TRANSACTIONAL_LEVELDB_TRANSACTIONAL_LEVELDB_DATABASE_H_