blob: fc1707cf6400ccf52b04db7b5c38f0788228bc38 [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.
#include <memory>
#include <lib/callback/auto_cleanable.h>
#include <lib/fit/function.h>
#include <lib/fxl/memory/weak_ptr.h>
#include "peridot/bin/ledger/app/page_snapshot_impl.h"
#include "peridot/bin/ledger/coroutine/coroutine.h"
#include "peridot/bin/ledger/storage/public/commit_watcher.h"
#include "peridot/bin/ledger/storage/public/page_storage.h"
#include "peridot/bin/ledger/storage/public/types.h"
namespace ledger {
class PageManager;
// Tracks the head of a commit "branch". A commit is chosen arbitrarily from the
// page's head commits at construction. Subsequently, this object will track the
// head of this commit branch, unless reset by |SetBranchHead|. If two commits
// have the same parent, the first one to be received will be tracked.
class BranchTracker : public storage::CommitWatcher {
BranchTracker(coroutine::CoroutineService* coroutine_service,
PageManager* manager, storage::PageStorage* storage);
~BranchTracker() override;
void Init(fit::function<void(Status)> on_done);
void set_on_empty(fit::closure on_empty_callback);
// Returns the head commit of the currently tracked branch.
const storage::CommitId& GetBranchHeadId();
// Registers a new PageWatcher interface.
void RegisterPageWatcher(PageWatcherPtr page_watcher_ptr,
std::unique_ptr<const storage::Commit> base_commit,
std::string key_prefix);
// Informs the BranchTracker that a transaction is in progress. It first
// drains all pending Watcher updates, then stops sending them until
// |StopTransaction| is called. |watchers_drained_callback| is called when all
// watcher updates have been processed by the clients. This should be used by
// |PageDelegate| when a transaction is in progress.
void StartTransaction(fit::closure watchers_drained_callback);
// Informs the BranchTracker that a transaction is no longer in progress.
// Resumes sending updates to registered watchers. This should be used by
// |PageDelegate| when a transaction is committed or rolled back.
// |commit| must be the one created by the transaction if it was committed, or
// nullptr otherwise.
void StopTransaction(std::unique_ptr<const storage::Commit> commit);
// Returns true if there are no watchers registered.
bool IsEmpty();
class PageWatcherContainer;
// storage::CommitWatcher:
void OnNewCommits(
const std::vector<std::unique_ptr<const storage::Commit>>& commits,
storage::ChangeSource source) override;
void InitCommitAndSetWatcher(storage::CommitId commit_id);
void CheckEmpty();
coroutine::CoroutineService* coroutine_service_;
PageManager* manager_;
storage::PageStorage* storage_;
callback::AutoCleanableSet<PageWatcherContainer> watchers_;
fit::closure on_empty_callback_;
bool transaction_in_progress_;
// The following two variables hold the commit object and id correspondingly
// of the commit tracked by this BranchTracker. |current_commit_| is used
// for notifying the watchers. On initialization, |current_commit_id_| is set
// to track the first head as returned from PageStorage. |current_commit_| at
// that point equals nullptr and is only updated with a valid Commit,
// corresponding to the tracked id, after the first call to OnNewCommits or
// StopTransaction. Since the notifications are sent to the watchers only
// after updating the tracked commit, the value of the |current_commit_| at
// initialization (which is set to nullptr) is not necessary.
std::unique_ptr<const storage::Commit> current_commit_;
storage::CommitId current_commit_id_;
// This must be the last member of the class.
fxl::WeakPtrFactory<BranchTracker> weak_factory_;
} // namespace ledger