| // 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 <fcntl.h> |
| #include <unistd.h> |
| #include <memory> |
| #include <utility> |
| |
| #include <fuchsia/ledger/internal/cpp/fidl.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/backoff/exponential_backoff.h> |
| #include <lib/component/cpp/startup_context.h> |
| #include <lib/fidl/cpp/binding_set.h> |
| #include <lib/fit/function.h> |
| #include <lib/fxl/command_line.h> |
| #include <lib/fxl/files/unique_fd.h> |
| #include <lib/fxl/log_settings_command_line.h> |
| #include <lib/fxl/logging.h> |
| #include <lib/fxl/macros.h> |
| #include <trace-provider/provider.h> |
| #include <zircon/device/vfs.h> |
| |
| #include "peridot/bin/ledger/app/constants.h" |
| #include "peridot/bin/ledger/app/ledger_repository_factory_impl.h" |
| #include "peridot/bin/ledger/cobalt/cobalt.h" |
| #include "peridot/bin/ledger/environment/environment.h" |
| #include "peridot/bin/ledger/fidl/error_notifier.h" |
| #include "peridot/bin/ledger/fidl/include/types.h" |
| #include "peridot/bin/ledger/p2p_sync/impl/user_communicator_factory_impl.h" |
| |
| namespace ledger { |
| namespace { |
| |
| constexpr fxl::StringView kNoStatisticsReportingFlag = "disable_reporting"; |
| constexpr fxl::StringView kFirebaseApiKeyFlag = "firebase_api_key"; |
| |
| struct AppParams { |
| bool disable_statistics = false; |
| std::string firebase_api_key = ""; |
| }; |
| |
| fit::deferred_action<fit::closure> SetupCobalt( |
| bool disable_statistics, async_dispatcher_t* dispatcher, |
| component::StartupContext* startup_context) { |
| if (disable_statistics) { |
| return fit::defer<fit::closure>([] {}); |
| } |
| return InitializeCobalt(dispatcher, startup_context); |
| }; |
| |
| // App is the main entry point of the Ledger application. |
| // |
| // It is responsible for setting up the LedgerRepositoryFactory, which connects |
| // clients to individual Ledger instances. It should not however hold long-lived |
| // objects shared between Ledger instances, as we need to be able to put them in |
| // separate processes when the app becomes multi-instance. |
| class App : public ledger_internal::LedgerController { |
| public: |
| explicit App(AppParams app_params) |
| : app_params_(app_params), |
| loop_(&kAsyncLoopConfigAttachToThread), |
| io_loop_(&kAsyncLoopConfigNoAttachToThread), |
| trace_provider_(loop_.dispatcher()), |
| startup_context_(component::StartupContext::CreateFromStartupInfo()), |
| cobalt_cleaner_(SetupCobalt(app_params_.disable_statistics, |
| loop_.dispatcher(), |
| startup_context_.get())) { |
| FXL_DCHECK(startup_context_); |
| |
| ReportEvent(CobaltEvent::LEDGER_STARTED); |
| } |
| ~App() override {} |
| |
| bool Start() { |
| io_loop_.StartThread("io thread"); |
| |
| EnvironmentBuilder builder; |
| |
| if (!app_params_.firebase_api_key.empty()) { |
| builder.SetFirebaseApiKey(app_params_.firebase_api_key); |
| } |
| |
| environment_ = std::make_unique<Environment>( |
| builder.SetDisableStatistics(app_params_.disable_statistics) |
| .SetAsync(loop_.dispatcher()) |
| .SetIOAsync(io_loop_.dispatcher()) |
| .SetStartupContext(startup_context_.get()) |
| .Build()); |
| auto user_communicator_factory = |
| std::make_unique<p2p_sync::UserCommunicatorFactoryImpl>( |
| environment_.get()); |
| |
| factory_impl_ = std::make_unique<LedgerRepositoryFactoryImpl>( |
| environment_.get(), std::move(user_communicator_factory), |
| *startup_context_->outgoing().object_dir()); |
| |
| startup_context_->outgoing() |
| .AddPublicService<ledger_internal::LedgerRepositoryFactory>( |
| [this]( |
| fidl::InterfaceRequest<ledger_internal::LedgerRepositoryFactory> |
| request) { |
| factory_bindings_.emplace(factory_impl_.get(), |
| std::move(request)); |
| }); |
| startup_context_->outgoing().AddPublicService<LedgerController>( |
| [this](fidl::InterfaceRequest<LedgerController> request) { |
| controller_bindings_.AddBinding(this, std::move(request)); |
| }); |
| |
| startup_context_->outgoing().object_dir()->set_prop( |
| "statistic_gathering", app_params_.disable_statistics ? "off" : "on"); |
| |
| startup_context_->outgoing().object_dir()->set_children_callback( |
| {kRepositoriesInspectPathComponent}, |
| [this](component::Object::ObjectVector* out) { |
| factory_impl_->GetChildren(out); |
| }); |
| |
| loop_.Run(); |
| |
| startup_context_->outgoing().object_dir()->set_children_callback( |
| {kRepositoriesInspectPathComponent}, nullptr); |
| |
| return true; |
| } |
| |
| private: |
| // LedgerController: |
| void Terminate() override { loop_.Quit(); } |
| |
| const AppParams app_params_; |
| async::Loop loop_; |
| async::Loop io_loop_; |
| trace::TraceProvider trace_provider_; |
| std::unique_ptr<component::StartupContext> startup_context_; |
| fit::deferred_action<fit::closure> cobalt_cleaner_; |
| std::unique_ptr<Environment> environment_; |
| std::unique_ptr<LedgerRepositoryFactoryImpl> factory_impl_; |
| callback::AutoCleanableSet<ErrorNotifierBinding< |
| fuchsia::ledger::internal::LedgerRepositoryFactoryErrorNotifierDelegate>> |
| factory_bindings_; |
| fidl::BindingSet<LedgerController> controller_bindings_; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(App); |
| }; |
| |
| int Main(int argc, const char** argv) { |
| const auto command_line = fxl::CommandLineFromArgcArgv(argc, argv); |
| fxl::SetLogSettingsFromCommandLine(command_line); |
| |
| AppParams app_params; |
| app_params.disable_statistics = |
| command_line.HasOption(kNoStatisticsReportingFlag); |
| if (command_line.HasOption(kFirebaseApiKeyFlag)) { |
| if (!command_line.GetOptionValue(kFirebaseApiKeyFlag, |
| &app_params.firebase_api_key)) { |
| FXL_LOG(ERROR) << "Unable to retrieve the firebase api key."; |
| return 1; |
| } |
| } |
| |
| App app(app_params); |
| if (!app.Start()) { |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| } // namespace |
| } // namespace ledger |
| |
| int main(int argc, const char** argv) { return ledger::Main(argc, argv); } |