123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- // Copyright 2018 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_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_H_
- #define COMPONENTS_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_H_
- #include <memory>
- #include <string>
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/cancelable_callback.h"
- #include "base/component_export.h"
- #include "base/containers/queue.h"
- #include "base/gtest_prod_util.h"
- #include "base/memory/ref_counted.h"
- #include "base/sequence_checker.h"
- #include "base/synchronization/lock.h"
- #include "base/time/time.h"
- #include "components/leveldb_proto/internal/proto/shared_db_metadata.pb.h"
- #include "components/leveldb_proto/internal/shared_proto_database_client.h"
- #include "components/leveldb_proto/public/proto_database.h"
- namespace leveldb_proto {
- // Controls a single LevelDB database to be used by many clients, and provides
- // a way to get SharedProtoDatabaseClients that allow shared access to the
- // underlying single database.
- class COMPONENT_EXPORT(LEVELDB_PROTO) SharedProtoDatabase
- : public base::RefCountedThreadSafe<SharedProtoDatabase> {
- public:
- using SharedClientInitCallback =
- base::OnceCallback<void(Enums::InitStatus,
- SharedDBMetadataProto::MigrationStatus)>;
- SharedProtoDatabase(const SharedProtoDatabase&) = delete;
- SharedProtoDatabase& operator=(const SharedProtoDatabase&) = delete;
- // Always returns a SharedProtoDatabaseClient pointer, but that should ONLY
- // be used if the callback returns success.
- std::unique_ptr<SharedProtoDatabaseClient> GetClientForTesting(
- ProtoDbType db_type,
- bool create_if_missing,
- SharedClientInitCallback callback);
- // A version of GetClient that returns the client in a callback instead of
- // giving back a client instance immediately.
- void GetClientAsync(
- ProtoDbType db_type,
- bool create_if_missing,
- base::OnceCallback<void(std::unique_ptr<SharedProtoDatabaseClient>,
- Enums::InitStatus)> callback);
- void GetDatabaseInitStatusAsync(const std::string& client_db_id,
- Callbacks::InitStatusCallback callback);
- void UpdateClientMetadataAsync(
- const std::string& client_db_id,
- SharedDBMetadataProto::MigrationStatus migration_status,
- Callbacks::UpdateCallback callback);
- protected:
- SharedProtoDatabase(const std::string& client_db_id,
- const base::FilePath& db_dir);
- virtual ~SharedProtoDatabase();
- private:
- friend class base::RefCountedThreadSafe<SharedProtoDatabase>;
- friend class ProtoDatabaseProvider;
- template <typename T>
- friend class ProtoDatabaseImplTest;
- friend class SharedProtoDatabaseTest;
- friend class SharedProtoDatabaseClientTest;
- friend class TestSharedProtoDatabase;
- friend class TestSharedProtoDatabaseClient;
- FRIEND_TEST_ALL_PREFIXES(SharedProtoDatabaseTest,
- CancelDeleteObsoleteClients);
- FRIEND_TEST_ALL_PREFIXES(SharedProtoDatabaseTest, DeleteObsoleteClients);
- enum InitState {
- // Initialization hasn't been attempted.
- kNotAttempted,
- // Initialization is in progress, new requests will be enqueued.
- kInProgress,
- // Initialization successful, new requests will return existing DB.
- kSuccess,
- // Initialization failed, new requests will return InitStatus::kError.
- kFailure,
- // Shared database doesn't exist, new requests with create_if_missing ==
- // true will attempt to create it, if create_if_missing == false then will
- // return InitStatus::kInvalidOperation.
- kNotFound,
- };
- struct InitRequest {
- InitRequest(SharedClientInitCallback callback,
- const scoped_refptr<base::SequencedTaskRunner>& task_runner,
- const std::string& client_db_id);
- ~InitRequest();
- SharedClientInitCallback callback;
- scoped_refptr<base::SequencedTaskRunner> task_runner;
- std::string client_db_id;
- };
- // Make sure to give enough time after startup so that we have less chance of
- // affecting startup or navigations.
- static const base::TimeDelta kDelayToClearObsoleteDatabase;
- void Shutdown();
- void ProcessInitRequests(Enums::InitStatus status);
- std::unique_ptr<SharedProtoDatabaseClient> GetClientInternal(
- ProtoDbType db_type);
- void OnGetClientMetadata(
- const std::string& client_db_id,
- SharedClientInitCallback callback,
- scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
- bool success,
- std::unique_ptr<SharedDBMetadataProto> proto);
- // |callback_task_runner| should be the same sequence that Init was called
- // from.
- virtual void Init(
- bool create_if_missing,
- const std::string& client_db_id,
- SharedClientInitCallback callback,
- scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
- void InitMetadataDatabase(int attempt, bool corruption);
- void OnMetadataInitComplete(int attempt,
- bool corruption,
- leveldb_proto::Enums::InitStatus status);
- void OnGetGlobalMetadata(bool corruption,
- bool success,
- std::unique_ptr<SharedDBMetadataProto> proto);
- void OnWriteMetadataAtInit(bool success);
- void OnDestroySharedDatabase(bool success);
- void InitDatabase();
- void OnDatabaseInit(bool create_if_missing, Enums::InitStatus status);
- void CheckCorruptionAndRunInitCallback(
- const std::string& client_db_id,
- SharedClientInitCallback callback,
- scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
- Enums::InitStatus status);
- void GetClientMetadataAsync(
- const std::string& client_db_id,
- SharedClientInitCallback callback,
- scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
- void OnUpdateCorruptionCountAtInit(bool success);
- void CommitUpdatedGlobalMetadata(Callbacks::UpdateCallback callback);
- void RunInitCallback(
- Callbacks::InitStatusCallback callback,
- scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
- // |done| will be called on |task_runner|.
- virtual void DestroyObsoleteSharedProtoDatabaseClients(
- Callbacks::UpdateCallback done);
- LevelDB* GetLevelDBForTesting() const;
- void SetDeleteObsoleteDelayForTesting(base::TimeDelta delay);
- scoped_refptr<base::SequencedTaskRunner> database_task_runner_for_testing()
- const {
- return task_runner_;
- }
- SEQUENCE_CHECKER(on_task_runner_);
- InitState init_state_ = InitState::kNotAttempted;
- // This TaskRunner is used to properly sequence Init calls and checks for the
- // current init state. When clients request the current InitState as part of
- // their call to their Init function, the request is put into this TaskRunner.
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- base::FilePath db_dir_;
- std::unique_ptr<LevelDB> db_;
- std::unique_ptr<ProtoLevelDBWrapper> db_wrapper_;
- std::unique_ptr<ProtoDatabase<SharedDBMetadataProto>> metadata_db_wrapper_;
- std::unique_ptr<SharedDBMetadataProto> metadata_;
- // Used to return to the Init callback in the case of an error, so we can
- // report corruptions.
- Enums::InitStatus init_status_ = Enums::InitStatus::kNotInitialized;
- base::queue<std::unique_ptr<InitRequest>> outstanding_init_requests_;
- bool create_if_missing_ = false;
- base::TimeDelta delete_obsolete_delay_ = base::Seconds(120);
- base::Lock delete_obsolete_delay_lock_;
- base::CancelableOnceClosure delete_obsolete_task_;
- };
- } // namespace leveldb_proto
- #endif // COMPONENTS_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_H_
|