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_SERVICES_STORAGE_INDEXED_DB_SCOPES_LEVELDB_SCOPES_H_
6 #define COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_LEVELDB_SCOPES_H_
7 
8 #include <stdint.h>
9 #include <limits>
10 #include <list>
11 #include <memory>
12 #include <string>
13 #include <tuple>
14 #include <utility>
15 #include <vector>
16 
17 #include "base/callback.h"
18 #include "base/macros.h"
19 #include "base/memory/scoped_refptr.h"
20 #include "base/memory/weak_ptr.h"
21 #include "base/numerics/checked_math.h"
22 #include "base/sequence_checker.h"
23 #include "base/sequenced_task_runner.h"
24 #include "components/services/storage/indexed_db/scopes/leveldb_scopes_coding.h"
25 #include "components/services/storage/indexed_db/scopes/scope_lock.h"
26 #include "components/services/storage/indexed_db/scopes/scope_lock_range.h"
27 #include "third_party/leveldatabase/src/include/leveldb/options.h"
28 #include "third_party/leveldatabase/src/include/leveldb/status.h"
29 
30 namespace content {
31 class LevelDBScope;
32 class LevelDBState;
33 class ScopesLockManager;
34 
35 class LevelDBScopes {
36  public:
37   using TearDownCallback = base::RepeatingCallback<void(leveldb::Status)>;
38   using EmptyRange = std::pair<std::string, std::string>;
39   static constexpr const size_t kDefaultMaxWriteBatchSizeBytes = 1024 * 1024;
40 
41   enum class TaskRunnerMode {
42     // No new sequence runners are created. Both the cleanup and the revert
43     // tasks are run using the sequence runner that is calling this class.
44     kUseCurrentSequence,
45     // A new sequence runner is created for both the cleanup tasks and the
46     // revert tasks.
47     kNewCleanupAndRevertSequences,
48   };
49 
50   // |lock_manager| is expected to be alive during the lifetime of this class.
51   // |tear_down_callback| will not be called after the destruction of this
52   // class.
53   LevelDBScopes(std::vector<uint8_t> metadata_key_prefix,
54                 size_t max_write_batch_size_bytes_bytes,
55                 scoped_refptr<LevelDBState> level_db,
56                 ScopesLockManager* lock_manager,
57                 TearDownCallback tear_down_callback);
58   ~LevelDBScopes();
59 
60   // This method needs to be called before any other method on this class. If
61   // unsuccessful, the class cannot be used. Note, this will acquire locks for
62   // the revert tasks if necessary.
63   leveldb::Status Initialize();
64 
65   // This starts (or adopts) the task runners associated with aborting and
66   // cleaning up previous logs based on the given |mode|, and schedules any
67   // pending cleanup or revert tasks.
68   // Returns any errors that might occur during revert if |mode| is
69   // kUseCurrentSequence.
70   leveldb::Status StartRecoveryAndCleanupTasks(TaskRunnerMode mode);
71 
72   // In |empty_ranges|, |pair.first| is the inclusive range begin, and
73   // |pair.end| is the exclusive range end. The ranges must be disjoint (they
74   // cannot overlap).
75   std::unique_ptr<LevelDBScope> CreateScope(
76       std::vector<ScopeLock> locks,
77       std::vector<EmptyRange> empty_ranges);
78 
79   leveldb::Status Commit(std::unique_ptr<LevelDBScope> scope,
80                          bool sync_on_commit);
81 
82   // |on_complete| will be called when the cleanup task for the scope has
83   // finished operating.
84   leveldb::Status Commit(std::unique_ptr<LevelDBScope> scope,
85                          bool sync_on_commit,
86                          base::OnceClosure on_complete);
87 
RevertRunnerForTesting()88   base::SequencedTaskRunner* RevertRunnerForTesting() const {
89     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
90     return revert_runner_.get();
91   }
92 
CleanupRunnerForTesting()93   base::SequencedTaskRunner* CleanupRunnerForTesting() const {
94     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
95     return cleanup_runner_.get();
96   }
97 
metadata_key_prefix()98   const std::vector<uint8_t>& metadata_key_prefix() const {
99     return metadata_key_prefix_;
100   }
101 
tear_down_callback()102   const TearDownCallback& tear_down_callback() { return tear_down_callback_; }
103 
104  private:
105   enum class StartupCleanupType { kExecuteCleanupTasks, kIgnoreCleanupTasks };
106   using StartupScopeToRevert = std::pair<int64_t, std::vector<ScopeLock>>;
107   using StartupScopeToCleanup = std::pair<int64_t, StartupCleanupType>;
108   using RecoveryLocksList = std::list<std::vector<ScopeLock>>;
109 
110   leveldb::Status InitializeGlobalMetadata(
111       const leveldb::ReadOptions& read_options,
112       const leveldb::WriteOptions& write_options);
113   leveldb::Status InitializeScopesAndTasks(
114       const leveldb::ReadOptions& read_options,
115       const leveldb::WriteOptions& write_options);
116 
117   // If the mode is TaskRunnerMode::kUseCurrentSequence, then the result of the
118   // revert task is returned.
119   leveldb::Status Rollback(int64_t scope_id, std::vector<ScopeLock> locks);
120 
121   void OnCleanupTaskResult(base::OnceClosure on_complete,
122                            leveldb::Status result);
123 
124   void StartRevertTask(int64_t scope_id, std::vector<ScopeLock> locks);
125 
126   void OnRevertTaskResult(int64_t scope_id,
127                           std::vector<ScopeLock> locks,
128                           leveldb::Status result);
129 
130   SEQUENCE_CHECKER(sequence_checker_);
131   const std::vector<uint8_t> metadata_key_prefix_;
132   const size_t max_write_batch_size_bytes_;
133   std::vector<StartupScopeToCleanup> startup_scopes_to_clean_;
134   std::vector<StartupScopeToRevert> startup_scopes_to_revert_;
135   scoped_refptr<base::SequencedTaskRunner> revert_runner_;
136   scoped_refptr<base::SequencedTaskRunner> cleanup_runner_;
137 
138   // This gets set to |true| when |Initialize()| succeeds.
139   bool recovery_finished_ = false;
140   int next_scope_id_ = 0;
141   scoped_refptr<LevelDBState> level_db_;
142   // The |lock_manager_| is expected to outlive this class.
143   ScopesLockManager* lock_manager_;
144   TearDownCallback tear_down_callback_;
145 
146 #if DCHECK_IS_ON()
147   bool initialize_called_ = false;
148 #endif
149 
150   base::WeakPtrFactory<LevelDBScopes> weak_factory_{this};
151   DISALLOW_COPY_AND_ASSIGN(LevelDBScopes);
152 };
153 
154 }  // namespace content
155 
156 #endif  // COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_LEVELDB_SCOPES_H_
157