From 736124435900826d5030387fa0acace6b199b833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beat=20K=C3=BCng?= Date: Thu, 27 Apr 2017 17:05:37 +0200 Subject: [PATCH] logger: convert to use ModuleBase --- src/modules/logger/logger.cpp | 226 ++++++++++++++-------------------- src/modules/logger/logger.h | 32 +++-- 2 files changed, 111 insertions(+), 147 deletions(-) diff --git a/src/modules/logger/logger.cpp b/src/modules/logger/logger.cpp index 6c6c1a9477..e397ccfabc 100644 --- a/src/modules/logger/logger.cpp +++ b/src/modules/logger/logger.cpp @@ -89,9 +89,6 @@ using namespace px4::logger; -static Logger *logger_ptr = nullptr; -static int logger_task = -1; - /* This is used to schedule work for the logger (periodic scan for updated topics) */ static void timer_callback(void *arg) { @@ -110,75 +107,7 @@ int logger_main(int argc, char *argv[]) return 1; } - if (argc < 2) { - PX4_INFO("usage: logger {start|stop|status}"); - return 1; - } - - //Check if thread exited, but the object has not been destroyed yet (happens in case of an error) - if (logger_task == -1 && logger_ptr) { - delete logger_ptr; - logger_ptr = nullptr; - } - - if (!strcmp(argv[1], "start")) { - - if (logger_ptr != nullptr) { - PX4_INFO("already running"); - return 1; - } - - if (OK != Logger::start((char *const *)argv)) { - PX4_WARN("start failed"); - return 1; - } - - return 0; - } - - if (!strcmp(argv[1], "on")) { - if (logger_ptr != nullptr) { - logger_ptr->set_arm_override(true); - return 0; - } - - return 1; - } - - if (!strcmp(argv[1], "off")) { - if (logger_ptr != nullptr) { - logger_ptr->set_arm_override(false); - return 0; - } - - return 1; - } - - if (!strcmp(argv[1], "stop")) { - if (logger_ptr == nullptr) { - PX4_INFO("not running"); - return 1; - } - - logger_ptr->print_statistics(); - delete logger_ptr; - logger_ptr = nullptr; - return 0; - } - - if (!strcmp(argv[1], "status")) { - if (logger_ptr) { - logger_ptr->status(); - return 0; - - } else { - PX4_INFO("not running"); - return 1; - } - } - - Logger::usage("unrecognized command"); - return 1; + return Logger::main(argc, argv); } namespace px4 @@ -186,46 +115,92 @@ namespace px4 namespace logger { -void Logger::usage(const char *reason) +int Logger::custom_command(int argc, char *argv[]) +{ + if (!is_running()) { + print_usage("logger not running"); + return 1; + } + + if (!strcmp(argv[0], "on")) { + get_instance()->set_arm_override(true); + return 0; + } + + if (!strcmp(argv[0], "off")) { + get_instance()->set_arm_override(false); + return 0; + } + + return print_usage("unknown command"); +} + +int Logger::print_usage(const char *reason) { if (reason) { PX4_WARN("%s\n", reason); } - PX4_INFO("usage: logger {start|stop|on|off|status} [-r ] [-b ]\n" - " [-p ] -e -a -t -x -m -q \n" - "\t-r\tLog rate in Hz, 0 means unlimited rate\n" - "\t-p\tPoll on a topic instead of running with fixed rate (Log rate and topic interval are ignored if this is set)\n" - "\t-b\tLog buffer size in KiB, default is 12\n" - "\t-e\tEnable logging right after start until disarm (otherwise only when armed)\n" - "\t-f\tLog until shutdown (implies -e)\n" - "\t-t\tUse date/time for naming log directories and files\n" - "\t-m\tMode: one of 'file', 'mavlink', 'all' (default=all)\n" - "\t-q\tuORB queue size for mavlink mode"); + PRINT_MODULE_DESCRIPTION( + R"DESCR_STR( +System logger which logs a (configurable) set of uORB topics and system printf messages +(warnings and errors) to ULog files. These can be used for system and flight performance evaluation, +tuning, replay and crash analysis. + +It supports 2 backends: +- Files: write ULog files to the file system (SD card) +- MAVLink: stream ULog data via MAVLink to a client (the client must support this) +Both backends can be enabled and used at the same time. + +The implementation uses two threads: +- The main thread, running at a fixed rate (or polling on a topic if started with -p) and checking for +data updates +- The writer thread, writing data to the file +In between there is a write buffer with configurable size. It should be large to avoid dropouts. + +Typical usage to start logging immediately: +$ logger start -e -t + +Or if already running: +$ logger on +)DESCR_STR"); + + PRINT_MODULE_USAGE_NAME("logger", "system"); + PRINT_MODULE_USAGE_COMMAND("start"); + PRINT_MODULE_USAGE_PARAM_STRING('m', "all", "file|mavlink|all", "Backend mode", true); + PRINT_MODULE_USAGE_PARAM_FLAG('e', "Enable logging right after start until disarm (otherwise only when armed)", true); + PRINT_MODULE_USAGE_PARAM_FLAG('f', "Log until shutdown (implies -e)", true); + PRINT_MODULE_USAGE_PARAM_FLAG('t', "Use date/time for naming log directories and files", true); + PRINT_MODULE_USAGE_PARAM_INT('r', 280, 0, 8000, "Log rate in Hz, 0 means unlimited rate", true); + PRINT_MODULE_USAGE_PARAM_INT('b', 12, 4, 10000, "Log buffer size in KiB", true); + PRINT_MODULE_USAGE_PARAM_INT('q', 14, 1, 100, "uORB queue size for mavlink mode", true); + PRINT_MODULE_USAGE_PARAM_STRING('p', nullptr, "", + "Poll on a topic instead of running with fixed rate (Log rate and topic intervals are ignored if this is set)", true); + PRINT_MODULE_USAGE_COMMAND_DESCR("on", "start logging now, override arming (logger must be running)"); + PRINT_MODULE_USAGE_COMMAND_DESCR("off", "stop logging now, override arming (logger must be running)"); + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); + + return 0; } -int Logger::start(char *const *argv) +int Logger::task_spawn(int argc, char *argv[]) { - ASSERT(logger_task == -1); + _task_id = px4_task_spawn_cmd("logger", + SCHED_DEFAULT, + SCHED_PRIORITY_MAX - 10, + 3600, + (px4_main_t)&run_trampoline, + (char *const *)argv); - /* start the task */ - logger_task = px4_task_spawn_cmd("logger", - SCHED_DEFAULT, - SCHED_PRIORITY_MAX - 10, - 3600, - (px4_main_t)&Logger::run_trampoline, - (char *const *)argv); - - if (logger_task < 0) { - logger_task = -1; - PX4_WARN("task start failed"); + if (_task_id < 0) { + _task_id = -1; return -errno; } - return OK; + return 0; } -void Logger::status() +int Logger::print_status() { PX4_INFO("Running in mode: %s", configured_backend_mode()); @@ -237,6 +212,8 @@ void Logger::status() if (_writer.is_started(LogWriter::BackendMavlink)) { PX4_INFO("Mavlink Logging Running"); } + + return 0; } void Logger::print_statistics() @@ -259,7 +236,7 @@ void Logger::print_statistics() _max_dropout_duration = 0.f; } -void Logger::run_trampoline(int argc, char *argv[]) +Logger *Logger::instanciate(int argc, char *argv[]) { uint32_t log_interval = 3500; int log_buffer_size = 12 * 1024; @@ -355,12 +332,11 @@ void Logger::run_trampoline(int argc, char *argv[]) } if (error_flag) { - logger_task = -1; - return; + return nullptr; } - logger_ptr = new Logger(backend, log_buffer_size, log_interval, poll_topic, log_on_start, - log_until_shutdown, log_name_timestamp, queue_size); + Logger *logger = new Logger(backend, log_buffer_size, log_interval, poll_topic, log_on_start, + log_until_shutdown, log_name_timestamp, queue_size); #if defined(DBGPRINT) && defined(__PX4_NUTTX) struct mallinfo alloc_info = mallinfo(); @@ -368,7 +344,7 @@ void Logger::run_trampoline(int argc, char *argv[]) PX4_INFO("remaining free heap: %d bytes", alloc_info.fordblks); #endif /* DBGPRINT */ - if (logger_ptr == nullptr) { + if (logger == nullptr) { PX4_ERR("alloc failed"); } else { @@ -377,15 +353,14 @@ void Logger::run_trampoline(int argc, char *argv[]) const char *logfile = getenv(px4::replay::ENV_FILENAME); if (logfile) { - logger_ptr->setReplayFile(logfile); + logger->setReplayFile(logfile); } #endif /* __PX4_NUTTX */ - logger_ptr->run(); } - logger_task = -1; + return logger; } @@ -420,26 +395,6 @@ Logger::Logger(LogWriter::Backend backend, size_t buffer_size, uint32_t log_inte Logger::~Logger() { - if (logger_task != -1) { - /* task wakes up every 100ms or so at the longest */ - _task_should_exit = true; - - /* wait for a second for the task to quit at our request */ - unsigned int i = 0; - - do { - /* wait 20ms */ - usleep(20000); - - /* if we have given up, kill it */ - if (++i > 200) { - px4_task_delete(logger_task); - logger_task = -1; - break; - } - } while (logger_task != -1); - } - if (_replay_file_name) { free(_replay_file_name); } @@ -449,13 +404,14 @@ Logger::~Logger() } } -bool Logger::request_stop() +bool Logger::request_stop_static() { - if (logger_ptr) { - logger_ptr->_task_should_exit = true; + if (is_running()) { + get_instance()->request_stop(); + return false; } - return logger_task == -1; + return true; } int Logger::add_topic(const orb_metadata *topic) @@ -819,14 +775,12 @@ void Logger::run() return; } - _task_should_exit = false; - #ifdef DBGPRINT hrt_abstime timer_start = 0; uint32_t total_bytes = 0; #endif /* DBGPRINT */ - px4_register_shutdown_hook(&Logger::request_stop); + px4_register_shutdown_hook(&Logger::request_stop_static); // we start logging immediately // the case where we wait with logging until vehicle is armed is handled below @@ -859,7 +813,7 @@ void Logger::run() hrt_abstime next_subscribe_check = 0; int next_subscribe_topic_index = -1; // this is used to distribute the checks over time - while (!_task_should_exit) { + while (!should_exit()) { // Start/stop logging when system arm/disarm bool vehicle_status_updated; @@ -1134,7 +1088,7 @@ void Logger::run() orb_unsubscribe(vehicle_command_sub); } - px4_unregister_shutdown_hook(&Logger::request_stop); + px4_unregister_shutdown_hook(&Logger::request_stop_static); } bool Logger::write_message(void *ptr, size_t size) diff --git a/src/modules/logger/logger.h b/src/modules/logger/logger.h index 1282e50b73..33db7fdb01 100644 --- a/src/modules/logger/logger.h +++ b/src/modules/logger/logger.h @@ -41,6 +41,7 @@ #include #include #include +#include extern "C" __EXPORT int logger_main(int argc, char *argv[]); @@ -87,7 +88,7 @@ struct LoggerSubscription { } }; -class Logger +class Logger : public ModuleBase { public: Logger(LogWriter::Backend backend, size_t buffer_size, uint32_t log_interval, const char *poll_topic_name, @@ -95,6 +96,24 @@ public: ~Logger(); + /** @see ModuleBase */ + static int task_spawn(int argc, char *argv[]); + + /** @see ModuleBase */ + static Logger *instanciate(int argc, char *argv[]); + + /** @see ModuleBase */ + static int custom_command(int argc, char *argv[]); + + /** @see ModuleBase */ + static int print_usage(const char *reason = nullptr); + + /** @see ModuleBase::run() */ + void run() override; + + /** @see ModuleBase::print_status() */ + int print_status() override; + /** * Tell the logger that we're in replay mode. This must be called * before starting the logger. @@ -116,25 +135,17 @@ public: */ int add_topic(const orb_metadata *topic); - static int start(char *const *argv); - /** * request the logger thread to stop (this method does not block). * @return true if the logger is stopped, false if (still) running */ - static bool request_stop(); + static bool request_stop_static(); - static void usage(const char *reason); - - void status(); void print_statistics(); void set_arm_override(bool override) { _arm_override = override; } private: - static void run_trampoline(int argc, char *argv[]); - - void run(); /** * Write an ADD_LOGGED_MSG to the log for a all current subscriptions and instances @@ -284,7 +295,6 @@ private: char _log_dir[LOG_DIR_LEN]; int _sess_dir_index = 1; ///< search starting index for 'sess' directory name char _log_file_name[32]; - bool _task_should_exit = true; bool _has_log_dir = false; bool _was_armed = false; bool _arm_override;