blob: 864ae370c89d607a34892caad0f448ba2cf97d1b [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 <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); }