| // SPDX-License-Identifier: LGPL-2.1 |
| |
| /* |
| * Copyright (C) 2018 VMware Inc, Yordan Karadzhov (VMware) <y.karadz@gmail.com> |
| */ |
| |
| /** |
| * @file libkshark-configio.c |
| * @brief Json Configuration I/O. |
| */ |
| |
| // C |
| #ifndef _GNU_SOURCE |
| /** Use GNU C Library. */ |
| #define _GNU_SOURCE |
| #endif // _GNU_SOURCE |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <sys/stat.h> |
| |
| // KernelShark |
| #include "libkshark.h" |
| #include "libkshark-model.h" |
| #include "libkshark-plugin.h" |
| #include "libkshark-tepdata.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, otherwise 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); |
| } |
| |
| return NULL; |
| |
| 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.config.record" or "kshark.config.filter". |
| * @param format: Input location for the Configuration format identifier. |
| * Currently only Json format is supported. |
| * |
| * @returns kshark_config_doc instance on success, otherwise 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; |
| |
| switch (format) { |
| case 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; |
| } |
| } |
| |
| break; |
| case KS_CONFIG_STRING: |
| doc = kshark_config_alloc(format); |
| break; |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| format); |
| return 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, otherwise NULL. 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, otherwise NULL. 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". |
| * |
| * @returns True on success, otherwise False. |
| */ |
| bool 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 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_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); |
| return false; |
| } |
| |
| free(val); |
| break; |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return false; |
| } |
| |
| return true; |
| |
| fail: |
| fprintf(stderr, "Failed to allocate memory for json_object.\n"); |
| json_object_put(jobj); |
| |
| return false; |
| } |
| |
| 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, otherwise 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 not_found; |
| |
| 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 not_found; |
| |
| 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); |
| return false; |
| } |
| |
| break; |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return false; |
| } |
| |
| return true; |
| |
| fail: |
| fprintf(stderr, "Failed to get config. document <%s>.\n", key); |
| |
| not_found: |
| return false; |
| } |
| |
| /** |
| * @brief Create an empty Record Configuration document. The type description |
| * is set to "kshark.config.record". |
| * |
| * @returns kshark_config_doc instance on success, otherwise NULL. 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.config.record", format); |
| } |
| |
| /** |
| * @brief Create an empty Data Stream Configuration document. The type |
| * description is set to "kshark.config.stream". |
| * |
| * @returns kshark_config_doc instance on success, otherwise NULL. Use |
| * kshark_free_config_doc() to free the object. |
| */ |
| struct kshark_config_doc * |
| kshark_stream_config_new(enum kshark_config_formats format) |
| { |
| return kshark_config_new("kshark.config.stream", format); |
| } |
| |
| /** |
| * @brief Create an empty Filter Configuration document. The type description |
| * is set to "kshark.config.filter". |
| * |
| * @returns kshark_config_doc instance on success, otherwise NULL. 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.config.filter", format); |
| } |
| |
| /** |
| * @brief Create an empty Session Configuration document. The type description |
| * is set to "kshark.config.filter". |
| * |
| * @returns kshark_config_doc instance on success, otherwise NULL. Use |
| * kshark_free_config_doc() to free the object. |
| */ |
| struct kshark_config_doc * |
| kshark_session_config_new(enum kshark_config_formats format) |
| { |
| return kshark_config_new("kshark.config.session", format); |
| } |
| |
| /** |
| * @brief Create an empty Text Configuration document. The Text Configuration |
| * documents do not use type descriptions. |
| * |
| * @returns kshark_config_doc instance on success, otherwise NULL. Use free() |
| * to free the object. |
| */ |
| struct kshark_config_doc *kshark_string_config_alloc(void) |
| { |
| 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.config.record" or |
| * "kshark.config.filter". |
| * |
| * @returns True, if the document has the expected type, otherwise 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, const char *name, |
| struct json_object *jobj) |
| { |
| struct json_object *jfile_name, *jbuffer_name, *jtime; |
| char abs_path[FILENAME_MAX]; |
| struct stat st; |
| |
| if (!file || !jobj) |
| return false; |
| |
| if (stat(file, &st) != 0) { |
| fprintf(stderr, "Unable to find file %s\n", file); |
| return false; |
| } |
| |
| if (!realpath(file, abs_path)) { |
| fprintf(stderr, "Unable to get absolute pathname for %s\n", |
| file); |
| return false; |
| } |
| |
| jfile_name = json_object_new_string(abs_path); |
| jbuffer_name = json_object_new_string(name); |
| 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, "name", jbuffer_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 name: The name of the data buffer. |
| * @param format: Input location for the Configuration format identifier. |
| * Currently only Json format is supported. |
| * |
| * @returns kshark_config_doc instance on success, otherwise NULL. Use |
| * kshark_free_config_doc() to free the object. |
| */ |
| struct kshark_config_doc * |
| kshark_export_trace_file(const char *file, const char *name, |
| enum kshark_config_formats format) |
| { |
| /* Create a new Configuration document. */ |
| struct kshark_config_doc *conf = |
| kshark_config_new("kshark.config.data", format); |
| |
| if (!conf) |
| return NULL; |
| |
| switch (format) { |
| case KS_CONFIG_JSON: |
| kshark_trace_file_to_json(file, name, 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, const char **name, |
| const char *type, |
| struct json_object *jobj) |
| { |
| struct json_object *jfile_name, *jbuffer_name, *jtime; |
| const char *file_str, *name_str; |
| struct stat st; |
| char *header; |
| int64_t time; |
| bool type_OK = true; |
| |
| if (!jobj) |
| return false; |
| |
| if (type) { |
| /* Make sure that the condition document has a correct type. */ |
| type_OK = false; |
| if (asprintf(&header, "kshark.config.%s", type) >= 0) |
| type_OK = kshark_json_type_check(jobj, header); |
| } |
| |
| if (!type_OK || |
| !json_object_object_get_ex(jobj, "file", &jfile_name) || |
| !json_object_object_get_ex(jobj, "name", &jbuffer_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); |
| name_str = json_object_get_string(jbuffer_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! (%" PRIu64 "!=%li)\nFile %s\n", |
| time, st.st_mtime, file_str); |
| return false; |
| } |
| |
| *file = file_str; |
| *name = name_str; |
| |
| return true; |
| } |
| |
| /* Quiet warnings over documenting simple structures */ |
| //! @cond Doxygen_Suppress |
| |
| #define TOP_BUFF_NAME "top buffer" |
| |
| //! @endcond |
| |
| /** |
| * @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 Id number of the data stream associated with the loaded file on |
| * success, otherwise -1. "conf" has the ownership over the returned |
| * string. |
| */ |
| int kshark_import_trace_file(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf) |
| { |
| const char *file = NULL, *name = NULL; |
| int sd = -1; |
| |
| switch (conf->format) { |
| case KS_CONFIG_JSON: |
| if (kshark_trace_file_from_json(&file, &name, "data", |
| conf->conf_doc)) { |
| if (strcmp(name, KS_UNNAMED) == 0 || |
| strcmp(name, TOP_BUFF_NAME) == 0) { |
| sd = kshark_open(kshark_ctx, file); |
| } else { |
| int sd_top; |
| |
| sd_top = kshark_tep_find_top_stream(kshark_ctx, |
| file); |
| if (sd_top < 0) { |
| /* |
| * The "top" steam (buffer) has to be |
| * initialized first. |
| */ |
| sd_top = kshark_open(kshark_ctx, file); |
| } |
| |
| if (sd_top >= 0) |
| sd = kshark_tep_open_buffer(kshark_ctx, |
| sd_top, |
| name); |
| |
| if (sd >= 0) |
| kshark_tep_handle_plugins(kshark_ctx, sd); |
| } |
| } |
| |
| break; |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| break; |
| } |
| |
| return sd; |
| } |
| |
| static bool kshark_plugin_to_json(struct kshark_plugin_list *plugin, |
| struct json_object *jobj) |
| { |
| struct json_object *jname = json_object_new_string(plugin->name); |
| |
| if (!kshark_trace_file_to_json(plugin->file, plugin->name, jobj) || |
| !jname) { |
| json_object_put(jname); |
| return false; |
| } |
| |
| json_object_object_add(jobj, "name", jname); |
| return true; |
| } |
| |
| /** |
| * @brief Record the name of a plugin's obj file and its timestamp into a |
| * Configuration document. |
| * |
| * @param plugin: The plugin to be expected. |
| * @param format: Input location for the Configuration format identifier. |
| * Currently only Json format is supported. |
| * |
| * @returns kshark_config_doc instance on success, otherwise NULL. Use |
| * kshark_free_config_doc() to free the object. |
| */ |
| struct kshark_config_doc * |
| kshark_export_plugin_file(struct kshark_plugin_list *plugin, |
| enum kshark_config_formats format) |
| { |
| /* Create a new Configuration document. */ |
| struct kshark_config_doc *conf = |
| kshark_config_new("kshark.config.library", format); |
| |
| if (!conf) |
| return NULL; |
| |
| switch (format) { |
| case KS_CONFIG_JSON: |
| kshark_plugin_to_json(plugin, conf->conf_doc); |
| return conf; |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return NULL; |
| } |
| } |
| |
| static bool kshark_all_plugins_to_json(struct kshark_context *kshark_ctx, |
| struct json_object *jobj) |
| { |
| struct kshark_plugin_list *plugin = kshark_ctx->plugins; |
| struct json_object *jfile, *jlist; |
| |
| jlist = json_object_new_array(); |
| if (!jlist) |
| return false; |
| |
| while (plugin) { |
| jfile = json_object_new_object(); |
| if (!kshark_trace_file_to_json(plugin->file, plugin->name, jfile)) |
| goto fail; |
| |
| json_object_array_add(jlist, jfile); |
| plugin = plugin->next; |
| } |
| |
| json_object_object_add(jobj, "obj. files", jlist); |
| |
| return true; |
| |
| fail: |
| fprintf(stderr, "Failed to allocate memory for json_object.\n"); |
| json_object_put(jobj); |
| json_object_put(jlist); |
| return false; |
| } |
| |
| /** |
| * @brief Record the current list of registered plugins into a |
| * Configuration document. |
| * |
| * @param kshark_ctx: Input location for session context pointer. |
| * @param format: Input location for the Configuration format identifier. |
| * Currently only Json format is supported. |
| * |
| * @returns kshark_config_doc instance on success, otherwise NULL. Use |
| * kshark_free_config_doc() to free the object. |
| */ |
| struct kshark_config_doc * |
| kshark_export_all_plugins(struct kshark_context *kshark_ctx, |
| enum kshark_config_formats format) |
| { |
| struct kshark_config_doc *conf = |
| kshark_config_new("kshark.config.plugins", KS_CONFIG_JSON); |
| |
| if (!conf) |
| return NULL; |
| |
| switch (format) { |
| case KS_CONFIG_JSON: |
| kshark_all_plugins_to_json(kshark_ctx, conf->conf_doc); |
| return conf; |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return NULL; |
| } |
| } |
| |
| static bool kshark_plugin_from_json(struct kshark_context *kshark_ctx, |
| struct json_object *jobj) |
| { |
| const char *file, *name; |
| |
| if (!kshark_trace_file_from_json(&file, &name, NULL, jobj)) { |
| fprintf(stderr, "Failed to import plugin!\n"); |
| return false; |
| } |
| |
| return !!(long) kshark_register_plugin(kshark_ctx, name, file); |
| } |
| |
| static bool kshark_all_plugins_from_json(struct kshark_context *kshark_ctx, |
| struct json_object *jobj) |
| { |
| struct json_object *jlist = NULL, *jfile = NULL; |
| int i, n_plugins; |
| |
| if (!kshark_ctx || !jobj) |
| return false; |
| |
| if (!kshark_json_type_check(jobj, "kshark.config.plugins") || |
| !json_object_object_get_ex(jobj, "obj. files", &jlist) || |
| json_object_get_type(jlist) != json_type_array) |
| goto fail; |
| |
| n_plugins = json_object_array_length(jlist); |
| for (i = 0; i < n_plugins; ++i) { |
| jfile = json_object_array_get_idx(jlist, i); |
| if (!jfile) |
| goto fail; |
| |
| kshark_plugin_from_json(kshark_ctx, jfile); |
| } |
| |
| return true; |
| |
| fail: |
| json_object_put(jfile); |
| json_object_put(jlist); |
| return false; |
| } |
| |
| /** |
| * @brief Load the list of registered plugins from 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. |
| * |
| * @returns True, if plugins have been loaded. If the configuration |
| * document contains no data or in a case of an error, the function |
| * returns False. |
| */ |
| bool kshark_import_all_plugins(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf) |
| { |
| switch (conf->format) { |
| case KS_CONFIG_JSON: |
| return kshark_all_plugins_from_json(kshark_ctx, |
| conf->conf_doc); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return false; |
| } |
| } |
| |
| static void kshark_stream_plugins_to_json(struct kshark_data_stream *stream, |
| struct json_object *jobj) |
| { |
| struct kshark_dpi_list *plugin = stream->plugins; |
| struct json_object *jlist, *jplg; |
| bool active; |
| |
| jlist = json_object_new_array(); |
| while (plugin) { |
| jplg = json_object_new_array(); |
| json_object_array_add(jplg, |
| json_object_new_string(plugin->interface->name)); |
| |
| active = plugin->status & KSHARK_PLUGIN_ENABLED; |
| json_object_array_add(jplg, json_object_new_boolean(active)); |
| |
| json_object_array_add(jlist, jplg); |
| |
| plugin = plugin->next; |
| } |
| |
| json_object_object_add(jobj, "registered", jlist); |
| } |
| |
| /** |
| * @brief Record the current list of plugins registered for a given Data |
| * stream into a Configuration document. |
| * |
| * @param stream: Input location for a Trace data stream pointer. |
| * @param format: Input location for the Configuration format identifier. |
| * Currently only Json format is supported. |
| * |
| * @returns kshark_config_doc instance on success, otherwise NULL. Use |
| * kshark_free_config_doc() to free the object. |
| */ |
| struct kshark_config_doc * |
| kshark_export_stream_plugins(struct kshark_data_stream *stream, |
| enum kshark_config_formats format) |
| { |
| struct kshark_config_doc *conf = |
| kshark_config_new("kshark.config.plugins", KS_CONFIG_JSON); |
| |
| if (!conf) |
| return NULL; |
| |
| switch (format) { |
| case KS_CONFIG_JSON: |
| kshark_stream_plugins_to_json(stream, conf->conf_doc); |
| return conf; |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return NULL; |
| } |
| } |
| |
| static bool kshark_stream_plugins_from_json(struct kshark_context *kshark_ctx, |
| struct kshark_data_stream *stream, |
| struct json_object *jobj) |
| { |
| struct json_object *jlist, *jplg, *jname, *jstatus; |
| struct kshark_plugin_list *plugin; |
| struct kshark_dpi_list *dpi_list; |
| struct kshark_dpi *dpi; |
| int i, n_plugins; |
| bool active; |
| |
| jlist = jplg = jname = jstatus = NULL; |
| |
| if (!kshark_ctx || !stream || !jobj) |
| return false; |
| |
| if (!kshark_json_type_check(jobj, "kshark.config.plugins") || |
| !json_object_object_get_ex(jobj, "registered", &jlist) || |
| json_object_get_type(jlist) != json_type_array) |
| goto fail; |
| |
| n_plugins = json_object_array_length(jlist); |
| for (i = 0; i < n_plugins; ++i) { |
| jplg = json_object_array_get_idx(jlist, i); |
| if (!jplg || |
| json_object_get_type(jplg) != json_type_array || |
| json_object_array_length(jplg) != 2) |
| goto fail; |
| |
| jname = json_object_array_get_idx(jplg, 0); |
| jstatus = json_object_array_get_idx(jplg, 1); |
| if (!jname || !jstatus) |
| goto fail; |
| |
| plugin = kshark_find_plugin_by_name(kshark_ctx->plugins, |
| json_object_get_string(jname)); |
| |
| if (plugin) { |
| active = json_object_get_boolean(jstatus); |
| dpi = plugin->process_interface; |
| dpi_list = kshark_register_plugin_to_stream(stream, dpi, |
| active); |
| |
| kshark_handle_dpi(stream, dpi_list, KSHARK_PLUGIN_INIT); |
| } |
| } |
| |
| return true; |
| |
| fail: |
| json_object_put(jplg); |
| json_object_put(jlist); |
| return false; |
| } |
| |
| /** |
| * @brief Load the list of registered plugins for a given Data |
| * stream from a Configuration document. |
| * |
| * @param kshark_ctx: Input location for session context pointer. |
| * @param stream: Input location for a Trace data stream pointer. |
| * @param conf: Input location for the kshark_config_doc instance. Currently |
| * only Json format is supported. |
| * |
| * @returns True, if plugins have been loaded. If the configuration |
| * document contains no data or in a case of an error, the function |
| * returns False. |
| */ |
| bool kshark_import_stream_plugins(struct kshark_context *kshark_ctx, |
| struct kshark_data_stream *stream, |
| struct kshark_config_doc *conf) |
| { |
| switch (conf->format) { |
| case KS_CONFIG_JSON: |
| return kshark_stream_plugins_from_json(kshark_ctx, stream, |
| conf->conf_doc); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return false; |
| } |
| } |
| |
| 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. |
| * |
| * @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 kshark_config_doc instance on success, otherwise NULL. Use |
| * free() to free the object. |
| */ |
| 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.config.model", format); |
| |
| if (!conf) |
| return NULL; |
| |
| 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.config.model") || |
| !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 kshark_data_stream *stream, |
| enum kshark_filter_type filter_type, |
| const char *filter_name, |
| struct json_object *jobj) |
| { |
| json_object *jfilter_data, *jname; |
| struct kshark_hash_id *filter; |
| char *name_str; |
| int i, *ids; |
| |
| filter = kshark_get_filter(stream, filter_type); |
| if (!filter) |
| return false; |
| |
| jname = NULL; |
| |
| /* |
| * 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 = kshark_hash_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) { |
| name_str = kshark_event_from_id(stream->stream_id, |
| ids[i]); |
| if (name_str) { |
| jname = json_object_new_string(name_str); |
| if (!jname) |
| goto fail; |
| |
| json_object_array_add(jfilter_data, jname); |
| } |
| } |
| |
| 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(jname); |
| free(ids); |
| |
| return false; |
| } |
| |
| /** |
| * @brief Record the current configuration of an Event Id filter into a |
| * Configuration document. |
| * |
| * @param stream: Input location for a Trace data stream pointer. |
| * @param filter_type: Identifier of the 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, otherwise False. |
| */ |
| bool kshark_export_event_filter(struct kshark_data_stream *stream, |
| enum kshark_filter_type filter_type, |
| const char *filter_name, |
| struct kshark_config_doc *conf) |
| { |
| switch (conf->format) { |
| case KS_CONFIG_JSON: |
| return kshark_event_filter_to_json(stream, filter_type, |
| filter_name, |
| conf->conf_doc); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return false; |
| } |
| } |
| |
| static int kshark_event_filter_from_json(struct kshark_data_stream *stream, |
| enum kshark_filter_type filter_type, |
| const char *filter_name, |
| struct json_object *jobj) |
| { |
| int i, length, event_id, count = 0; |
| struct kshark_hash_id *filter; |
| json_object *jfilter, *jevent; |
| const char *name_str; |
| |
| filter = kshark_get_filter(stream, filter_type); |
| if (!filter) |
| return 0; |
| |
| /* |
| * 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 0; |
| |
| if (!kshark_json_type_check(jobj, "kshark.config.filter") || |
| 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); |
| name_str = json_object_get_string(jevent); |
| event_id = kshark_find_event_id(stream, name_str); |
| if (event_id < 0) |
| continue; |
| |
| kshark_hash_id_add(filter, event_id); |
| count++; |
| } |
| |
| if (count != length) |
| count = -count; |
| |
| return count; |
| |
| fail: |
| fprintf(stderr, "Failed to load event filter from json_object.\n"); |
| kshark_hash_id_clear(filter); |
| return 0; |
| } |
| |
| /** |
| * @brief Load from Configuration document the configuration of an Event Id filter. |
| * |
| * @param stream: Input location for a Trace data stream pointer. |
| * @param filter_type: Identifier of the 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 The total number of events added to the filter. If not all events |
| * listed in the input configuration have been added successfully, |
| * the returned number is negative. |
| */ |
| int kshark_import_event_filter(struct kshark_data_stream *stream, |
| enum kshark_filter_type filter_type, |
| const char *filter_name, |
| struct kshark_config_doc *conf) |
| { |
| switch (conf->format) { |
| case KS_CONFIG_JSON: |
| return kshark_event_filter_from_json(stream, filter_type, |
| filter_name, |
| conf->conf_doc); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return 0; |
| } |
| } |
| |
| static bool kshark_filter_array_to_json(struct kshark_hash_id *filter, |
| const char *filter_name, |
| struct json_object *jobj) |
| { |
| json_object *jfilter_data, *jpid = NULL; |
| int i, *ids; |
| |
| /* |
| * 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 filtered. */ |
| ids = kshark_hash_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 simple 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, otherwise False. |
| */ |
| bool kshark_export_filter_array(struct kshark_hash_id *filter, |
| const char *filter_name, |
| struct kshark_config_doc *conf) |
| { |
| switch (conf->format) { |
| case KS_CONFIG_JSON: |
| return kshark_filter_array_to_json(filter, filter_name, |
| conf->conf_doc); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return false; |
| } |
| } |
| |
| static bool kshark_filter_array_from_json(struct kshark_hash_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.config.filter") || |
| 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; |
| |
| kshark_hash_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 simple |
| * 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_filter_array(struct kshark_hash_id *filter, |
| const char *filter_name, |
| struct kshark_config_doc *conf) |
| { |
| switch (conf->format) { |
| case KS_CONFIG_JSON: |
| return kshark_filter_array_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_data_stream *stream, |
| struct json_object *jobj) |
| { |
| json_object *jfilter_data, *jevent, *jname, *jfilter; |
| char *filter_str; |
| int *events, i; |
| |
| jevent = jname = jfilter = NULL; |
| |
| /* |
| * 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_tep_filter_is_set(stream)) |
| 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 = kshark_get_all_event_ids(stream); |
| if (!events) |
| return false; |
| |
| for (i = 0; i < stream->n_events; ++i) { |
| filter_str = kshark_tep_filter_make_string(stream, events[i]); |
| if (!filter_str) |
| continue; |
| |
| jevent = json_object_new_object(); |
| jname = json_object_new_string(kshark_event_from_id(stream->stream_id, |
| events[i])); |
| |
| jfilter = json_object_new_string(filter_str); |
| if (!jevent || !jname || !jfilter) |
| goto fail; |
| |
| 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(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 sd: Data stream identifier. |
| * @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, otherwise False. |
| */ |
| bool kshark_export_adv_filters(struct kshark_context *kshark_ctx, int sd, |
| struct kshark_config_doc **conf) |
| { |
| struct kshark_data_stream *stream = |
| kshark_get_data_stream(kshark_ctx, sd); |
| |
| if (!stream) |
| return false; |
| |
| if (!kshark_is_tep(stream)) { |
| /* Nothing to export. */ |
| return true; |
| } |
| |
| if (!*conf) |
| *conf = kshark_filter_config_new(KS_CONFIG_JSON); |
| |
| if (!*conf) |
| return false; |
| |
| switch ((*conf)->format) { |
| case KS_CONFIG_JSON: |
| return kshark_adv_filters_to_json(stream, |
| (*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_data_stream *stream, |
| struct json_object *jobj) |
| { |
| json_object *jfilter, *jname, *jcond; |
| int i, length, n, ret = 0; |
| char *filter_str = NULL; |
| |
| /* |
| * 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.config.filter") || |
| 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, "name", &jname) || |
| !json_object_object_get_ex(jfilter, "condition", &jcond)) |
| goto fail; |
| |
| n = asprintf(&filter_str, "%s:%s", |
| json_object_get_string(jname), |
| json_object_get_string(jcond)); |
| |
| if (n <= 0) { |
| filter_str = NULL; |
| goto fail; |
| } |
| |
| ret = kshark_tep_add_filter_str(stream, filter_str); |
| if (ret < 0) |
| goto fail; |
| } |
| |
| return true; |
| |
| fail: |
| fprintf(stderr, "Failed to laod Advanced filters.\n"); |
| |
| 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 sd: Data stream identifier. |
| * @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, int sd, |
| struct kshark_config_doc *conf) |
| { |
| struct kshark_data_stream *stream = |
| kshark_get_data_stream(kshark_ctx, sd); |
| |
| if (!stream) |
| return false; |
| |
| switch (conf->format) { |
| case KS_CONFIG_JSON: |
| return kshark_adv_filters_from_json(stream, |
| conf->conf_doc); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return false; |
| } |
| } |
| |
| static bool kshark_user_mask_to_json(struct kshark_context *kshark_ctx, |
| struct json_object *jobj) |
| { |
| json_object *jmask; |
| uint8_t mask; |
| |
| mask = kshark_ctx->filter_mask; |
| |
| jmask = json_object_new_int((int) mask); |
| if (!jmask) |
| return false; |
| |
| /* Add the mask to the filter config document. */ |
| json_object_object_add(jobj, KS_USER_FILTER_MASK_NAME, jmask); |
| return true; |
| } |
| |
| /** |
| * @brief Record the current value of the the user-specified filter mask 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, otherwise False. |
| */ |
| bool kshark_export_user_mask(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc **conf) |
| { |
| if (!*conf) |
| *conf = kshark_filter_config_new(KS_CONFIG_JSON); |
| |
| if (!*conf) |
| return false; |
| |
| switch ((*conf)->format) { |
| case KS_CONFIG_JSON: |
| return kshark_user_mask_to_json(kshark_ctx, (*conf)->conf_doc); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| (*conf)->format); |
| return false; |
| } |
| } |
| |
| static bool kshark_user_mask_from_json(struct kshark_context *kshark_ctx, |
| struct json_object *jobj) |
| { |
| json_object *jmask; |
| uint8_t mask; |
| |
| if (!kshark_json_type_check(jobj, "kshark.config.filter")) |
| return false; |
| /* |
| * Use the name of the filter to find the value of the filter maks. |
| * Notice that the filter config document may contain no data for |
| * the mask. |
| */ |
| if (!json_object_object_get_ex(jobj, KS_USER_FILTER_MASK_NAME, |
| &jmask)) |
| return false; |
| |
| mask = json_object_get_int(jmask); |
| kshark_ctx->filter_mask = mask; |
| |
| return true; |
| } |
| |
| /** |
| * @brief Load from Configuration document the value of the user-specified |
| * filter mask. |
| * |
| * @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 mask has been loaded. If the filter configuration |
| * document contains no data for the mask or in a case of an error, |
| * the function returns False. |
| */ |
| bool kshark_import_user_mask(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf) |
| { |
| switch (conf->format) { |
| case KS_CONFIG_JSON: |
| return kshark_user_mask_from_json(kshark_ctx, conf->conf_doc); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return false; |
| } |
| } |
| |
| static bool kshark_calib_array_from_json(struct kshark_context *kshark_ctx, |
| int sd, struct json_object *jobj) |
| { |
| json_object *jcalib_argv, *jcalib; |
| int64_t *calib_argv = NULL; |
| int i, calib_length; |
| |
| if (!json_object_object_get_ex(jobj, "calib. array", &jcalib_argv) || |
| json_object_get_type(jcalib_argv) != json_type_array) |
| return false; |
| |
| calib_length = json_object_array_length(jcalib_argv); |
| if (!calib_length) |
| return false; |
| |
| calib_argv = calloc(calib_length, sizeof(*calib_argv)); |
| for (i = 0; i < calib_length; ++i) { |
| jcalib = json_object_array_get_idx(jcalib_argv, i); |
| calib_argv[i] = json_object_get_int64(jcalib); |
| } |
| |
| kshark_ctx->stream[sd]->calib = kshark_offset_calib; |
| kshark_ctx->stream[sd]->calib_array = calib_argv; |
| kshark_ctx->stream[sd]->calib_array_size = calib_length; |
| |
| return true; |
| } |
| |
| /** |
| * @brief Load from Configuration document the value of the time calibration |
| * constants into a Configuration document. |
| * |
| * @param kshark_ctx: Input location for session context pointer. |
| * @param sd: Data stream identifier. |
| * @param conf: Input location for the kshark_config_doc instance. Currently |
| * only Json format is supported. If NULL, a new Configuration |
| * document will be created. |
| * |
| * @returns True on success, otherwise False. |
| */ |
| bool kshark_import_calib_array(struct kshark_context *kshark_ctx, int sd, |
| struct kshark_config_doc *conf) |
| { |
| switch (conf->format) { |
| case KS_CONFIG_JSON: |
| return kshark_calib_array_from_json(kshark_ctx, sd, conf->conf_doc); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return false; |
| } |
| } |
| |
| static bool kshark_calib_array_to_json(struct kshark_context *kshark_ctx, |
| int sd, struct json_object *jobj) |
| { |
| json_object *jval = NULL, *jcalib = NULL; |
| struct kshark_data_stream *stream; |
| |
| stream = kshark_get_data_stream(kshark_ctx, sd); |
| if (!stream || !stream->calib_array_size) |
| goto fail; |
| |
| jcalib = json_object_new_array(); |
| if (!jcalib) |
| goto fail; |
| |
| for (size_t i = 0; i < stream->calib_array_size; ++i) { |
| jval = json_object_new_int64(stream->calib_array[i]); |
| if (!jval) |
| goto fail; |
| |
| json_object_array_add(jcalib, jval); |
| } |
| |
| /* Add the mask to the filter config document. */ |
| json_object_object_add(jobj, "calib. array", jcalib); |
| |
| return true; |
| |
| fail: |
| json_object_put(jval); |
| json_object_put(jcalib); |
| |
| return false; |
| } |
| |
| /** |
| * @brief Record the current values of the time calibration constants into |
| * a Configuration document. |
| * |
| * @param kshark_ctx: Input location for session context pointer. |
| * @param sd: Data stream identifier. |
| * @param conf: Input location for the kshark_config_doc instance. Currently |
| * only Json format is supported. If NULL, a new Configuration |
| * document will be created. |
| * |
| * @returns True on success, otherwise False. |
| */ |
| bool kshark_export_calib_array(struct kshark_context *kshark_ctx, int sd, |
| struct kshark_config_doc **conf) |
| { |
| if (!*conf) |
| *conf = kshark_stream_config_new(KS_CONFIG_JSON); |
| |
| if (!*conf) |
| return false; |
| |
| switch ((*conf)->format) { |
| case KS_CONFIG_JSON: |
| return kshark_calib_array_to_json(kshark_ctx, sd, |
| (*conf)->conf_doc); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| (*conf)->format); |
| return false; |
| } |
| } |
| |
| /** |
| * @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 sd: Data stream identifier. |
| * @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, int sd, |
| struct kshark_config_doc **conf) |
| { |
| struct kshark_data_stream *stream = |
| kshark_get_data_stream(kshark_ctx, sd); |
| bool ret; |
| |
| if (!stream) |
| return false; |
| |
| if (!*conf) |
| *conf = kshark_filter_config_new(KS_CONFIG_JSON); |
| |
| if (!*conf) |
| return false; |
| |
| /* Save a filter only if it contains Id values. */ |
| ret = true; |
| if (kshark_this_filter_is_set(stream->show_event_filter)) |
| ret &= kshark_export_event_filter(stream, |
| KS_SHOW_EVENT_FILTER, |
| KS_SHOW_EVENT_FILTER_NAME, |
| *conf); |
| |
| if (kshark_this_filter_is_set(stream->hide_event_filter)) |
| ret &= kshark_export_event_filter(stream, |
| KS_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 sd: Data stream identifier. |
| * @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, int sd, |
| struct kshark_config_doc **conf) |
| { |
| struct kshark_data_stream *stream = |
| kshark_get_data_stream(kshark_ctx, sd); |
| bool ret; |
| |
| if (!stream) |
| return false; |
| |
| if (!*conf) |
| *conf = kshark_filter_config_new(KS_CONFIG_JSON); |
| |
| if (!*conf) |
| return false; |
| |
| /* Save a filter only if it contains Id values. */ |
| ret = true; |
| if (kshark_this_filter_is_set(stream->show_task_filter)) |
| ret &= kshark_export_filter_array(stream->show_task_filter, |
| KS_SHOW_TASK_FILTER_NAME, |
| *conf); |
| |
| if (kshark_this_filter_is_set(stream->hide_task_filter)) |
| ret &= kshark_export_filter_array(stream->hide_task_filter, |
| KS_HIDE_TASK_FILTER_NAME, |
| *conf); |
| |
| return ret; |
| } |
| |
| /** |
| * @brief Record the current configuration of "show cpu" and "hide cpu" |
| * filters into a Configuration document. |
| * |
| * @param kshark_ctx: Input location for session context pointer. |
| * @param sd: Data stream identifier. |
| * @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_cpu_filters(struct kshark_context *kshark_ctx, int sd, |
| struct kshark_config_doc **conf) |
| { |
| struct kshark_data_stream *stream = |
| kshark_get_data_stream(kshark_ctx, sd); |
| bool ret; |
| |
| if (!stream) |
| return false; |
| |
| if (!*conf) |
| *conf = kshark_filter_config_new(KS_CONFIG_JSON); |
| |
| if (!*conf) |
| return false; |
| |
| /* Save a filter only if it contains Id values. */ |
| ret = true; |
| if (kshark_this_filter_is_set(stream->show_cpu_filter)) |
| ret &= kshark_export_filter_array(stream->show_cpu_filter, |
| KS_SHOW_CPU_FILTER_NAME, |
| *conf); |
| |
| if (kshark_this_filter_is_set(stream->hide_cpu_filter)) |
| ret &= kshark_export_filter_array(stream->hide_cpu_filter, |
| KS_HIDE_CPU_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 sd: Data stream identifier. |
| * @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, int sd, |
| struct kshark_config_doc *conf) |
| { |
| struct kshark_data_stream *stream = |
| kshark_get_data_stream(kshark_ctx, sd); |
| bool ret = false; |
| |
| if (!stream) |
| return false; |
| |
| ret |= kshark_import_event_filter(stream, |
| KS_HIDE_EVENT_FILTER, |
| KS_HIDE_EVENT_FILTER_NAME, |
| conf); |
| |
| ret |= kshark_import_event_filter(stream, |
| KS_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 sd: Data stream identifier. |
| * @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, int sd, |
| struct kshark_config_doc *conf) |
| { |
| struct kshark_data_stream *stream = |
| kshark_get_data_stream(kshark_ctx, sd); |
| bool ret = false; |
| |
| if (!stream) |
| return false; |
| |
| ret |= kshark_import_filter_array(stream->hide_task_filter, |
| KS_HIDE_TASK_FILTER_NAME, |
| conf); |
| |
| ret |= kshark_import_filter_array(stream->show_task_filter, |
| KS_SHOW_TASK_FILTER_NAME, |
| conf); |
| |
| return ret; |
| } |
| |
| /** |
| * @brief Load from Configuration document the configuration of "show cpu" |
| * and "hide cpu" filters. |
| * |
| * @param kshark_ctx: Input location for session context pointer. |
| * @param sd: Data stream identifier. |
| * @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 cpu filter or in a case of an |
| * error, the function returns False. |
| */ |
| bool kshark_import_all_cpu_filters(struct kshark_context *kshark_ctx, int sd, |
| struct kshark_config_doc *conf) |
| { |
| struct kshark_data_stream *stream = |
| kshark_get_data_stream(kshark_ctx, sd); |
| bool ret = false; |
| |
| if (!stream) |
| return false; |
| |
| ret |= kshark_import_filter_array(stream->hide_cpu_filter, |
| KS_HIDE_CPU_FILTER_NAME, |
| conf); |
| |
| ret |= kshark_import_filter_array(stream->show_cpu_filter, |
| KS_SHOW_CPU_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 sd: Data stream identifier. |
| * @param format: Input location for the kshark_config_doc instance. Currently |
| * only Json format is supported. |
| * |
| * @returns kshark_config_doc instance on success, otherwise NULL. Use |
| * kshark_free_config_doc() to free the object. |
| */ |
| struct kshark_config_doc * |
| kshark_export_all_filters(struct kshark_context *kshark_ctx, int sd, |
| 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 (!conf || |
| !kshark_export_all_event_filters(kshark_ctx, sd, &conf) || |
| !kshark_export_all_task_filters(kshark_ctx, sd, &conf) || |
| !kshark_export_all_cpu_filters(kshark_ctx, sd, &conf) || |
| !kshark_export_user_mask(kshark_ctx, &conf) || |
| !kshark_export_adv_filters(kshark_ctx, sd, &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 sd: Data stream identifier. |
| * @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, int sd, |
| struct kshark_config_doc *conf) |
| { |
| bool ret; |
| |
| ret = kshark_import_all_task_filters(kshark_ctx, sd, conf); |
| ret |= kshark_import_all_cpu_filters(kshark_ctx, sd, conf); |
| ret |= kshark_import_all_event_filters(kshark_ctx, sd, conf); |
| ret |= kshark_import_user_mask(kshark_ctx, conf); |
| ret |= kshark_import_adv_filters(kshark_ctx, sd, conf); |
| |
| return ret; |
| } |
| |
| /** |
| * @brief Create a Data Stream Configuration document. |
| * |
| * @param kshark_ctx: Input location for session context pointer. |
| * @param sd: Data stream identifier. |
| * @param format: Input location for the kshark_config_doc instance. Currently |
| * only Json format is supported. |
| * |
| * @returns kshark_config_doc instance on success, otherwise NULL. Use |
| * kshark_free_config_doc() to free the object. |
| */ |
| struct kshark_config_doc * |
| kshark_export_dstream(struct kshark_context *kshark_ctx, int sd, |
| enum kshark_config_formats format) |
| { |
| struct kshark_config_doc *file_conf, *filter_conf, *sd_conf, *plg_conf; |
| struct kshark_config_doc *dstream_conf; |
| struct kshark_data_stream *stream; |
| |
| stream = kshark_get_data_stream(kshark_ctx, sd); |
| if (!stream) |
| return NULL; |
| |
| /* Create new Configuration documents. */ |
| dstream_conf = kshark_stream_config_new(format); |
| sd_conf = kshark_config_alloc(KS_CONFIG_JSON); |
| |
| sd_conf->conf_doc = json_object_new_int(sd); |
| |
| filter_conf = kshark_export_all_filters(kshark_ctx, sd, format); |
| |
| if (kshark_is_tep(stream) && kshark_tep_is_top_stream(stream)) |
| file_conf = kshark_export_trace_file(stream->file, |
| TOP_BUFF_NAME, |
| format); |
| else |
| file_conf = kshark_export_trace_file(stream->file, |
| stream->name, |
| format); |
| |
| plg_conf = kshark_export_stream_plugins(stream, format); |
| |
| if (!dstream_conf || |
| !sd_conf || |
| !filter_conf || |
| !file_conf || |
| !plg_conf) |
| goto fail; |
| |
| kshark_config_doc_add(dstream_conf, "stream id", sd_conf); |
| kshark_config_doc_add(dstream_conf, "data", file_conf); |
| kshark_config_doc_add(dstream_conf, "filters", filter_conf); |
| kshark_config_doc_add(dstream_conf, "plugins", plg_conf); |
| |
| if (stream->calib_array_size) |
| kshark_export_calib_array(kshark_ctx, sd, &dstream_conf); |
| |
| return dstream_conf; |
| |
| fail: |
| kshark_free_config_doc(dstream_conf); |
| kshark_free_config_doc(filter_conf); |
| kshark_free_config_doc(file_conf); |
| kshark_free_config_doc(plg_conf); |
| kshark_free_config_doc(sd_conf); |
| |
| return NULL; |
| } |
| |
| /** |
| * @brief Load Data Stream from 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. |
| * |
| * @returns The Stream Id on the loaded Data Stream on success, otherwise a |
| * negative error code. |
| */ |
| int kshark_import_dstream(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf) |
| { |
| struct kshark_config_doc *file_conf, *filter_conf, *plg_conf; |
| struct kshark_data_stream *stream; |
| bool ret = false; |
| int sd = -EFAULT; |
| |
| if (!kshark_type_check(conf, "kshark.config.stream")) |
| return sd; |
| |
| file_conf = kshark_config_alloc(KS_CONFIG_JSON); |
| filter_conf = kshark_config_alloc(KS_CONFIG_JSON); |
| plg_conf = kshark_config_alloc(KS_CONFIG_JSON); |
| if (!file_conf || !filter_conf || !plg_conf) { |
| fprintf(stderr, |
| "Failed to allocate memory for Json document.\n"); |
| goto free; |
| } |
| |
| if (kshark_config_doc_get(conf, "data", file_conf) && |
| kshark_config_doc_get(conf, "filters", filter_conf) && |
| kshark_config_doc_get(conf, "plugins", plg_conf)) { |
| sd = kshark_import_trace_file(kshark_ctx, file_conf); |
| if (sd < 0) { |
| fprintf(stderr, |
| "Failed to import data file form Json document.\n"); |
| goto free; |
| } |
| |
| stream = kshark_ctx->stream[sd]; |
| kshark_import_calib_array(kshark_ctx, sd, conf); |
| ret = kshark_import_all_filters(kshark_ctx, sd, |
| filter_conf); |
| if (!ret) { |
| fprintf(stderr, |
| "Failed to import filters form Json document.\n"); |
| kshark_close(kshark_ctx, sd); |
| sd = -EFAULT; |
| goto free; |
| } |
| |
| ret = kshark_import_stream_plugins(kshark_ctx, stream, plg_conf); |
| |
| if (!ret) { |
| fprintf(stderr, |
| "Failed to import stream plugins form Json document.\n"); |
| kshark_close(kshark_ctx, sd); |
| sd = -EFAULT; |
| goto free; |
| } |
| } |
| |
| free: |
| /* Free only the kshark_config_doc objects. */ |
| free(file_conf); |
| free(filter_conf); |
| free(plg_conf); |
| |
| return sd; |
| } |
| |
| static bool |
| kshark_export_all_dstreams_to_json(struct kshark_context *kshark_ctx, |
| struct json_object *jobj) |
| { |
| int *stream_ids = kshark_all_streams(kshark_ctx); |
| struct kshark_config_doc *dstream_conf; |
| struct json_object *jall_streams; |
| |
| json_del_if_exist(jobj, KS_DSTREAMS_NAME); |
| jall_streams = json_object_new_array(); |
| |
| for (int i = 0; i < kshark_ctx->n_streams; ++i) { |
| dstream_conf = kshark_export_dstream(kshark_ctx, stream_ids[i], |
| KS_CONFIG_JSON); |
| if (!dstream_conf) |
| goto fail; |
| |
| json_object_array_put_idx(jall_streams, i, dstream_conf->conf_doc); |
| |
| /* Free only the kshark_config_doc object. */ |
| free(dstream_conf); |
| } |
| |
| free(stream_ids); |
| |
| json_object_object_add(jobj, KS_DSTREAMS_NAME, jall_streams); |
| |
| return true; |
| |
| fail: |
| json_object_put(jall_streams); |
| free(stream_ids); |
| |
| return false; |
| } |
| |
| /** |
| * @brief Record the current configuration for all Data Streams 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 Configuration |
| * document will be created. |
| * |
| * @returns True on success, otherwise False. |
| */ |
| bool kshark_export_all_dstreams(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc **conf) |
| { |
| if (!*conf) |
| *conf = kshark_session_config_new(KS_CONFIG_JSON); |
| |
| if (!*conf) |
| return false; |
| |
| switch ((*conf)->format) { |
| case KS_CONFIG_JSON: |
| return kshark_export_all_dstreams_to_json(kshark_ctx, |
| (*conf)->conf_doc); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| (*conf)->format); |
| return false; |
| } |
| } |
| |
| static ssize_t |
| kshark_import_all_dstreams_from_json(struct kshark_context *kshark_ctx, |
| struct json_object *jobj, |
| struct kshark_entry ***data_rows) |
| { |
| struct kshark_config_doc dstream_conf; |
| json_object *jall_streams, *jstream; |
| int sd, i, length; |
| |
| if (!json_object_object_get_ex(jobj, KS_DSTREAMS_NAME, &jall_streams) || |
| json_object_get_type(jall_streams) != json_type_array) |
| return -EFAULT; |
| |
| length = json_object_array_length(jall_streams); |
| if (!length) |
| return -EFAULT; |
| |
| dstream_conf.format = KS_CONFIG_JSON; |
| for (i = 0; i < length; ++i) { |
| jstream = json_object_array_get_idx(jall_streams, i); |
| dstream_conf.conf_doc = jstream; |
| sd = kshark_import_dstream(kshark_ctx, &dstream_conf); |
| |
| if (sd < 0) |
| return -EFAULT; |
| } |
| |
| return kshark_load_all_entries(kshark_ctx, data_rows); |
| } |
| |
| /** |
| * @brief Load all Data Streams from 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. |
| * @param data_rows: Output location for the trace data. The user is |
| * responsible for freeing the elements of the outputted |
| * array. |
| * |
| * @returns The size of the outputted data in the case of success, or a |
| * negative error code on failure. |
| */ |
| ssize_t kshark_import_all_dstreams(struct kshark_context *kshark_ctx, |
| struct kshark_config_doc *conf, |
| struct kshark_entry ***data_rows) |
| { |
| switch (conf->format) { |
| case KS_CONFIG_JSON: |
| return kshark_import_all_dstreams_from_json(kshark_ctx, |
| conf->conf_doc, |
| data_rows); |
| |
| default: |
| fprintf(stderr, "Document format %d not supported\n", |
| conf->format); |
| return -EFAULT; |
| } |
| } |
| |
| 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, otherwise 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.config.record" or "kshark.config.filter". |
| * |
| * @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; |
| } |