1 // Copyright 2018 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_FEED_CORE_FEED_JOURNAL_DATABASE_H_ 6 #define COMPONENTS_FEED_CORE_FEED_JOURNAL_DATABASE_H_ 7 8 #include <memory> 9 #include <string> 10 #include <vector> 11 12 #include "base/containers/flat_map.h" 13 #include "base/files/file_path.h" 14 #include "base/macros.h" 15 #include "base/memory/weak_ptr.h" 16 #include "base/sequenced_task_runner.h" 17 #include "components/leveldb_proto/public/proto_database.h" 18 19 namespace leveldb_proto { 20 class ProtoDatabaseProvider; 21 } // namespace leveldb_proto 22 23 namespace feed { 24 25 class JournalMutation; 26 class JournalOperation; 27 class JournalStorageProto; 28 29 using InitStatus = leveldb_proto::Enums::InitStatus; 30 31 // FeedJournalDatabase is leveldb backend store for Feed's journal storage data. 32 // Feed's journal data are key-value pairs. In order to support callers from 33 // different threads, this class posts all database operations to an owned 34 // sequenced task runner. 35 class FeedJournalDatabase { 36 public: 37 // Returns the journal data as a vector of strings when calling loading data 38 // or keys. 39 using JournalLoadCallback = 40 base::OnceCallback<void(bool, std::vector<std::string>)>; 41 42 // Return whether the entry exists when calling for checking 43 // the entry's existence. 44 using CheckExistingCallback = base::OnceCallback<void(bool, bool)>; 45 46 // Returns whether the commit operation succeeded when calling for database 47 // operations. 48 using ConfirmationCallback = base::OnceCallback<void(bool)>; 49 50 using JournalMap = base::flat_map<std::string, JournalStorageProto>; 51 52 using StorageEntryVector = 53 leveldb_proto::ProtoDatabase<JournalStorageProto>::KeyEntryVector; 54 55 // Initializes the database with |proto_database_provider| and 56 // |database_folder|. 57 FeedJournalDatabase( 58 leveldb_proto::ProtoDatabaseProvider* proto_database_provider, 59 const base::FilePath& database_folder); 60 61 // Creates storage using the given |storage_database| for local storage. 62 // Useful for testing. 63 explicit FeedJournalDatabase( 64 std::unique_ptr<leveldb_proto::ProtoDatabase<JournalStorageProto>> 65 storage_database, 66 scoped_refptr<base::SequencedTaskRunner> task_runner); 67 68 ~FeedJournalDatabase(); 69 70 // Returns true if initialization has finished successfully, else false. 71 // While this is false, initialization may already started, or initialization 72 // failed. 73 bool IsInitialized() const; 74 75 // Loads the journal data for the |key| and passes it to |callback|. 76 void LoadJournal(const std::string& key, JournalLoadCallback callback); 77 78 // Checks if the journal for the |key| exists, and return the result to 79 // |callback|. 80 void DoesJournalExist(const std::string& key, CheckExistingCallback callback); 81 82 // Commits the operations in the |journal_mutation|. |callback| will be called 83 // when all the operations are committed. Or if any operation failed, database 84 // will stop process any operations and passed error to |callback|. 85 void CommitJournalMutation(std::unique_ptr<JournalMutation> journal_mutation, 86 ConfirmationCallback callback); 87 88 // Loads all journal keys in the storage, and passes them to |callback|. 89 void LoadAllJournalKeys(JournalLoadCallback callback); 90 91 // Delete all journals, |callback| will be called when all journals are 92 // deleted or if there is an error. 93 void DeleteAllJournals(ConfirmationCallback callback); 94 95 private: 96 // This method performs JournalOperation in the |journal_mutation|. 97 // If the first operation in |journal_mutation| is JOURNAL_DELETE, journal 98 // can be empty, otherwise we need to load |journal| from database and 99 // then pass to this method. 100 void PerformOperations(std::unique_ptr<JournalStorageProto> journal, 101 std::unique_ptr<JournalMutation> journal_mutation, 102 ConfirmationCallback callback); 103 void CommitOperations(base::TimeTicks start_time, 104 std::unique_ptr<JournalStorageProto> journal, 105 JournalMap copy_to_journal, 106 ConfirmationCallback callback); 107 108 // The following *Internal methods must be executed from |task_runner_|. 109 void InitInternal(); 110 void GetEntryInternal( 111 const std::string& key, 112 leveldb_proto::Callbacks::Internal<JournalStorageProto>::GetCallback 113 callback); 114 void LoadKeysInternal(JournalLoadCallback callback); 115 void DeleteAllEntriesInternal(ConfirmationCallback callback); 116 void UpdateEntriesInternal( 117 std::unique_ptr<StorageEntryVector> entries_to_save, 118 std::unique_ptr<std::vector<std::string>> keys_to_remove, 119 base::TimeTicks start_time, 120 ConfirmationCallback callback); 121 122 // Callback methods given to |storage_database_| for async responses. 123 void OnDatabaseInitialized(InitStatus status); 124 void OnGetEntryForLoadJournal(base::TimeTicks start_time, 125 JournalLoadCallback callback, 126 bool success, 127 std::unique_ptr<JournalStorageProto> journal); 128 void OnGetEntryForDoesJournalExist( 129 base::TimeTicks start_time, 130 CheckExistingCallback callback, 131 bool success, 132 std::unique_ptr<JournalStorageProto> journal); 133 void OnGetEntryForCommitJournalMutation( 134 std::unique_ptr<JournalMutation> journal_mutation, 135 ConfirmationCallback callback, 136 bool success, 137 std::unique_ptr<JournalStorageProto> journal); 138 void OnLoadKeysForLoadAllJournalKeys( 139 base::TimeTicks start_time, 140 JournalLoadCallback callback, 141 bool success, 142 std::unique_ptr<std::vector<std::string>> keys); 143 void OnOperationCommitted(base::TimeTicks start_time, 144 ConfirmationCallback callback, 145 bool success); 146 147 JournalStorageProto CopyJournal(const std::string& new_journal_name, 148 const JournalStorageProto& source_journal); 149 150 // Status of the database initialization. 151 InitStatus database_status_; 152 153 // Task runner on which to execute database calls. 154 scoped_refptr<base::SequencedTaskRunner> task_runner_; 155 156 // The database for storing journal storage information. 157 std::unique_ptr<leveldb_proto::ProtoDatabase<JournalStorageProto>> 158 storage_database_; 159 160 base::WeakPtrFactory<FeedJournalDatabase> weak_ptr_factory_{this}; 161 162 DISALLOW_COPY_AND_ASSIGN(FeedJournalDatabase); 163 }; 164 165 } // namespace feed 166 167 #endif // COMPONENTS_FEED_CORE_FEED_JOURNAL_DATABASE_H_ 168