| // 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_LIB_LEDGER_CLIENT_LEDGER_CLIENT_H_ |
| #define PERIDOT_LIB_LEDGER_CLIENT_LEDGER_CLIENT_H_ |
| |
| #include <functional> |
| #include <memory> |
| #include <vector> |
| |
| #include <fuchsia/ledger/cpp/fidl.h> |
| #include <fuchsia/ledger/internal/cpp/fidl.h> |
| #include <lib/async/cpp/operation.h> |
| #include <lib/fidl/cpp/binding_set.h> |
| #include <lib/fidl/cpp/interface_ptr.h> |
| #include <lib/fxl/logging.h> |
| #include <lib/fxl/macros.h> |
| |
| #include "peridot/lib/ledger_client/types.h" |
| |
| namespace modular { |
| |
| class PageClient; |
| |
| // The primary purpose of the ledger client is to act as conflict resolver |
| // factory which is able to dispatch conflicts to the page clients based on |
| // their page and key prefix. |
| class LedgerClient : fuchsia::ledger::ConflictResolverFactory { |
| public: |
| LedgerClient(fuchsia::ledger::internal::LedgerRepository* ledger_repository, |
| const std::string& name, std::function<void()> error); |
| LedgerClient(fuchsia::ledger::LedgerPtr ledger); |
| ~LedgerClient() override; |
| |
| fuchsia::ledger::Ledger* ledger() const { return ledger_.get(); } |
| |
| // A callback that is invoked every time one conflict resolution completes. |
| // Used only for testing so far. |
| void add_watcher(std::function<void()> watcher) { |
| watchers_.emplace_back(std::move(watcher)); |
| } |
| |
| private: |
| friend class PageClient; |
| class ConflictResolverImpl; |
| struct PageEntry; |
| |
| // Used by PageClient to access a new page on creation. Two page clients of |
| // the same page share the same ledger::Page connection. |
| fuchsia::ledger::Page* GetPage(PageClient* page_client, |
| const std::string& context, |
| const fuchsia::ledger::PageId& page_id); |
| |
| // PageClient deregisters itself on destrution. |
| void DropPageClient(PageClient* page_client); |
| |
| // |ConflictResolverFactory| |
| void GetPolicy(LedgerPageId page_id, GetPolicyCallback callback) override; |
| |
| // |ConflictResolverFactory| |
| void NewConflictResolver( |
| LedgerPageId page_id, |
| fidl::InterfaceRequest<fuchsia::ledger::ConflictResolver> request) |
| override; |
| |
| void ClearConflictResolver(const LedgerPageId& page_id); |
| |
| // The ledger this is a client of. |
| fuchsia::ledger::LedgerPtr ledger_; |
| |
| fidl::BindingSet<fuchsia::ledger::ConflictResolverFactory> bindings_; |
| std::vector<std::unique_ptr<ConflictResolverImpl>> resolvers_; |
| |
| // ledger::Page connections are owned by LedgerClient, and only handed to |
| // PageClient as naked pointers. This allows multiple clients of the same page |
| // to share a page connection. |
| std::vector<std::unique_ptr<PageEntry>> pages_; |
| |
| // Notified whenever a conflict resolution cycle finishes. |
| std::vector<std::function<void()>> watchers_; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(LedgerClient); |
| }; |
| |
| // A conflict resolver for one page that delegates the diff for a key to the |
| // appropriate page client that handles that key. |
| class LedgerClient::ConflictResolverImpl : fuchsia::ledger::ConflictResolver { |
| public: |
| ConflictResolverImpl(LedgerClient* ledger_client, |
| const LedgerPageId& page_id); |
| ~ConflictResolverImpl() override; |
| |
| void Connect( |
| fidl::InterfaceRequest<fuchsia::ledger::ConflictResolver> request); |
| |
| const LedgerPageId& page_id() const { return page_id_; } |
| |
| private: |
| // |ConflictResolver| |
| void Resolve( |
| fidl::InterfaceHandle<fuchsia::ledger::PageSnapshot> left_version, |
| fidl::InterfaceHandle<fuchsia::ledger::PageSnapshot> right_version, |
| fidl::InterfaceHandle<fuchsia::ledger::PageSnapshot> common_version, |
| fidl::InterfaceHandle<fuchsia::ledger::MergeResultProvider> |
| result_provider) override; |
| |
| void GetPageClients(std::vector<PageClient*>* page_clients); |
| |
| void NotifyWatchers() const; |
| |
| LedgerClient* const ledger_client_; |
| LedgerPageId page_id_; |
| |
| fidl::BindingSet<fuchsia::ledger::ConflictResolver> bindings_; |
| |
| OperationQueue operation_queue_; |
| class ResolveCall; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(ConflictResolverImpl); |
| }; |
| |
| } // namespace modular |
| |
| #endif // PERIDOT_LIB_LEDGER_CLIENT_LEDGER_CLIENT_H_ |