.. _program_listing_file_falcon_main.cpp: Program Listing for File main.cpp ================================= |exhale_lsh| :ref:`Return to documentation for file ` (``falcon/main.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // --------------------------------------------------------------------- // This file is part of falcon-core. // // Copyright (C) 2015, 2016, 2017 Neuro-Electronics Research Flanders // // Falcon-server is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Falcon-server is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with falcon-core. If not, see . // --------------------------------------------------------------------- #include #include #include #include #include #include #include "cmdline/cmdline.h" #include "logging/log.hpp" #include "logging/customsink.hpp" #include "commandsource.hpp" #include "commandhandler.hpp" #include "graphmanager.hpp" #include "buildconstant.hpp" #include "configuration.hpp" #include "context.hpp" #include "options/units.hpp" #include "utilities/time.hpp" using namespace std; int main(int argc, char** argv) { // create a parser cmdline::parser parser; // add specified type of variable. // 1st argument is long name // 2nd argument is short name (no short name if '\0' specified) // 3rd argument is description // 4th argument is mandatory (optional. default is false) // 5th argument is default value (optional. it used when mandatory is false) parser.add("config", 'c', "configuration file", false, "$HOME/.config/falcon/config.yaml"); parser.add("autostart", 'a', "auto start processing (needs graph)"); parser.add("debug", 'd', "show debug messages"); parser.add("noscreenlog", '\0', "disable logging to screen"); parser.add("nocloudlog", '\0', "disable logging to cloud"); parser.add("test", 't', "turn testing on by default"); parser.add("version", 'v', "Show the falcon version number and exit."); parser.footer("[graph file] ..."); // Run parser // It returns only if command line arguments are valid. // If arguments are invalid, a parser output error msgs then exit program. // If help flag ('--help' or '-?') is specified, a parser output usage message then exit program. parser.parse_check(argc, argv); if (parser.exist("version")) { std::cout << "Falcon " << GIT_REVISION << std::endl; std::cout << "Last build: " << BUILD_TIMESTAMP << std::endl; std::cout << "Configuration: " << BUILD_TYPE << std::endl; std::cout << "Extensions: " << std::endl; std::vector extensions = split(EXTENSIONS_BUILD, ';'); for(auto it:extensions){ std::cout << it << std::endl; } return EXIT_SUCCESS; } // create default configuration FalconConfiguration config; // add custom units units::addUserDefinedUnit("sample", units::precise::sample_units); units::addUserDefinedUnit("spike", units::precise::spike_units); // load configuration file try { config.load(parser.get("config")); } catch (std::runtime_error &e) { std::cout << e.what() << std::endl; std::cout << "Falcon terminated." << std::endl; return EXIT_FAILURE; } // apply command line arguments if (parser.exist("autostart")) { config.graph_autostart = true; } if (parser.exist("debug")) { config.debug_enabled = true; } if (parser.exist("noscreenlog")) { config.logging_screen_enabled = false; } if (parser.exist("nocloudlog")) { config.logging_cloud_enabled = false; } if (parser.exist("test")) { config.testing_enabled = true; } // add default URIs config.server_side_storage_custom["resources"] = config.server_side_storage_resources(); config.server_side_storage_custom["graphs"] = config.server_side_storage_resources() + "/graphs"; config.server_side_storage_custom["filters"] = config.server_side_storage_resources() + "/filters"; config.server_side_storage_custom["runroot"] = config.server_side_storage_environment(); GlobalContext context(config.testing_enabled(), config.server_side_storage_custom()); // set up loggers // file logger char *home = getenv("HOME"); std::regex re("(\\$HOME|~)"); std::string logpath = std::regex_replace(config.logging_path(), re, home); auto worker = g3::LogWorker::createLogWorker(); auto defaultHandler = worker->addDefaultLogger("falcon", logpath); // initialize logging before creating additional loggers g3::initializeLogging(worker.get()); g3::only_change_at_initialization::addLogLevel(STATE); g3::only_change_at_initialization::addLogLevel(UPDATE); g3::only_change_at_initialization::addLogLevel(ERROR); // enable DEBUG logging if(config.debug_enabled()){ g3::log_levels::enable(DEBUG); }else{ g3::log_levels::disable(DEBUG); } // screen logger if (config.logging_screen_enabled()) { worker->addSink(std::make_unique(), &ScreenSink::ReceiveLogMessage); LOG(INFO) << "Enabled logging to screen."; } // cloud logger if (config.logging_cloud_enabled()) { worker->addSink( std::make_unique(context.zmq(), config.logging_cloud_port()), &ZMQSink::ReceiveLogMessage); // wait so that any existing subscriber has a change to connect before we send out first messages std::this_thread::sleep_for(std::chrono::milliseconds(200)); LOG(INFO) << "Enabled logging to cloud on port " << config.logging_cloud_port(); } LOG(INFO) << "Logging initialized. Log file saved to " << logpath; // Check clock used for internal timing LOG_IF(WARNING, not Clock::is_steady) << "The clock used for timing is not steady."; LOG(INFO) << "Resolution of clock used for timing is " << 10e6 * static_cast(Clock::period::num) / Clock::period::den << " microseconds."; // create and start GraphManager in separate thread graph::GraphManager gm(context); gm.start(); // create command sources // keyboard commands commands::KeyboardCommands kb; // cloud commands commands::ZMQCommands zc(context.zmq(), config.network_port()); // command line commands commands::CommandLineCommands cl; std::string graph_file = config.graph_file(); if (parser.rest().size() > 0) { graph_file = parser.rest().back(); } std::deque command; if (graph_file.size() > 0) { command.push_back("graph"); command.push_back("build"); command.push_back(graph_file); cl.AddCommand(command); command.clear(); if (config.graph_autostart()) { command.push_back("graph"); command.push_back("start"); cl.AddCommand(command); command.clear(); } } // set up Command handler commands::CommandHandler commandhandler(context); // add command sources to handler commandhandler.addSource(cl); commandhandler.addSource(kb); commandhandler.addSource(zc); LOG(INFO) << "Enabled keyboard commands."; LOG(INFO) << "Enabled cloud commands on port " << config.network_port() ; LOG(INFO) << "Falcon started successfully."; // start handling commands commandhandler.start(); LOG(INFO) << "Falcon shutting down normally."; g3::internal::shutDownLogging(); return EXIT_SUCCESS; }