blob: 82a3ad84a6e75cdd54e2635cf6dd3d481fbf0757 [file] [log] [blame]
// Copyright 2017 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_APP_MERGING_CONFLICT_RESOLVER_CLIENT_H_
#define PERIDOT_BIN_LEDGER_APP_MERGING_CONFLICT_RESOLVER_CLIENT_H_
#include <memory>
#include <vector>
#include <lib/callback/operation_serializer.h>
#include <lib/callback/waiter.h>
#include <lib/fit/function.h>
#include <lib/fxl/macros.h>
#include <lib/fxl/memory/weak_ptr.h>
#include "peridot/bin/ledger/app/diff_utils.h"
#include "peridot/bin/ledger/app/page_manager.h"
#include "peridot/bin/ledger/fidl/include/types.h"
#include "peridot/bin/ledger/storage/public/commit.h"
#include "peridot/bin/ledger/storage/public/page_storage.h"
namespace ledger {
// Client handling communication with a ConflictResolver interface in order to
// merge conflicting commit branches. It is used both by AutoMergeStrategy and
// CustomMergeStrategy.
class ConflictResolverClient : public MergeResultProvider {
public:
explicit ConflictResolverClient(
storage::PageStorage* storage, PageManager* page_manager,
ConflictResolver* conflict_resolver,
std::unique_ptr<const storage::Commit> left,
std::unique_ptr<const storage::Commit> right,
std::unique_ptr<const storage::Commit> ancestor,
fit::function<void(Status)> callback);
~ConflictResolverClient() override;
void Start();
void Cancel();
private:
void OnNextMergeResult(
const MergedValue& merged_value,
const fxl::RefPtr<callback::Waiter<storage::Status,
storage::ObjectIdentifier>>& waiter);
void Finalize(Status status);
// Performs a diff of the given type on the conflict.
void GetDiff(diff_utils::DiffType type, std::unique_ptr<Token> token,
fit::function<void(Status, fidl::VectorPtr<DiffEntry>,
std::unique_ptr<Token>)>
callback);
// MergeResultProvider:
void GetFullDiff(std::unique_ptr<Token> token,
GetFullDiffCallback callback) override;
void GetConflictingDiff(std::unique_ptr<Token> token,
GetConflictingDiffCallback callback) override;
void Merge(fidl::VectorPtr<MergedValue> merged_values,
MergeCallback callback) override;
void MergeNonConflictingEntries(
MergeNonConflictingEntriesCallback callback) override;
void Done(DoneCallback callback) override;
// Checks whether this ConflictResolverClient is not cancelled and the storage
// returned status is ok. If not, calls the given |callback| and |Finalize|
// with an error status.
bool IsInValidStateAndNotify(const MergeCallback& callback,
storage::Status status = storage::Status::OK);
storage::PageStorage* const storage_;
PageManager* const manager_;
ConflictResolver* const conflict_resolver_;
std::unique_ptr<const storage::Commit> const left_;
std::unique_ptr<const storage::Commit> const right_;
std::unique_ptr<const storage::Commit> const ancestor_;
fit::function<void(Status)> callback_;
// |has_merged_values_| is true when |Merge| has been called to set some
// values. It is used as an optimization in |MergeNonConflictingEntries|.
bool has_merged_values_ = false;
std::unique_ptr<storage::Journal> journal_;
// |in_client_request_| is true when waiting for the callback of the
// ConflictResolver.Resolve call. When this merge is cancelled, we check this
// boolean to know if we should abort immediately (when in a client request,
// as the client may have disconnected) and when we should wait for the
// operation to finish (the other cases, such as committing the merge).
bool in_client_request_ = false;
bool cancelled_ = false;
callback::OperationSerializer operation_serializer_;
fidl::Binding<MergeResultProvider> merge_result_provider_binding_;
// This must be the last member of the class.
fxl::WeakPtrFactory<ConflictResolverClient> weak_factory_;
FXL_DISALLOW_COPY_AND_ASSIGN(ConflictResolverClient);
};
} // namespace ledger
#endif // PERIDOT_BIN_LEDGER_APP_MERGING_CONFLICT_RESOLVER_CLIENT_H_