blob: 0b1596e51d355c1d1d6cc0bc93aa2cd3feed1f42 [file] [log] [blame]
// 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_SERVICES_STORAGE_INDEXED_DB_SCOPES_LEVELDB_SCOPES_H_
#define COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_LEVELDB_SCOPES_H_
#include <stdint.h>
#include <limits>
#include <list>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/checked_math.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "components/services/storage/indexed_db/scopes/leveldb_scopes_coding.h"
#include "components/services/storage/indexed_db/scopes/scope_lock.h"
#include "components/services/storage/indexed_db/scopes/scope_lock_range.h"
#include "third_party/leveldatabase/src/include/leveldb/options.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
namespace content {
class LevelDBScope;
class LevelDBState;
class ScopesLockManager;
class LevelDBScopes {
public:
using TearDownCallback = base::RepeatingCallback<void(leveldb::Status)>;
using EmptyRange = std::pair<std::string, std::string>;
enum class TaskRunnerMode {
// No new sequence runners are created. Both the cleanup and the revert
// tasks are run using the sequence runner that is calling this class.
kUseCurrentSequence,
// A new sequence runner is created for both the cleanup tasks and the
// revert tasks.
kNewCleanupAndRevertSequences,
};
// |lock_manager| is expected to be alive during the lifetime of this class.
// |tear_down_callback| will not be called after the destruction of this
// class.
LevelDBScopes(std::vector<uint8_t> metadata_key_prefix,
size_t max_write_batch_size_bytes_bytes,
scoped_refptr<LevelDBState> level_db,
ScopesLockManager* lock_manager,
TearDownCallback tear_down_callback);
~LevelDBScopes();
// This method needs to be called before any other method on this class. If
// unsuccessful, the class cannot be used. Note, this will acquire locks for
// the revert tasks if necessary.
leveldb::Status Initialize();
// This starts (or adopts) the task runners associated with aborting and
// cleaning up previous logs based on the given |mode|, and schedules any
// pending cleanup or revert tasks.
// Returns any errors that might occur during revert if |mode| is
// kUseCurrentSequence.
leveldb::Status StartRecoveryAndCleanupTasks(TaskRunnerMode mode);
// In |empty_ranges|, |pair.first| is the inclusive range begin, and
// |pair.end| is the exclusive range end. The ranges must be disjoint (they
// cannot overlap).
std::unique_ptr<LevelDBScope> CreateScope(
std::vector<ScopeLock> locks,
std::vector<EmptyRange> empty_ranges);
leveldb::Status Commit(std::unique_ptr<LevelDBScope> scope,
bool sync_on_commit);
// |on_complete| will be called when the cleanup task for the scope has
// finished operating.
leveldb::Status Commit(std::unique_ptr<LevelDBScope> scope,
bool sync_on_commit,
base::OnceClosure on_complete);
base::SequencedTaskRunner* RevertRunnerForTesting() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return revert_runner_.get();
}
base::SequencedTaskRunner* CleanupRunnerForTesting() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return cleanup_runner_.get();
}
const std::vector<uint8_t>& metadata_key_prefix() const {
return metadata_key_prefix_;
}
const TearDownCallback& tear_down_callback() { return tear_down_callback_; }
private:
enum class StartupCleanupType { kExecuteCleanupTasks, kIgnoreCleanupTasks };
using StartupScopeToRevert = std::pair<int64_t, std::vector<ScopeLock>>;
using StartupScopeToCleanup = std::pair<int64_t, StartupCleanupType>;
using RecoveryLocksList = std::list<std::vector<ScopeLock>>;
leveldb::Status InitializeGlobalMetadata(
const leveldb::ReadOptions& read_options,
const leveldb::WriteOptions& write_options);
leveldb::Status InitializeScopesAndTasks(
const leveldb::ReadOptions& read_options,
const leveldb::WriteOptions& write_options);
// If the mode is TaskRunnerMode::kUseCurrentSequence, then the result of the
// revert task is returned.
leveldb::Status Rollback(int64_t scope_id, std::vector<ScopeLock> locks);
void OnCleanupTaskResult(base::OnceClosure on_complete,
leveldb::Status result);
void StartRevertTask(int64_t scope_id, std::vector<ScopeLock> locks);
void OnRevertTaskResult(int64_t scope_id,
std::vector<ScopeLock> locks,
leveldb::Status result);
SEQUENCE_CHECKER(sequence_checker_);
const std::vector<uint8_t> metadata_key_prefix_;
const size_t max_write_batch_size_bytes_;
std::vector<StartupScopeToCleanup> startup_scopes_to_clean_;
std::vector<StartupScopeToRevert> startup_scopes_to_revert_;
scoped_refptr<base::SequencedTaskRunner> revert_runner_;
scoped_refptr<base::SequencedTaskRunner> cleanup_runner_;
// This gets set to |true| when |Initialize()| succeeds.
bool recovery_finished_ = false;
int next_scope_id_ = 0;
scoped_refptr<LevelDBState> level_db_;
// The |lock_manager_| is expected to outlive this class.
ScopesLockManager* lock_manager_;
TearDownCallback tear_down_callback_;
#if DCHECK_IS_ON()
bool initialize_called_ = false;
#endif
base::WeakPtrFactory<LevelDBScopes> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(LevelDBScopes);
};
} // namespace content
#endif // COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_LEVELDB_SCOPES_H_