blob: c840196b8b62af3ed5cd9de516bd6c32be20afa9 [file] [log] [blame]
// Copyright 2016 The Fuchsia 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 PERIDOT_BIN_LEDGER_STORAGE_IMPL_PAGE_DB_H_
#define PERIDOT_BIN_LEDGER_STORAGE_IMPL_PAGE_DB_H_
#include <memory>
#include <string>
#include <vector>
#include <lib/fxl/logging.h>
#include <lib/fxl/strings/string_view.h>
#include <lib/zx/time.h>
#include "peridot/bin/ledger/coroutine/coroutine.h"
#include "peridot/bin/ledger/storage/public/data_source.h"
#include "peridot/bin/ledger/storage/public/db.h"
#include "peridot/bin/ledger/storage/public/iterator.h"
#include "peridot/bin/ledger/storage/public/journal.h"
#include "peridot/bin/ledger/storage/public/object.h"
#include "peridot/bin/ledger/storage/public/types.h"
namespace storage {
class PageStorageImpl;
// Status of an object in the database.
enum class PageDbObjectStatus {
// The object is not in the database.
UNKNOWN,
// The object is in the database, but not in any commit.
TRANSIENT,
// The object is associated to a commit, but not yet synced.
LOCAL,
// The object is synced.
SYNCED,
};
// |PageDbMutator| provides all update (insertion and deletion) operations
// over |PageDb|.
class PageDbMutator {
public:
PageDbMutator() {}
virtual ~PageDbMutator() {}
// Heads.
// Adds the given |head| in the set of commit heads.
FXL_WARN_UNUSED_RESULT virtual Status AddHead(
coroutine::CoroutineHandler* handler, CommitIdView head,
zx::time_utc timestamp) = 0;
// Removes the given |head| from the head commits.
FXL_WARN_UNUSED_RESULT virtual Status RemoveHead(
coroutine::CoroutineHandler* handler, CommitIdView head) = 0;
// Commits.
// Adds the given |commit| in the database.
FXL_WARN_UNUSED_RESULT virtual Status AddCommitStorageBytes(
coroutine::CoroutineHandler* handler, const CommitId& commit_id,
fxl::StringView storage_bytes) = 0;
// Removes the commit with the given |commit_id| from the commits.
FXL_WARN_UNUSED_RESULT virtual Status RemoveCommit(
coroutine::CoroutineHandler* handler, const CommitId& commit_id) = 0;
// Journals.
// Creates a new id for a journal with the given type and base commit. In a
// merge journal, the base commit is always the left one.
FXL_WARN_UNUSED_RESULT virtual Status CreateJournalId(
coroutine::CoroutineHandler* handler, JournalType journal_type,
const CommitId& base, JournalId* journal_id) = 0;
// Removes all information on explicit journals from the database.
FXL_WARN_UNUSED_RESULT virtual Status RemoveExplicitJournals(
coroutine::CoroutineHandler* handler) = 0;
// Removes all information on the journal with the given |journal_id| from the
// database.
FXL_WARN_UNUSED_RESULT virtual Status RemoveJournal(
coroutine::CoroutineHandler* handler, const JournalId& journal_id) = 0;
// Adds a new |key|-|value| pair with the given |priority| to the journal with
// the given |journal_id|.
FXL_WARN_UNUSED_RESULT virtual Status AddJournalEntry(
coroutine::CoroutineHandler* handler, const JournalId& journal_id,
fxl::StringView key, const ObjectIdentifier& object_identifier,
KeyPriority priority) = 0;
// Removes the given key from the journal with the given |journal_id|.
FXL_WARN_UNUSED_RESULT virtual Status RemoveJournalEntry(
coroutine::CoroutineHandler* handler, const JournalId& journal_id,
convert::ExtendedStringView key) = 0;
// Marks the journal with the given |journal_id| as containing a clear
// operation and removes all entries.
FXL_WARN_UNUSED_RESULT virtual Status
EmptyJournalAndMarkContainsClearOperation(
coroutine::CoroutineHandler* handler, const JournalId& journal_id) = 0;
// Object data.
// Writes the content of the given object.
FXL_WARN_UNUSED_RESULT virtual Status WriteObject(
coroutine::CoroutineHandler* handler, ObjectIdentifier object_identifier,
std::unique_ptr<DataSource::DataChunk> content,
PageDbObjectStatus object_status) = 0;
// Object sync metadata.
// Sets the status of the object with the given id.
FXL_WARN_UNUSED_RESULT virtual Status SetObjectStatus(
coroutine::CoroutineHandler* handler, ObjectIdentifier object_identifier,
PageDbObjectStatus object_status) = 0;
// Commit sync metadata.
// Marks the given |commit_id| as synced.
FXL_WARN_UNUSED_RESULT virtual Status MarkCommitIdSynced(
coroutine::CoroutineHandler* handler, const CommitId& commit_id) = 0;
// Marks the given |commit_id| as unsynced.
FXL_WARN_UNUSED_RESULT virtual Status MarkCommitIdUnsynced(
coroutine::CoroutineHandler* handler, const CommitId& commit_id,
uint64_t generation) = 0;
// Sets the opaque sync metadata associated with this page for the given key.
FXL_WARN_UNUSED_RESULT virtual Status SetSyncMetadata(
coroutine::CoroutineHandler* handler, fxl::StringView key,
fxl::StringView value) = 0;
// Updates the online state of the page.
FXL_WARN_UNUSED_RESULT virtual Status MarkPageOnline(
coroutine::CoroutineHandler* handler) = 0;
private:
FXL_DISALLOW_COPY_AND_ASSIGN(PageDbMutator);
};
// |PageDb| manages all Ledger related data that are locally stored. This
// includes commit, value and tree node objects, information on head commits, as
// well as metadata on which objects and commits are not yet synchronized to the
// cloud.
class PageDb : public PageDbMutator {
public:
// A |Batch| can be used to execute a number of updates in |PageDb|
// atomically.
class Batch : public PageDbMutator {
public:
Batch() {}
~Batch() override {}
// Executes this batch. No further operations in this batch are supported
// after a successful execution.
FXL_WARN_UNUSED_RESULT virtual Status Execute(
coroutine::CoroutineHandler* handler) = 0;
private:
FXL_DISALLOW_COPY_AND_ASSIGN(Batch);
};
PageDb() {}
~PageDb() override {}
// Starts a new batch. The batch will be written when Execute is called on the
// returned object. The PageDb object must outlive the batch object. If the
// coroutine is interrupted, |INTERRUPTED| status is returned.
FXL_WARN_UNUSED_RESULT virtual Status StartBatch(
coroutine::CoroutineHandler* handler, std::unique_ptr<Batch>* batch) = 0;
// Heads.
// Finds all head commits and replaces the contents of |heads| with their ids.
// Returns |OK| on success or |IO_ERROR| in case of an error reading the
// values. It is not an error if no heads are found. The resulting |heads| are
// ordered by the timestamp given at their insertion and if identical, by
// their id.
FXL_WARN_UNUSED_RESULT virtual Status GetHeads(
coroutine::CoroutineHandler* handler, std::vector<CommitId>* heads) = 0;
// Commits.
// Finds the commit with the given |commit_id| and stores its represenation in
// storage bytes in the |storage_bytes| string.
FXL_WARN_UNUSED_RESULT virtual Status GetCommitStorageBytes(
coroutine::CoroutineHandler* handler, CommitIdView commit_id,
std::string* storage_bytes) = 0;
// Journals.
// Finds all implicit journal ids and replaces the contents of |journal_ids|
// with their ids.
FXL_WARN_UNUSED_RESULT virtual Status GetImplicitJournalIds(
coroutine::CoroutineHandler* handler,
std::vector<JournalId>* journal_ids) = 0;
// Stores the id of the base commit for the journal with the given |base|
// parameter.
FXL_WARN_UNUSED_RESULT virtual Status GetBaseCommitForJournal(
coroutine::CoroutineHandler* handler, const JournalId& journal_id,
CommitId* base) = 0;
// Finds all the entries of the journal with the given |journal_id| and stores
// an interator over the results on |entires|. Also returns a flag indicating
// if the journal contains a clear operation, in which case we need to delete
// all pre-existing data from the page upon commit.
FXL_WARN_UNUSED_RESULT virtual Status GetJournalEntries(
coroutine::CoroutineHandler* handler, const JournalId& journal_id,
std::unique_ptr<Iterator<const EntryChange>>* entries,
JournalContainsClearOperation* contains_clear_operation) = 0;
// Object data.
// Reads the content of the given object. To check whether an object is stored
// in the PageDb without retrieving its value, |nullptr| can be given for the
// |object| argument.
FXL_WARN_UNUSED_RESULT virtual Status ReadObject(
coroutine::CoroutineHandler* handler, ObjectIdentifier object_identifier,
std::unique_ptr<const Object>* object) = 0;
// Checks whether the object with the given |object_digest| is stored in the
// database.
FXL_WARN_UNUSED_RESULT virtual Status HasObject(
coroutine::CoroutineHandler* handler, const ObjectDigest& object_digest,
bool* has_object) = 0;
// Returns the status of the object with the given id.
FXL_WARN_UNUSED_RESULT virtual Status GetObjectStatus(
coroutine::CoroutineHandler* handler, ObjectIdentifier object_identifier,
PageDbObjectStatus* object_status) = 0;
// Commit sync metadata.
// Finds the set of unsynced commits and replaces the contents of |commit_ids|
// with their ids. The result is ordered by the timestamps given when calling
// |MarkCommitIdUnsynced|.
FXL_WARN_UNUSED_RESULT virtual Status GetUnsyncedCommitIds(
coroutine::CoroutineHandler* handler,
std::vector<CommitId>* commit_ids) = 0;
// Checks if the commit with the given |commit_id| is synced.
FXL_WARN_UNUSED_RESULT virtual Status IsCommitSynced(
coroutine::CoroutineHandler* handler, const CommitId& commit_id,
bool* is_synced) = 0;
// Object sync metadata.
// Finds the set of unsynced pieces and replaces the contents of
// |object_identifiers| with their identifiers.
FXL_WARN_UNUSED_RESULT virtual Status GetUnsyncedPieces(
coroutine::CoroutineHandler* handler,
std::vector<ObjectIdentifier>* object_identifiers) = 0;
// Sync metadata.
// Retrieves the opaque sync metadata associated with this page for the given
// key.
FXL_WARN_UNUSED_RESULT virtual Status GetSyncMetadata(
coroutine::CoroutineHandler* handler, fxl::StringView key,
std::string* value) = 0;
// Returns whether the page is online, i.e. has been synced to the cloud or a
// peer at least once from this device. By default, the state of a page is
// offline. Once the state is set to online, it cannot be unset.
FXL_WARN_UNUSED_RESULT virtual Status IsPageOnline(
coroutine::CoroutineHandler* handler, bool* page_is_online) = 0;
private:
FXL_DISALLOW_COPY_AND_ASSIGN(PageDb);
};
} // namespace storage
#endif // PERIDOT_BIN_LEDGER_STORAGE_IMPL_PAGE_DB_H_