| // Copyright 2019 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 <fuchsia/sysinfo/c/fidl.h> |
| #include <grpc++/grpc++.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/fdio/fdio.h> |
| #include <lib/zx/channel.h> |
| #include <lib/zx/time.h> |
| #include <zircon/status.h> |
| |
| #include <chrono> |
| #include <iostream> |
| #include <string> |
| #include <thread> |
| |
| #include "dockyard_proxy.h" |
| #include "dockyard_proxy_grpc.h" |
| #include "dockyard_proxy_local.h" |
| #include "harvester.h" |
| #include "src/lib/fxl/command_line.h" |
| #include "src/lib/fxl/log_settings_command_line.h" |
| #include "src/lib/fxl/logging.h" |
| #include "src/lib/fxl/strings/string_number_conversions.h" |
| |
| namespace { |
| |
| zx_status_t get_root_resource(zx_handle_t* root_resource) { |
| const char* sysinfo = "/dev/misc/sysinfo"; |
| int fd = open(sysinfo, O_RDWR); |
| if (fd < 0) { |
| FXL_LOG(ERROR) << "Cannot open sysinfo: " << strerror(errno); |
| return ZX_ERR_NOT_FOUND; |
| } |
| |
| zx::channel channel; |
| zx_status_t status = |
| fdio_get_service_handle(fd, channel.reset_and_get_address()); |
| if (status != ZX_OK) { |
| FXL_LOG(ERROR) << "Cannot obtain sysinfo channel: " |
| << zx_status_get_string(status); |
| return status; |
| } |
| |
| zx_status_t fidl_status = fuchsia_sysinfo_DeviceGetRootResource( |
| channel.get(), &status, root_resource); |
| if (fidl_status != ZX_OK) { |
| FXL_LOG(ERROR) << "Cannot obtain root resource: " |
| << zx_status_get_string(fidl_status); |
| return fidl_status; |
| } else if (status != ZX_OK) { |
| FXL_LOG(ERROR) << "Cannot obtain root resource: " |
| << zx_status_get_string(status); |
| return status; |
| } |
| return ZX_OK; |
| } |
| |
| } // namespace |
| |
| int main(int argc, char** argv) { |
| constexpr int EXIT_CODE_OK = 0; |
| // A broad 'something went wrong' error. |
| constexpr int EXIT_CODE_GENERAL_ERROR = 1; |
| |
| // The wip number is incremented arbitrarily. |
| // TODO(smbug.com/44) replace wip number with real version number. |
| constexpr char VERSION_OUTPUT[] = "System Monitor Harvester - wip 11"; |
| |
| // Command line options. |
| constexpr char COMMAND_INSPECT[] = "inspect"; |
| constexpr char COMMAND_UPDATE_PERIOD[] = "msec-update-period"; |
| constexpr char COMMAND_LOCAL[] = "local"; |
| constexpr char COMMAND_VERSION[] = "version"; |
| |
| bool use_grpc = true; |
| int cycle_msec_period = 100; |
| |
| // Parse command line. |
| FXL_LOG(INFO) << VERSION_OUTPUT; |
| auto command_line = fxl::CommandLineFromArgcArgv(argc, argv); |
| if (!fxl::SetLogSettingsFromCommandLine(command_line)) { |
| exit(EXIT_CODE_GENERAL_ERROR); |
| } |
| if (command_line.HasOption(COMMAND_VERSION)) { |
| std::cout << VERSION_OUTPUT << std::endl; |
| exit(EXIT_CODE_OK); |
| } |
| if (command_line.HasOption(COMMAND_LOCAL)) { |
| FXL_LOG(INFO) << "Option: local only, not using transport to Dockyard."; |
| use_grpc = false; |
| } |
| if (command_line.HasOption(COMMAND_INSPECT)) { |
| FXL_LOG(INFO) << "Enabled component framework inspection (wip)"; |
| // TODO(smbug.com/43): actually do component framework inspection. |
| } |
| if (command_line.HasOption(COMMAND_UPDATE_PERIOD)) { |
| std::string update_period; |
| command_line.GetOptionValue(COMMAND_UPDATE_PERIOD, &update_period); |
| if (!fxl::StringToNumberWithError(update_period, &cycle_msec_period)) { |
| std::cerr << "Error: Unable to parse `--" << COMMAND_UPDATE_PERIOD |
| << "` value of \"" << update_period << "\"" << std::endl; |
| exit(EXIT_CODE_GENERAL_ERROR); |
| } |
| } |
| FXL_LOG(INFO) << "Gathering data every " << cycle_msec_period << " msec."; |
| |
| // Set up. |
| std::unique_ptr<harvester::DockyardProxy> dockyard_proxy; |
| if (use_grpc) { |
| const auto& positional_args = command_line.positional_args(); |
| if (positional_args.size() < 1) { |
| // TODO(smbug.com/30): Adhere to CLI tool requirements for --help. |
| std::cerr << "Please specify an IP:Port, such as localhost:50051" |
| << std::endl; |
| exit(EXIT_CODE_GENERAL_ERROR); |
| } |
| |
| // TODO(smbug.com/32): This channel isn't authenticated |
| // (InsecureChannelCredentials()). |
| dockyard_proxy = |
| std::make_unique<harvester::DockyardProxyGrpc>(grpc::CreateChannel( |
| positional_args[0], grpc::InsecureChannelCredentials())); |
| |
| if (!dockyard_proxy || |
| dockyard_proxy->Init() != harvester::DockyardProxyStatus::OK) { |
| exit(EXIT_CODE_GENERAL_ERROR); |
| } |
| } else { |
| dockyard_proxy = std::make_unique<harvester::DockyardProxyLocal>(); |
| } |
| |
| zx_handle_t root_resource; |
| zx_status_t ret = get_root_resource(&root_resource); |
| if (ret != ZX_OK) { |
| exit(EXIT_CODE_GENERAL_ERROR); |
| } |
| |
| async::Loop loop(&kAsyncLoopConfigAttachToThread); |
| |
| harvester::Harvester harvester(zx::msec(cycle_msec_period), root_resource, |
| loop.dispatcher(), std::move(dockyard_proxy)); |
| harvester.GatherData(); |
| loop.Run(); |
| |
| FXL_LOG(INFO) << "System Monitor Harvester - exiting"; |
| return 0; |
| } |