From patchwork Thu Aug 16 15:07:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10759021 Return-Path: Received: from mail-wr1-f66.google.com ([209.85.221.66]:38585 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726328AbeHPSGt (ORCPT ); Thu, 16 Aug 2018 14:06:49 -0400 Received: by mail-wr1-f66.google.com with SMTP id w11-v6so1896322wrc.5 for ; Thu, 16 Aug 2018 08:07:45 -0700 (PDT) From: "Yordan Karadzhov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, "Yordan Karadzhov (VMware)" Subject: [PATCH v3 1/3] kernel-shark-qt: Add Json-C as a third party dependency. Date: Thu, 16 Aug 2018 18:07:27 +0300 Message-Id: <20180816150729.4680-1-y.karadz@gmail.com> Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 4219 This patch prepares the Cmake build infrastructure for the introduction of a Json I/O for filter configurations. The Json I/O will be added to the C API of KernelShark in the following patch. Signed-off-by: Yordan Karadzhov (VMware) --- kernel-shark-qt/CMakeLists.txt | 2 ++ kernel-shark-qt/README | 4 +-- kernel-shark-qt/build/FindJSONC.cmake | 38 +++++++++++++++++++++++++++ kernel-shark-qt/src/CMakeLists.txt | 1 + 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 kernel-shark-qt/build/FindJSONC.cmake diff --git a/kernel-shark-qt/CMakeLists.txt b/kernel-shark-qt/CMakeLists.txt index 7a802cd..3516caa 100644 --- a/kernel-shark-qt/CMakeLists.txt +++ b/kernel-shark-qt/CMakeLists.txt @@ -13,6 +13,7 @@ message("\n project: Kernel Shark: (version: ${KS_VERSION_STRING})\n") set(KS_DIR ${CMAKE_SOURCE_DIR}) include(${KS_DIR}/build/FindTraceCmd.cmake) +include(${KS_DIR}/build/FindJSONC.cmake) find_package(Doxygen) @@ -24,6 +25,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -pthread") include_directories(${KS_DIR}/src/ ${KS_DIR}/build/src/ + ${JSONC_INCLUDE_DIR} ${TRACECMD_INCLUDE_DIR} ${TRACEEVENT_INCLUDE_DIR}) diff --git a/kernel-shark-qt/README b/kernel-shark-qt/README index 6ff77a5..e6818fc 100644 --- a/kernel-shark-qt/README +++ b/kernel-shark-qt/README @@ -6,14 +6,14 @@ Third Party Software: ------------------------------------------------------------ The external dependencies: 1. In order to install the packages on Ubuntu do the following: - sudo apt-get install build-essential git cmake -y + sudo apt-get install build-essential git cmake libjson-c-dev -y 1.1 I you want to be able to generate Doxygen documentation: sudo apt-get install graphviz doxygen-gui -y 2. In order to install the packages on Fedora, as root do the following: - dnf install gcc gcc-c++ git cmake -y + dnf install gcc gcc-c++ git cmake json-c-devel -y 2.1 I you want to be able to generate Doxygen documentation: dnf install graphviz doxygen -y diff --git a/kernel-shark-qt/build/FindJSONC.cmake b/kernel-shark-qt/build/FindJSONC.cmake new file mode 100644 index 0000000..3bae20f --- /dev/null +++ b/kernel-shark-qt/build/FindJSONC.cmake @@ -0,0 +1,38 @@ +# - Try to find json-c +# https://cmake.org/Wiki/CMake:How_To_Find_Libraries +# Once done this will define +# JSONC_FOUND - System has json-c +# JSONC_INCLUDE_DIRS - The json-c include directories +# JSONC_LIBRARIES - The libraries needed to use json-c +# JSONC_DEFINITIONS - Compiler switches required for using json-c + +find_package(PkgConfig) +pkg_check_modules(PC_JSONC QUIET json-c) +set(JSONC_DEFINITIONS ${PC_JSONC_CFLAGS_OTHER}) + +find_path(JSONC_INCLUDE_DIR json.h + HINTS ${PC_JSONC_INCLUDEDIR} ${PC_JSONC_INCLUDE_DIRS} + PATH_SUFFIXES json-c) + +find_library(JSONC_LIBRARY NAMES json-c libjson-c + HINTS ${PC_JSONC_LIBDIR} ${PC_JSONC_LIBRARY_DIRS}) + +find_library(JSONC_LIBRARY NAMES json-c libjson-c + HINTS ${PC_JSON-C_LIBDIR} ${PC_JSON-C_LIBRARY_DIRS}) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set JSONC_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(JSONC DEFAULT_MSG + JSONC_LIBRARY JSONC_INCLUDE_DIR) + +if (NOT JSONC_FOUND) + + message(FATAL_ERROR "Json-C is Required!\n") + +endif (NOT JSONC_FOUND) + +mark_as_advanced(JSONC_INCLUDE_DIR JSONC_LIBRARY) + +set(JSONC_LIBRARIES ${JSONC_LIBRARY}) +set(JSONC_INCLUDE_DIRS ${JSONC_INCLUDE_DIR}) diff --git a/kernel-shark-qt/src/CMakeLists.txt b/kernel-shark-qt/src/CMakeLists.txt index cd42920..ea5dbda 100644 --- a/kernel-shark-qt/src/CMakeLists.txt +++ b/kernel-shark-qt/src/CMakeLists.txt @@ -6,6 +6,7 @@ add_library(kshark SHARED libkshark.c libkshark-collection.c) target_link_libraries(kshark ${CMAKE_DL_LIBS} + ${JSONC_LIBRARY} ${TRACEEVENT_LIBRARY} ${TRACECMD_LIBRARY}) From patchwork Thu Aug 16 15:07:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10759025 Return-Path: Received: from mail-wr1-f53.google.com ([209.85.221.53]:46210 "EHLO mail-wr1-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726328AbeHPSHC (ORCPT ); Thu, 16 Aug 2018 14:07:02 -0400 Received: by mail-wr1-f53.google.com with SMTP id a108-v6so1806507wrc.13 for ; Thu, 16 Aug 2018 08:07:55 -0700 (PDT) From: "Yordan Karadzhov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, "Yordan Karadzhov (VMware)" Subject: [PATCH v3 2/3] kernel-shark-qt: Add I/O for configuration data. Date: Thu, 16 Aug 2018 18:07:28 +0300 Message-Id: <20180816150729.4680-2-y.karadz@gmail.com> In-Reply-To: <20180816150729.4680-1-y.karadz@gmail.com> References: <20180816150729.4680-1-y.karadz@gmail.com> Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 46386 Add to the C API of KernelShark instruments for importing/exporting configuration settings to/from Json files. A wrapper is added in order to abstract out completely the use of Json. This can be useful in the future if we want to support multiple formats (YAML for example). This version of the patch contains a number of improvements suggested by Steven Rostedt. Thanks Steven! Signed-off-by: Yordan Karadzhov (VMware) --- kernel-shark-qt/src/CMakeLists.txt | 1 + kernel-shark-qt/src/libkshark-configio.c | 1453 ++++++++++++++++++++++ kernel-shark-qt/src/libkshark.h | 160 +++ 3 files changed, 1614 insertions(+) create mode 100644 kernel-shark-qt/src/libkshark-configio.c diff --git a/kernel-shark-qt/src/CMakeLists.txt b/kernel-shark-qt/src/CMakeLists.txt index ea5dbda..a762da1 100644 --- a/kernel-shark-qt/src/CMakeLists.txt +++ b/kernel-shark-qt/src/CMakeLists.txt @@ -3,6 +3,7 @@ message("\n src ...") message(STATUS "libkshark") add_library(kshark SHARED libkshark.c libkshark-model.c + libkshark-configio.c libkshark-collection.c) target_link_libraries(kshark ${CMAKE_DL_LIBS} diff --git a/kernel-shark-qt/src/libkshark-configio.c b/kernel-shark-qt/src/libkshark-configio.c new file mode 100644 index 0000000..b54dc5a --- /dev/null +++ b/kernel-shark-qt/src/libkshark-configio.c @@ -0,0 +1,1453 @@ +// SPDX-License-Identifier: LGPL-2.1 + +/* + * Copyright (C) 2018 VMware Inc, Yordan Karadzhov + */ + + /** + * @file libkshark-configio.c + * @brief Json Configuration I/O. + */ + +// C +/** Use GNU C Library. */ +#define _GNU_SOURCE +#include +#include + +// KernelShark +#include "libkshark.h" +#include "libkshark-model.h" + +static struct json_object *kshark_json_config_alloc(const char *type) +{ + json_object *jobj, *jtype; + + jobj = json_object_new_object(); + jtype = json_object_new_string(type); + + if (!jobj || !jtype) + goto fail; + + /* Set the type of this Json document. */ + json_object_object_add(jobj, "type", jtype); + + return jobj; + + fail: + fprintf(stderr, "Failed to allocate memory for json_object.\n"); + json_object_put(jobj); + json_object_put(jtype); + + return NULL; +} + +/** + * @brief Allocate kshark_config_doc and set its format. + * + * @param format: Input location for the Configuration format identifier. + * Currently only Json and String formats are supported. + * + * @returns kshark_config_doc instance on success. Else NULL. Use + * free() to free the object. + */ +struct kshark_config_doc * +kshark_config_alloc(enum kshark_config_formats format) +{ + struct kshark_config_doc *doc; + + switch (format) { + case KS_CONFIG_AUTO: + case KS_CONFIG_JSON: + case KS_CONFIG_STRING: + doc = malloc(sizeof(*doc)); + if (!doc) + goto fail; + + doc->format = format; + doc->conf_doc = NULL; + return doc; + default: + fprintf(stderr, "Document format %d not supported\n", + format); + goto fail; + } + + fail: + fprintf(stderr, "Failed to allocate memory for kshark_config_doc.\n"); + return NULL; +} + +/** + * @brief Create an empty Configuration document and set its format and type. + * + * @param type: String describing the type of the document, + * e.g. "kshark.record.config" or "kshark.filter.config". + * @param format: Input location for the Configuration format identifier. + * Currently only Json format is supported. + * + * @returns kshark_config_doc instance on success. Else NULL. Use + * kshark_free_config_doc() to free the object. + */ +struct kshark_config_doc * +kshark_config_new(const char *type, enum kshark_config_formats format) +{ + struct kshark_config_doc *doc = NULL; + + if (format == KS_CONFIG_AUTO) + format = KS_CONFIG_JSON; + + if (format == KS_CONFIG_JSON) { + doc = kshark_config_alloc(format); + if (doc) { + doc->conf_doc = kshark_json_config_alloc(type); + if (!doc->conf_doc) { + free(doc); + doc = NULL; + } + } + } + + return doc; +} + +/** + * @brief Free the Configuration document. + * + * @param conf: Input location for the kshark_config_doc instance. It is safe + * to pass a NULL value. + */ +void kshark_free_config_doc(struct kshark_config_doc *conf) +{ + if (!conf) + return; + + switch (conf->format) { + case KS_CONFIG_JSON: + json_object_put(conf->conf_doc); + break; + case KS_CONFIG_STRING: + free(conf->conf_doc); + break; + } + + free(conf); +} + +/** + * @brief Use an existing Json document to create a new KernelShark + * Configuration document. + * + * @param jobj: Input location for the json_object instance. + * + * @returns shark_config_doc instance on success, or NULL on error. Use + * kshark_free_config_doc() to free the object. + */ +struct kshark_config_doc *kshark_json_to_conf(struct json_object *jobj) +{ + struct kshark_config_doc *conf = kshark_config_alloc(KS_CONFIG_JSON); + + if (conf) + conf->conf_doc = jobj; + + return conf; +} + +/** + * @brief Use an existing string to create a new KernelShark Configuration + * document. + * + * @param val: Input location for the string. + * + * @returns shark_config_doc instance on success, or NULL on error. Use + * kshark_free_config_doc() to free the object. + */ +struct kshark_config_doc *kshark_string_to_conf(const char* val) +{ + struct kshark_config_doc *conf; + char *str; + + conf = kshark_config_alloc(KS_CONFIG_STRING); + if (conf) { + if (asprintf(&str, "%s", val) > 0) { + conf->conf_doc = str; + } else { + fprintf(stderr, + "Failed to allocate string conf. doc.\n"); + free(conf); + conf = NULL; + } + } + + return conf; +} + +/** + * @brief Add a field to a KernelShark Configuration document. + * + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * @param key: The name of the field. + * @param val: Input location for the kshark_config_doc to be added. Currently + * only Json and String formats are supported. Pass KS_CONFIG_AUTO + * if you want "val" to have the same fornat as "conf". Upon + * calling this function, the ownership of "val" transfers to + * "conf". + */ +void kshark_config_doc_add(struct kshark_config_doc *conf, + const char *key, + struct kshark_config_doc *val) +{ + struct json_object *jobj = NULL; + + if (!conf || !val) + return; + + if (val->format == KS_CONFIG_AUTO) + val->format = conf->format; + + switch (conf->format) { + case KS_CONFIG_JSON: + switch (val->format) { + case KS_CONFIG_JSON: + json_object_object_add(conf->conf_doc, key, + val->conf_doc); + break; + + case KS_CONFIG_STRING: + jobj = json_object_new_string(val->conf_doc); + if (!jobj) + goto fail; + + json_object_object_add(conf->conf_doc, key, jobj); + break; + + default: + fprintf(stderr, "Value format %d not supported\n", + val->format); + goto fail; + } + + free(val); + break; + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + goto fail; + } + + return; + + fail: + fprintf(stderr, "Failed to allocate memory for json_object.\n"); + json_object_put(jobj); + + return; +} + +static bool get_jval(struct kshark_config_doc *conf, + const char *key, void **val) +{ + return json_object_object_get_ex(conf->conf_doc, key, + (json_object **) val); +} + +/** + * @brief Get the KernelShark Configuration document associate with a given + * field name. + * + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * @param key: The name of the field. + * @param val: Output location for the kshark_config_doc instance containing + * the field. Currently only Json and String formats are supported. + * + * @returns True, if the key exists. Else False. + */ +bool kshark_config_doc_get(struct kshark_config_doc *conf, + const char *key, + struct kshark_config_doc *val) +{ + struct kshark_config_doc *tmp; + + if (!conf || !val) + return false; + + if (val->format == KS_CONFIG_AUTO) + val->format = conf->format; + + switch (conf->format) { + case KS_CONFIG_JSON: + switch (val->format) { + case KS_CONFIG_JSON: + json_object_put(val->conf_doc); + if (!get_jval(conf, key, &val->conf_doc)) + goto fail; + + return true; + case KS_CONFIG_STRING: + tmp = kshark_config_alloc(KS_CONFIG_AUTO); + if (!tmp) + goto fail; + + if (!get_jval(conf, key, &tmp->conf_doc)) + goto fail; + + free(val->conf_doc); + val->conf_doc = + (char *) json_object_get_string(tmp->conf_doc); + free(tmp); + + return true; + default: + fprintf(stderr, "Value format %d not supported\n", + val->format); + goto fail; + } + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + goto fail; + } + + fail: + fprintf(stderr, "Failed to get config. document.\n"); + return false; +} + +/** + * @brief Create an empty Record Configuration document. The type description + * is set to "kshark.record.config". + * + * @returns kshark_config_doc instance. Use kshark_free_config_doc() to free + * the object. + */ +struct kshark_config_doc * +kshark_record_config_new(enum kshark_config_formats format) +{ + return kshark_config_new("kshark.record.config", format); +} + +/** + * @brief Create an empty Filter Configuration document. The type description + * is set to "kshark.filter.config". + * + * @returns kshark_config_doc instance. Use kshark_free_config_doc() to free + * the object. + */ +struct kshark_config_doc * +kshark_filter_config_new(enum kshark_config_formats format) +{ + return kshark_config_new("kshark.filter.config", format); +} + +/** + * @brief Create an empty Text Configuration document. The Text Configuration + * documents do not use type descriptions. + * + * @returns kshark_config_doc instance. Use free() to free the object. + */ +struct kshark_config_doc *kshark_string_config_alloc() +{ + return kshark_config_alloc(KS_CONFIG_STRING); +} + +static void json_del_if_exist(struct json_object *jobj, const char *key) +{ + struct json_object *temp; + if (json_object_object_get_ex(jobj, key, &temp)) + json_object_object_del(jobj, key); +} + + +static bool kshark_json_type_check(struct json_object *jobj, const char *type) +{ + struct json_object *jtype; + const char *type_str; + + if (!json_object_object_get_ex(jobj, "type", &jtype)) + return false; + + type_str = json_object_get_string(jtype); + if (strcmp(type_str, type) != 0) + return false; + + return true; +} + +/** + * @brief Check the type of a Configuration document and compare with an + * expected value. + * + * @param conf: Input location for the kshark_config_doc instance. + * @param type: Input location for the expected value of the Configuration + * document type, e.g. "kshark.record.config" or + * "kshark.filter.config". + * + * @returns True, if the document has the expected type. Else false. + */ +bool kshark_type_check(struct kshark_config_doc *conf, const char *type) +{ + switch (conf->format) { + case KS_CONFIG_JSON: + return kshark_json_type_check(conf->conf_doc, type); + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + return false; + } +} + +static bool kshark_trace_file_to_json(const char *file, + struct json_object *jobj) +{ + struct json_object *jfile_name, *jtime; + struct stat st; + + if (!file || !jobj) + return false; + + if (stat(file, &st) != 0) { + fprintf(stderr, "Unable to find file %s\n", file); + return false; + } + + jfile_name = json_object_new_string(file); + jtime = json_object_new_int64(st.st_mtime); + + if (!jfile_name || !jtime) + goto fail; + + json_object_object_add(jobj, "file", jfile_name); + json_object_object_add(jobj, "time", jtime); + + return true; + + fail: + fprintf(stderr, "Failed to allocate memory for json_object.\n"); + json_object_put(jobj); + json_object_put(jfile_name); + json_object_put(jtime); + + return false; +} + +/** + * @brief Record the name of a trace data file and its timestamp into a + * Configuration document. + * + * @param file: The name of the file. + * @param format: Input location for the Configuration format identifier. + * Currently only Json format is supported. + * + * @returns True, on success. Else False. + */ +struct kshark_config_doc * +kshark_export_trace_file(const char *file, + enum kshark_config_formats format) +{ + /* Create a new Configuration document. */ + struct kshark_config_doc *conf = + kshark_config_new("kshark.data.config", format); + + switch (format) { + case KS_CONFIG_JSON: + kshark_trace_file_to_json(file, conf->conf_doc); + return conf; + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + return NULL; + } +} + +static bool kshark_trace_file_from_json(const char **file, + struct json_object *jobj) +{ + struct json_object *jfile_name, *jtime; + const char *file_str; + struct stat st; + int64_t time; + + if (!jobj) + return false; + + if (!kshark_json_type_check(jobj, "kshark.data.config") || + !json_object_object_get_ex(jobj, "file", &jfile_name) || + !json_object_object_get_ex(jobj, "time", &jtime)) { + fprintf(stderr, + "Failed to retrieve data file from json_object.\n"); + return false; + } + + file_str = json_object_get_string(jfile_name); + time = json_object_get_int64(jtime); + + if (stat(file_str, &st) != 0) { + fprintf(stderr, "Unable to find file %s\n", file_str); + return false; + } + + if (st.st_mtime != time) { + fprintf(stderr,"Timestamp mismatch!\nFile %s", file_str); + return false; + } + + *file = file_str; + + return true; +} + +/** + * @brief Read the name of a trace data file and its timestamp from a + * Configuration document and check if such a file exists. + * If the file exists, open it. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns The name of the file on success. Else NULL. + */ +const char* kshark_import_trace_file(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf) +{ + const char *file = NULL; + switch (conf->format) { + case KS_CONFIG_JSON: + if (kshark_trace_file_from_json(&file, conf->conf_doc)) + kshark_open(kshark_ctx, file); + + break; + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + return NULL; + } + + return file; +} + +static bool kshark_model_to_json(struct kshark_trace_histo *histo, + struct json_object *jobj) +{ + struct json_object *jrange, *jmin, *jmax, *jn_bins; + if (!histo || !jobj) + return false; + + jrange = json_object_new_array(); + + jmin = json_object_new_int64(histo->min); + jmax = json_object_new_int64(histo->max); + jn_bins = json_object_new_int(histo->n_bins); + + if (!jrange || !jmin || !jmax || !jn_bins) + goto fail; + + json_object_array_put_idx(jrange, 0, jmin); + json_object_array_put_idx(jrange, 1, jmax); + + json_object_object_add(jobj, "range", jrange); + json_object_object_add(jobj, "bins", jn_bins); + + return true; + + fail: + fprintf(stderr, "Failed to allocate memory for json_object.\n"); + json_object_put(jobj); + json_object_put(jrange); + json_object_put(jmin); + json_object_put(jmax); + json_object_put(jn_bins); + + return false; +} + +/** + * @brief Record the current configuration of the Vis. model into a + * Configuration document. + * Load the configuration of the Vis. model from a Configuration + * document. + * + * @param histo: Input location for the Vis. model descriptor. + * @param format: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, on success. Else False. + */ +struct kshark_config_doc * +kshark_export_model(struct kshark_trace_histo *histo, + enum kshark_config_formats format) +{ + /* Create a new Configuration document. */ + struct kshark_config_doc *conf = + kshark_config_new("kshark.model.config", format); + + switch (format) { + case KS_CONFIG_JSON: + kshark_model_to_json(histo, conf->conf_doc); + return conf; + + default: + fprintf(stderr, "Document format %d not supported\n", + format); + return NULL; + } +} + +static bool kshark_model_from_json(struct kshark_trace_histo *histo, + struct json_object *jobj) +{ + struct json_object *jrange, *jmin, *jmax, *jn_bins; + uint64_t min, max; + int n_bins; + + if (!histo || !jobj) + return false; + + if (!kshark_json_type_check(jobj, "kshark.model.config") || + !json_object_object_get_ex(jobj, "range", &jrange) || + !json_object_object_get_ex(jobj, "bins", &jn_bins) || + json_object_get_type(jrange) != json_type_array || + json_object_array_length(jrange) != 2) + goto fail; + + jmin = json_object_array_get_idx(jrange, 0); + jmax = json_object_array_get_idx(jrange, 1); + if (!jmin || !jmax) + goto fail; + + min = json_object_get_int64(jmin); + max = json_object_get_int64(jmax); + n_bins = json_object_get_int(jn_bins); + ksmodel_set_bining(histo, n_bins, min, max); + + if (histo->data && histo->data_size) + ksmodel_fill(histo, histo->data, histo->data_size); + + return true; + + fail: + fprintf(stderr, "Failed to load event filter from json_object.\n"); + return false; +} + +/** + * @brief Load the configuration of the Vis. model from a Configuration + * document. + * + * @param histo: Input location for the Vis. model descriptor. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, if the model has been loaded. If the model configuration + * document contains no data or in a case of an error, the function + * returns False. + */ +bool kshark_import_model(struct kshark_trace_histo *histo, + struct kshark_config_doc *conf) +{ + switch (conf->format) { + case KS_CONFIG_JSON: + return kshark_model_from_json(histo, conf->conf_doc); + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + return false; + } +} + +static bool kshark_event_filter_to_json(struct pevent *pevent, + struct tracecmd_filter_id *filter, + const char *filter_name, + struct json_object *jobj) +{ + json_object *jfilter_data, *jevent, *jsystem, *jname; + int i, evt, *ids; + char *temp; + + /* + * If this Json document already contains a description of the filter, + * delete this description. + */ + json_del_if_exist(jobj, filter_name); + + /* Get the array of Ids to be fitered. */ + ids = tracecmd_filter_ids(filter); + if (!ids) + return true; + + /* Create a Json array and fill the Id values into it. */ + jfilter_data = json_object_new_array(); + if (!jfilter_data) + goto fail; + + for (i = 0; i < filter->count; ++i) { + for (evt = 0; evt < pevent->nr_events; ++evt) { + if (pevent->events[evt]->id == ids[i]) { + jevent = json_object_new_object(); + + temp = pevent->events[evt]->system; + jsystem = json_object_new_string(temp); + + temp = pevent->events[evt]->name; + jname = json_object_new_string(temp); + + if (!jevent || !jsystem || !jname) + goto fail; + + json_object_object_add(jevent, "system", + jsystem); + + json_object_object_add(jevent, "name", + jname); + + json_object_array_add(jfilter_data, jevent); + + break; + } + } + } + + free(ids); + + /* Add the array of Ids to the filter config document. */ + json_object_object_add(jobj, filter_name, jfilter_data); + + return true; + + fail: + fprintf(stderr, "Failed to allocate memory for json_object.\n"); + json_object_put(jfilter_data); + json_object_put(jevent); + json_object_put(jsystem); + json_object_put(jname); + free(ids); + + return false; +} + +/** + * @brief Record the current configuration of an Event Id filter into a + * Configuration document. + * + * @param pevent: Input location for the Page event. + * @param filter: Input location for an Id filter. + * @param filter_name: The name of the filter to show up in the Json document. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, on success or False in the case of an error. + */ +bool kshark_export_event_filter(struct pevent *pevent, + struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf) +{ + switch (conf->format) { + case KS_CONFIG_JSON: + return kshark_event_filter_to_json(pevent, filter, + filter_name, + conf->conf_doc); + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + return false; + } +} + +static bool kshark_event_filter_from_json(struct pevent *pevent, + struct tracecmd_filter_id *filter, + const char *filter_name, + struct json_object *jobj) +{ + json_object *jfilter, *jevent, *jsystem, *jname; + const char *system_str, *name_str; + struct event_format *event; + int i, length; + + /* + * Use the name of the filter to find the array of events associated + * with this filter. Notice that the filter config document may + * contain no data for this particular filter. + */ + if (!json_object_object_get_ex(jobj, filter_name, &jfilter)) + return false; + + if (!kshark_json_type_check(jobj, "kshark.filter.config") || + json_object_get_type(jfilter) != json_type_array) + goto fail; + + /* Set the filter. */ + length = json_object_array_length(jfilter); + for (i = 0; i < length; ++i) { + jevent = json_object_array_get_idx(jfilter, i); + + if (!json_object_object_get_ex(jevent, "system", &jsystem) || + !json_object_object_get_ex(jevent, "name", &jname)) + goto fail; + + system_str = json_object_get_string(jsystem); + name_str = json_object_get_string(jname); + + event = pevent_find_event_by_name(pevent, system_str, name_str); + if (!event) + goto fail; + + tracecmd_filter_id_add(filter, event->id); + } + + return true; + + fail: + fprintf(stderr, "Failed to load event filter from json_object.\n"); + return false; +} + +/** + * @brief Load from Configuration document the configuration of an Event Id filter. + * + * @param pevent: Input location for the Page event. + * @param filter: Input location for an Id filter. + * @param filter_name: The name of the filter as showing up in the Config. + * document. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, if a filter has been loaded. If the filter configuration + * document contains no data for this particular filter or in a case + * of an error, the function returns False. + */ +bool kshark_import_event_filter(struct pevent *pevent, + struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf) +{ + switch (conf->format) { + case KS_CONFIG_JSON: + return kshark_event_filter_from_json(pevent, filter, + filter_name, + conf->conf_doc); + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + return false; + } +} + +static bool kshark_task_filter_to_json(struct tracecmd_filter_id *filter, + const char *filter_name, + struct json_object *jobj) +{ + json_object *jfilter_data, *jpid; + int i, *ids; + + /* + * If this Json document already contains a description of the model, + * delete this description. + */ + json_del_if_exist(jobj, filter_name); + + /* Get the array of Ids to be fitered. */ + ids = tracecmd_filter_ids(filter); + if (!ids) + return true; + + /* Create a Json array and fill the Id values into it. */ + jfilter_data = json_object_new_array(); + if (!jfilter_data) + goto fail; + + for (i = 0; i < filter->count; ++i) { + jpid = json_object_new_int(ids[i]); + if (!jpid) + goto fail; + + json_object_array_add(jfilter_data, jpid); + } + + free(ids); + + /* Add the array of Ids to the filter config document. */ + json_object_object_add(jobj, filter_name, jfilter_data); + + return true; + + fail: + fprintf(stderr, "Failed to allocate memory for json_object.\n"); + json_object_put(jfilter_data); + json_object_put(jpid); + free(ids); + + return false; +} + +/** + * @brief Record the current configuration of a Task Id filter into a + * Configuration document. + * + * @param filter: Input location for an Id filter. + * @param filter_name: The name of the filter to show up in the Json document. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, on success or False in the case of an error. + */ +bool kshark_export_task_filter(struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf) +{ + switch (conf->format) { + case KS_CONFIG_JSON: + return kshark_task_filter_to_json(filter, filter_name, + conf->conf_doc); + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + return false; + } +} + +static bool kshark_task_filter_from_json(struct tracecmd_filter_id *filter, + const char *filter_name, + struct json_object *jobj) +{ + json_object *jfilter, *jpid; + int i, length; + + /* + * Use the name of the filter to find the array of events associated + * with this filter. Notice that the filter config document may + * contain no data for this particular filter. + */ + if (!json_object_object_get_ex(jobj, filter_name, &jfilter)) + return false; + + if (!kshark_json_type_check(jobj, "kshark.filter.config") || + json_object_get_type(jfilter) != json_type_array) + goto fail; + + /* Set the filter. */ + length = json_object_array_length(jfilter); + for (i = 0; i < length; ++i) { + jpid = json_object_array_get_idx(jfilter, i); + if (!jpid) + goto fail; + + tracecmd_filter_id_add(filter, json_object_get_int(jpid)); + } + + return true; + + fail: + fprintf(stderr, "Failed to load task filter from json_object.\n"); + return false; +} + +/** + * @brief Load from Configuration document the configuration of a Task Id filter. + * + * @param filter: Input location for an Id filter. + * @param filter_name: The name of the filter as showing up in the Config. + * document. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, if a filter has been loaded. If the filter configuration + * document contains no data for this particular filter or in a case + * of an error, the function returns False. + */ +bool kshark_import_task_filter(struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf) +{ + switch (conf->format) { + case KS_CONFIG_JSON: + return kshark_task_filter_from_json(filter, filter_name, + conf->conf_doc); + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + return false; + } +} + +static bool kshark_adv_filters_to_json(struct kshark_context *kshark_ctx, + struct json_object *jobj) +{ + struct event_filter *adv_filter = kshark_ctx->advanced_event_filter; + json_object *jfilter_data, *jevent, *jsystem, *jname, *jfilter; + struct event_format **events; + char *str; + int i; + + /* + * If this Json document already contains a description of the model, + * delete this description. + */ + json_del_if_exist(jobj, KS_ADV_EVENT_FILTER_NAME); + + if (!kshark_ctx->advanced_event_filter || + !kshark_ctx->advanced_event_filter->filters) + return true; + + /* Create a Json array and fill the Id values into it. */ + jfilter_data = json_object_new_array(); + if (!jfilter_data) + goto fail; + + events = pevent_list_events(kshark_ctx->pevent, EVENT_SORT_SYSTEM); + if (!events) + return false; + + for (i = 0; events[i]; i++) { + str = pevent_filter_make_string(adv_filter, + events[i]->id); + if (!str) + continue; + + jevent = json_object_new_object(); + jsystem = json_object_new_string(events[i]->system); + jname = json_object_new_string(events[i]->name); + jfilter = json_object_new_string(str); + if (!jevent || !jsystem || !jname || !jfilter) + goto fail; + + json_object_object_add(jevent, "system", jsystem); + json_object_object_add(jevent, "name", jname); + json_object_object_add(jevent, "condition", jfilter); + + json_object_array_add(jfilter_data, jevent); + } + + /* Add the array of advanced filters to the filter config document. */ + json_object_object_add(jobj, KS_ADV_EVENT_FILTER_NAME, jfilter_data); + + return true; + + fail: + fprintf(stderr, "Failed to allocate memory for json_object.\n"); + json_object_put(jfilter_data); + json_object_put(jevent); + json_object_put(jsystem); + json_object_put(jname); + json_object_put(jfilter); + + return false; +} + +/** + * @brief Record the current configuration of the advanced filter into a + * Configuration document. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. If NULL, a new Adv. Filter + * Configuration document will be created. + * + * @returns True, on success or False in the case of an error. + */ +bool kshark_export_adv_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc **conf) +{ + if (!*conf) + *conf = kshark_filter_config_new(KS_CONFIG_JSON); + + switch ((*conf)->format) { + case KS_CONFIG_JSON: + return kshark_adv_filters_to_json(kshark_ctx, + (*conf)->conf_doc); + + default: + fprintf(stderr, "Document format %d not supported\n", + (*conf)->format); + return false; + } +} + +static bool kshark_adv_filters_from_json(struct kshark_context *kshark_ctx, + struct json_object *jobj) +{ + struct event_filter *adv_filter = kshark_ctx->advanced_event_filter; + json_object *jfilter, *jsystem, *jname, *jcond; + int i, length, ret; + char *filter_str; + + /* + * Use the name of the filter to find the array of events associated + * with this filter. Notice that the filter config document may + * contain no data for this particular filter. + */ + if (!json_object_object_get_ex(jobj, KS_ADV_EVENT_FILTER_NAME, + &jfilter)) + return false; + + if (!kshark_json_type_check(jobj, "kshark.filter.config") || + json_object_get_type(jfilter) != json_type_array) + goto fail; + + /* Set the filter. */ + length = json_object_array_length(jfilter); + for (i = 0; i < length; ++i) { + jfilter = json_object_array_get_idx(jfilter, i); + + if (!json_object_object_get_ex(jfilter, "system", &jsystem) || + !json_object_object_get_ex(jfilter, "name", &jname) || + !json_object_object_get_ex(jfilter, "condition", &jcond)) + goto fail; + + asprintf(&filter_str, "%s/%s:%s", + json_object_get_string(jsystem), + json_object_get_string(jname), + json_object_get_string(jcond)); + + ret = pevent_filter_add_filter_str(adv_filter, + filter_str); + if (ret < 0) + goto fail; + } + + return true; + + fail: + fprintf(stderr, "Failed to laod Advanced filters.\n"); + char error_str[200]; + int error_status = + pevent_strerror(kshark_ctx->pevent, ret, error_str, + sizeof(error_str)); + + if (error_status == 0) + fprintf(stderr, "filter failed due to: %s\n", error_str); + + free(filter_str); + return false; +} + +/** + * @brief Load from Configuration document the configuration of the advanced + * filter. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, if a filter has been loaded. If the filter configuration + * document contains no data for the Adv. filter or in a case of + * an error, the function returns False. + */ +bool kshark_import_adv_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf) +{ + switch (conf->format) { + case KS_CONFIG_JSON: + return kshark_adv_filters_from_json(kshark_ctx, + conf->conf_doc); + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + return false; + } +} + +static bool filter_is_set(struct tracecmd_filter_id *filter) +{ + return filter && filter->count; +} + +/** + * @brief Record the current configuration of "show task" and "hide task" + * filters into a Json document. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. If NULL, a new Filter + * Configuration document will be created. + * + * @returns True, if a filter has been recorded. If both filters contain + * no Id values or in a case of an error, the function returns False. + */ +bool kshark_export_all_event_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc **conf) +{ + bool ret = true; + + if (!*conf) + *conf = kshark_filter_config_new(KS_CONFIG_JSON); + + /* Save a filter only if it contains Id values. */ + if (filter_is_set(kshark_ctx->show_event_filter)) + ret &= kshark_export_event_filter(kshark_ctx->pevent, + kshark_ctx->show_event_filter, + KS_SHOW_EVENT_FILTER_NAME, + *conf); + + if (filter_is_set(kshark_ctx->hide_event_filter)) + ret &= kshark_export_event_filter(kshark_ctx->pevent, + kshark_ctx->hide_event_filter, + KS_HIDE_EVENT_FILTER_NAME, + *conf); + + return ret; +} + +/** + * @brief Record the current configuration of "show task" and "hide task" + * filters into a Configuration document. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. If NULL, a new Filter + * Configuration document will be created. + * + * @returns True, if a filter has been recorded. If both filters contain + * no Id values or in a case of an error, the function returns False. + */ +bool kshark_export_all_task_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc **conf) +{ + bool ret = true; + + if (!*conf) + *conf = kshark_filter_config_new(KS_CONFIG_JSON); + + /* Save a filter only if it contains Id values. */ + if (filter_is_set(kshark_ctx->show_task_filter)) + ret &= kshark_export_task_filter(kshark_ctx->show_task_filter, + KS_SHOW_TASK_FILTER_NAME, + *conf); + + if (filter_is_set(kshark_ctx->hide_task_filter)) + ret &= kshark_export_task_filter(kshark_ctx->hide_task_filter, + KS_HIDE_TASK_FILTER_NAME, + *conf); + + return ret; +} + +/** + * @brief Load from a Configuration document the configuration of "show event" + * and "hide event" filters. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, if a filter has been loaded. If the filter configuration + * document contains no data for any event filter or in a case + * of an error, the function returns False. + */ +bool kshark_import_all_event_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf) +{ + bool ret = false; + + ret |= kshark_import_event_filter(kshark_ctx->pevent, + kshark_ctx->hide_event_filter, + KS_HIDE_EVENT_FILTER_NAME, + conf); + + ret |= kshark_import_event_filter(kshark_ctx->pevent, + kshark_ctx->show_event_filter, + KS_SHOW_EVENT_FILTER_NAME, + conf); + + return ret; +} + +/** + * @brief Load from Configuration document the configuration of "show task" + * and "hide task" filters. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, if a filter has been loaded. If the filter configuration + * document contains no data for any task filter or in a case of an + * error, the function returns False. + */ +bool kshark_import_all_task_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf) +{ + bool ret = false; + + ret |= kshark_import_task_filter(kshark_ctx->hide_task_filter, + KS_HIDE_TASK_FILTER_NAME, + conf); + + ret |= kshark_import_task_filter(kshark_ctx->show_task_filter, + KS_SHOW_TASK_FILTER_NAME, + conf); + + return ret; +} + +/** + * @brief Create a Filter Configuration document containing the current + * configuration of all filters. + * + * @param kshark_ctx: Input location for session context pointer. + * @param format: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns kshark_config_doc instance. Use kshark_free_config_doc() to free + * the object. + */ +struct kshark_config_doc * +kshark_export_all_filters(struct kshark_context *kshark_ctx, + enum kshark_config_formats format) +{ + /* Create a new Configuration document. */ + struct kshark_config_doc *conf = + kshark_filter_config_new(format); + + /* Save a filter only if it contains Id values. */ + if (!kshark_export_all_event_filters(kshark_ctx, &conf) || + !kshark_export_all_task_filters(kshark_ctx, &conf) || + !kshark_export_adv_filters(kshark_ctx, &conf)) { + kshark_free_config_doc(conf); + return NULL; + } + + return conf; +} + +/** + * @brief Load from a Configuration document the configuration of all filters. + * + * @param kshark_ctx: Input location for session context pointer. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, if a filter has been loaded. If the filter configuration + * document contains no data for any filter or in a case of an error, + * the function returns False. + */ +bool kshark_import_all_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf) +{ + bool ret; + ret = kshark_import_all_task_filters(kshark_ctx, conf); + ret |= kshark_import_all_event_filters(kshark_ctx, conf); + ret |= kshark_import_adv_filters(kshark_ctx, conf); + + return ret; +} + +static bool kshark_save_json_file(const char *file_name, + struct json_object *jobj) +{ + int flags; + + /* Save the file in a human-readable form. */ + flags = JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY; + if (json_object_to_file_ext(file_name, jobj, flags) == 0) + return true; + + return false; +} + +/** + * @brief Save a Configuration document into a file. + * + * @param file_name: The name of the file. + * @param conf: Input location for the kshark_config_doc instance. Currently + * only Json format is supported. + * + * @returns True, on success. Else False. + */ +bool kshark_save_config_file(const char *file_name, + struct kshark_config_doc *conf) +{ + switch (conf->format) { + case KS_CONFIG_JSON: + return kshark_save_json_file(file_name, conf->conf_doc); + + default: + fprintf(stderr, "Document format %d not supported\n", + conf->format); + return false; + } +} + +static struct json_object *kshark_open_json_file(const char *file_name, + const char *type) +{ + struct json_object *jobj, *var; + const char *type_var; + + jobj = json_object_from_file(file_name); + + if (!jobj) + return NULL; + + /* Get the type of the document. */ + if (!json_object_object_get_ex(jobj, "type", &var)) + goto fail; + + type_var = json_object_get_string(var); + + if (strcmp(type, type_var) != 0) + goto fail; + + return jobj; + + fail: + /* The document has a wrong type. */ + fprintf(stderr, "Failed to open Json file %s\n.", file_name); + fprintf(stderr, "The document has a wrong type.\n"); + + json_object_put(jobj); + return NULL; +} + +static const char *get_ext(const char *filename) +{ + const char *dot = strrchr(filename, '.'); + + if(!dot) + return "unknown"; + + return dot + 1; +} + +/** + * @brief Open for read a Configuration file and check if it has the + * expected type. + * + * @param file_name: The name of the file. Currently only Json files are + * supported. + * @param type: String describing the expected type of the document, + * e.g. "kshark.record.config" or "kshark.filter.config". + * + * @returns kshark_config_doc instance on success, or NULL on failure. Use + * kshark_free_config_doc() to free the object. + */ +struct kshark_config_doc *kshark_open_config_file(const char *file_name, + const char *type) +{ + struct kshark_config_doc *conf = NULL; + + if (strcmp(get_ext(file_name), "json") == 0) { + struct json_object *jobj = + kshark_open_json_file(file_name, type); + + if (jobj) { + conf = malloc(sizeof(*conf)); + conf->conf_doc = jobj; + conf->format = KS_CONFIG_JSON; + } + } + + return conf; +} diff --git a/kernel-shark-qt/src/libkshark.h b/kernel-shark-qt/src/libkshark.h index ff09da3..69f77af 100644 --- a/kernel-shark-qt/src/libkshark.h +++ b/kernel-shark-qt/src/libkshark.h @@ -16,6 +16,9 @@ #include #include +// Json-C +#include + #ifdef __cplusplus extern "C" { #endif @@ -367,6 +370,163 @@ kshark_get_collection_entry_back(struct kshark_entry_request **req, const struct kshark_entry_collection *col, ssize_t *index); +/** Structure representing a KernelShark Configuration document. */ +struct kshark_config_doc { + /** Document format identifier. */ + int format; + + /** Configuration document instance. */ + void *conf_doc; +}; + +/** Configuration format identifiers. */ +enum kshark_config_formats { + /** Unformatted Configuration document identifier. */ + KS_CONFIG_AUTO = 0, + + /** + * String Configuration document identifier. The String format is + * meant to be used only by kshark_config_doc_add() and + * kshark_config_doc_get(), when adding/getting simple string fields. + */ + KS_CONFIG_STRING, + + /** Json Configuration document identifier. */ + KS_CONFIG_JSON, +}; + +/** + * Field name for the Configuration document describing the Hide Event filter. + */ +#define KS_HIDE_EVENT_FILTER_NAME "hide event filter" + +/** + * Field name for the Configuration document describing the Show Event filter. + */ +#define KS_SHOW_EVENT_FILTER_NAME "show event filter" + +/** + * Field name for the Configuration document describing the Hide Task filter. + */ +#define KS_HIDE_TASK_FILTER_NAME "hide task filter" + +/** + * Field name for the Configuration document describing the Show Task filter. + */ +#define KS_SHOW_TASK_FILTER_NAME "show task filter" + +/** + * Field name for the Configuration document describing the Advanced event + * filter. + */ +#define KS_ADV_EVENT_FILTER_NAME "adv event filter" + +/** + * Field name for the Configuration document describing the state of the Vis. + * model. + */ +#define KS_HISTO_NAME "vis. model" + +/** + * Field name for the Configuration document describing the currently loaded + * trace data file. + */ +#define KS_DATA_SOURCE_NAME "trace data" + +struct kshark_config_doc * +kshark_config_alloc(enum kshark_config_formats); + +struct kshark_config_doc * +kshark_config_new(const char *type, enum kshark_config_formats); + +void kshark_free_config_doc(struct kshark_config_doc *conf); + +struct kshark_config_doc * +kshark_record_config_new(enum kshark_config_formats); + +struct kshark_config_doc * +kshark_filter_config_new(enum kshark_config_formats); + +struct kshark_config_doc *kshark_string_config_alloc(); + +bool kshark_type_check(struct kshark_config_doc *conf, const char *type); + +void kshark_config_doc_add(struct kshark_config_doc *conf, + const char *key, + struct kshark_config_doc *val); + +bool kshark_config_doc_get(struct kshark_config_doc *conf, + const char *key, + struct kshark_config_doc *val); + +struct kshark_trace_histo; + +struct kshark_config_doc * +kshark_export_trace_file(const char *file, + enum kshark_config_formats format); + +const char *kshark_import_trace_file(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf); + +struct kshark_config_doc * +kshark_export_model(struct kshark_trace_histo *histo, + enum kshark_config_formats format); + + +bool kshark_import_model(struct kshark_trace_histo *histo, + struct kshark_config_doc *conf); + +bool kshark_export_adv_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc **conf); + +bool kshark_import_adv_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf); + +bool kshark_export_event_filter(struct pevent *pevent, + struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf); + +bool kshark_import_event_filter(struct pevent *pevent, + struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf); + +bool kshark_export_task_filter(struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf); + +bool kshark_import_task_filter(struct tracecmd_filter_id *filter, + const char *filter_name, + struct kshark_config_doc *conf); + +bool kshark_export_all_event_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc **conf); + +bool kshark_export_all_task_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc **conf); + +struct kshark_config_doc * +kshark_export_all_filters(struct kshark_context *kshark_ctx, + enum kshark_config_formats format); + +bool kshark_import_all_event_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf); + +bool kshark_import_all_task_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf); + +bool kshark_import_all_filters(struct kshark_context *kshark_ctx, + struct kshark_config_doc *conf); + +bool kshark_save_config_file(const char *file_name, + struct kshark_config_doc *conf); + +struct kshark_config_doc *kshark_open_config_file(const char *file_name, + const char *type); + +struct kshark_config_doc *kshark_json_to_conf(struct json_object *jobj); + #ifdef __cplusplus } #endif From patchwork Thu Aug 16 15:07:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 10759023 Return-Path: Received: from mail-wm0-f67.google.com ([74.125.82.67]:36249 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388180AbeHPSHA (ORCPT ); Thu, 16 Aug 2018 14:07:00 -0400 Received: by mail-wm0-f67.google.com with SMTP id w24-v6so4656748wmc.1 for ; Thu, 16 Aug 2018 08:07:56 -0700 (PDT) From: "Yordan Karadzhov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, "Yordan Karadzhov (VMware)" Subject: [PATCH v3 3/3] kernel-shark-qt: Add an example showing how to import/export config. data Date: Thu, 16 Aug 2018 18:07:29 +0300 Message-Id: <20180816150729.4680-3-y.karadz@gmail.com> In-Reply-To: <20180816150729.4680-1-y.karadz@gmail.com> References: <20180816150729.4680-1-y.karadz@gmail.com> Sender: linux-trace-devel-owner@vger.kernel.org List-ID: Content-Length: 2873 This patch introduces a basic example, showing how to use the C API of KernelShark to import/export configuration data. Signed-off-by: Yordan Karadzhov (VMware) --- kernel-shark-qt/examples/CMakeLists.txt | 4 ++ kernel-shark-qt/examples/configio.c | 65 +++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 kernel-shark-qt/examples/configio.c diff --git a/kernel-shark-qt/examples/CMakeLists.txt b/kernel-shark-qt/examples/CMakeLists.txt index 6906eba..a3745fa 100644 --- a/kernel-shark-qt/examples/CMakeLists.txt +++ b/kernel-shark-qt/examples/CMakeLists.txt @@ -11,3 +11,7 @@ target_link_libraries(dfilter kshark) message(STATUS "datahisto") add_executable(dhisto datahisto.c) target_link_libraries(dhisto kshark) + +message(STATUS "confogio") +add_executable(confio configio.c) +target_link_libraries(confio kshark) diff --git a/kernel-shark-qt/examples/configio.c b/kernel-shark-qt/examples/configio.c new file mode 100644 index 0000000..3b1928f --- /dev/null +++ b/kernel-shark-qt/examples/configio.c @@ -0,0 +1,65 @@ +#include +#include + +#include "libkshark.h" + +int main(int argc, char **argv) +{ + struct kshark_config_doc *conf, *filter, *hello; + struct kshark_context *kshark_ctx; + int *ids, i; + + /* Create a new kshark session. */ + kshark_ctx = NULL; + if (!kshark_instance(&kshark_ctx)) + return 1; + + if (argc == 1) { + tracecmd_filter_id_add(kshark_ctx->show_task_filter, 314); + tracecmd_filter_id_add(kshark_ctx->show_task_filter, 42); + + /* Create a new Confog. doc. */ + conf = kshark_config_new("foo.bar.config", KS_CONFIG_JSON); + + /* Add filter's info. */ + filter = kshark_export_all_filters(kshark_ctx, KS_CONFIG_JSON); + kshark_config_doc_add(conf, "Filters" ,filter); + + /* Add "Hello Kernel" message. */ + hello = kshark_string_config_alloc(); + hello->conf_doc = "Hello Kernel"; + kshark_config_doc_add(conf, "Message" ,hello); + + /* Save to file. */ + kshark_save_config_file("conf.json", conf); + } else { + /* Open a Config. file. */ + conf = kshark_open_config_file(argv[1], "foo.bar.config"); + + /* Retrieve the filter's info. */ + filter = kshark_config_alloc(KS_CONFIG_JSON); + if (kshark_config_doc_get(conf, "Filters" ,filter)) { + kshark_import_all_filters(kshark_ctx, filter); + + /* Get the array of Ids to be fitered. */ + ids = tracecmd_filter_ids(kshark_ctx->show_task_filter); + for (i = 0; i < kshark_ctx->show_task_filter->count; ++i) + printf("pid: %i\n", ids[i]); + } + + /* Retrieve the message. */ + hello = kshark_string_config_alloc(); + if (kshark_config_doc_get(conf, "Message" ,hello)) + puts((char *) hello->conf_doc); + + free(filter); + free(hello); + free(ids); + } + + kshark_free_config_doc(conf); + + kshark_free(kshark_ctx); + + return 0; +}