summaryrefslogtreecommitdiff
path: root/src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp')
-rw-r--r--src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp b/src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp
new file mode 100644
index 0000000..5ebfc0c
--- /dev/null
+++ b/src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp
@@ -0,0 +1,251 @@
+/**
+ * Copyright (C) 2018-2020 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * DLT QNX system functionality source file.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Nguyen Dinh Thi <Thi.NguyenDinh@vn.bosch.com> ADIT 2018
+ * \author Felix Herrmann <fherrmann@de.adit-jv.com> ADIT 2020
+ *
+ * \file: dlt-qnx-slogger2-adapter.cpp
+ * For further information see http://www.genivi.org/.
+ */
+#include <cerrno>
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+#include <pthread.h>
+#include <sys/slog2.h>
+#include <sys/json.h>
+#include <slog2_parse.h>
+
+#include "dlt-qnx-system.h"
+#include "dlt_cpp_extension.hpp"
+
+/* Teach dlt about json_decoder_error_t */
+template<>
+inline int32_t logToDlt(DltContextData &log, const json_decoder_error_t &value)
+{
+ return logToDlt(log, static_cast<int>(value));
+}
+
+extern DltContext dltQnxSystem;
+
+static DltContext dltQnxSlogger2Context;
+
+extern DltQnxSystemThreads g_threads;
+static std::unordered_map<std::string, DltContext*> g_slog2file;
+
+static void dlt_context_map_read(const char *json_filename)
+{
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_VERBOSE,
+ "Loading Slog2Ctxt Map from json file: ", json_filename);
+
+ auto dec = json_decoder_create();
+ if (json_decoder_parse_file(dec, json_filename) != JSON_DECODER_OK) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_ERROR,
+ "Could not load Slog2Ctxt Map from json file: ", json_filename);
+ return;
+ }
+
+ const char *ctxtID, *name, *description;
+
+ /* go to first element in dlt-slog2ctxt.json e.g. "ADIO" */
+ auto ret = json_decoder_push_object(dec, nullptr, false);
+ while (ret == JSON_DECODER_OK) {
+ ctxtID = json_decoder_name(dec);
+
+ /* go into the element e.g. { name: "", description: "" } */
+ ret = json_decoder_push_object(dec, nullptr, false);
+ if (ret != JSON_DECODER_OK) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_WARN, __func__,
+ ": json parser error while descending into context dict. ret=", ret);
+ break;
+ }
+
+ ret = json_decoder_get_string(dec, "name", &name, false);
+ if (ret != JSON_DECODER_OK) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_WARN, __func__,
+ ": json parser error while retrieving 'name' element of ", ctxtID, ". ret=", ret);
+ break;
+ }
+
+ ret = json_decoder_get_string(dec, "description", &description, false);
+ if (ret != JSON_DECODER_OK) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_WARN, __func__,
+ ": json parser error while retrieving 'description' element of ", ctxtID, ". ret=", ret);
+ break;
+ }
+
+ auto ctxt = new DltContext;
+ g_slog2file.emplace(name, ctxt);
+
+ auto search = g_slog2file.find(name);
+ if (search == g_slog2file.end()) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_INFO,
+ "Could not emplace slog2ctxt map key: ", name);
+ } else {
+ dlt_register_context(ctxt, ctxtID, description);
+ }
+
+ ret = json_decoder_pop(dec);
+ }
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_DEBUG,
+ "Added ", g_slog2file.size(), " elements into the mapping table.");
+}
+
+/**
+ * Map the slog2 logfile name to a dlt context
+ * e.g. i2c_service.2948409 -> Context with id "I2CS"
+ */
+static DltContext *dlt_context_from_slog2file(const char *file_name) {
+ auto d = strchr(file_name, '.');
+
+ if (d == nullptr)
+ return &dltQnxSlogger2Context;
+
+ auto name = std::string(file_name).substr(0, d - file_name);
+
+ auto search = g_slog2file.find(name);
+ if (search == g_slog2file.end()) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_VERBOSE,
+ "slog2 filename not found in mapping: ", name.c_str());
+ return &dltQnxSlogger2Context;
+ } else {
+ return search->second;
+ }
+}
+
+/**
+ * Function which is invoked by slog2_parse_all()
+ * See slog2_parse_all api docs on qnx.com for details
+ */
+static int sloggerinfo_callback(slog2_packet_info_t *info, void *payload, void *param)
+{
+ DltQnxSystemConfiguration* conf = (DltQnxSystemConfiguration*) param;
+
+ if (param == NULL)
+ return -1;
+
+ DltLogLevelType loglevel;
+ switch (info->severity)
+ {
+ case SLOG2_SHUTDOWN:
+ case SLOG2_CRITICAL:
+ loglevel = DLT_LOG_FATAL;
+ break;
+ case SLOG2_ERROR:
+ loglevel = DLT_LOG_ERROR;
+ break;
+ case SLOG2_WARNING:
+ loglevel = DLT_LOG_WARN;
+ break;
+ case SLOG2_NOTICE:
+ case SLOG2_INFO:
+ loglevel = DLT_LOG_INFO;
+ break;
+ case SLOG2_DEBUG1:
+ loglevel = DLT_LOG_DEBUG;
+ break;
+ case SLOG2_DEBUG2:
+ loglevel = DLT_LOG_VERBOSE;
+ break;
+ default:
+ loglevel = DLT_LOG_INFO;
+ break;
+ }
+
+ DltContextData log_local; /* Used in DLT_* macros, do not rename */
+ DltContext *ctxt = dlt_context_from_slog2file(info->file_name);
+
+ int ret;
+ ret = dlt_user_log_write_start(ctxt, &log_local, loglevel);
+
+ /* OK means loglevel under threshold */
+ if (ret == DLT_RETURN_OK) {
+ return 0;
+ }
+
+ if (ret != DLT_RETURN_TRUE) {
+ fprintf(stderr, "%s: could not log to DLT status=%d\n", __func__, ret);
+ return -1;
+ }
+
+ if (conf->qnxslogger2.useOriginalTimestamp == 1) {
+ /* convert from ns to .1 ms */
+ log_local.user_timestamp = (uint32_t) (info->timestamp / 100000);
+ log_local.use_timestamp = DLT_USER_TIMESTAMP;
+ } else {
+ DLT_UINT64(info->timestamp);
+ }
+
+ DLT_UINT16(info->sequence_number);
+ DLT_STRING((char *)info->file_name);
+ DLT_STRING((char *)info->buffer_name);
+ DLT_UINT16(info->thread_id);
+ DLT_UINT8(info->severity);
+ DLT_STRING((char *)payload);
+
+ dlt_user_log_write_finish(&log_local);
+
+ return 0;
+}
+
+static void *slogger2_thread(void *v_conf)
+{
+ DltQnxSystemConfiguration *conf = (DltQnxSystemConfiguration *)v_conf;
+
+ if (v_conf == NULL)
+ return reinterpret_cast<void*>(EINVAL);
+
+ slog2_packet_info_t packet_info = SLOG2_PACKET_INFO_INIT;
+
+ DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG,
+ DLT_STRING("dlt-qnx-slogger2-adapter, in thread."));
+ DLT_REGISTER_CONTEXT(dltQnxSlogger2Context, conf->qnxslogger2.contextId,
+ "SLOGGER2 Adapter");
+
+ dlt_context_map_read(CONFIGURATION_FILES_DIR "/dlt-slog2ctxt.json");
+
+ /**
+ * Thread will block inside this function to get new log because
+ * flag = SLOG2_PARSE_FLAGS_DYNAMIC
+ */
+ int ret = slog2_parse_all(
+ SLOG2_PARSE_FLAGS_DYNAMIC, /* live streaming of all buffers merged */
+ NULL, NULL, &packet_info, sloggerinfo_callback, (void*) conf);
+ if (ret == -1) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_ERROR,
+ "slog2_parse_all() returned error=", ret);
+ ret = EBADMSG;
+ }
+
+ DLT_LOG_CXX(dltQnxSystem, DLT_LOG_DEBUG, __func__, ": Exited main loop.");
+
+ DLT_UNREGISTER_CONTEXT(dltQnxSlogger2Context);
+
+ /* Send a signal to main thread to wake up sigwait */
+ pthread_kill(g_threads.mainThread, SIGTERM);
+ return reinterpret_cast<void*>(ret);
+}
+
+void start_qnx_slogger2(DltQnxSystemConfiguration *conf)
+{
+ static pthread_attr_t t_attr;
+ static pthread_t pt;
+
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_DEBUG,
+ "dlt-qnx-slogger2-adapter, start syslog");
+ pthread_create(&pt, &t_attr, slogger2_thread, conf);
+ g_threads.threads[g_threads.count++] = pt;
+}