X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=plugins%2Ftext%2Ftext.c;h=44887b6fe11498470cac076f4d4deb9661a70318;hb=a263021c7b3cf7e563cb55b3985b46248320a545;hp=a318bfbf8b861580ce10ab2b4399ca05cf6c65d1;hpb=91e6e0b835e1a534c2e35929aed305255f0edf07;p=babeltrace.git diff --git a/plugins/text/text.c b/plugins/text/text.c index a318bfbf..44887b6f 100644 --- a/plugins/text/text.c +++ b/plugins/text/text.c @@ -4,6 +4,7 @@ * Babeltrace CTF Text Output Plugin * * Copyright 2016 Jérémie Galarneau + * Copyright 2016 Mathieu Desnoyers * * Author: Jérémie Galarneau * @@ -26,38 +27,56 @@ * SOFTWARE. */ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include "text.h" static -const char *loglevel_str [] = { - [LOGLEVEL_EMERG] = "TRACE_EMERG", - [LOGLEVEL_ALERT] = "TRACE_ALERT", - [LOGLEVEL_CRIT] = "TRACE_CRIT", - [LOGLEVEL_ERR] = "TRACE_ERR", - [LOGLEVEL_WARNING] = "TRACE_WARNING", - [LOGLEVEL_NOTICE] = "TRACE_NOTICE", - [LOGLEVEL_INFO] = "TRACE_INFO", - [LOGLEVEL_DEBUG_SYSTEM] = "TRACE_DEBUG_SYSTEM", - [LOGLEVEL_DEBUG_PROGRAM] = "TRACE_DEBUG_PROGRAM", - [LOGLEVEL_DEBUG_PROCESS] = "TRACE_DEBUG_PROCESS", - [LOGLEVEL_DEBUG_MODULE] = "TRACE_DEBUG_MODULE", - [LOGLEVEL_DEBUG_UNIT] = "TRACE_DEBUG_UNIT", - [LOGLEVEL_DEBUG_FUNCTION] = "TRACE_DEBUG_FUNCTION", - [LOGLEVEL_DEBUG_LINE] = "TRACE_DEBUG_LINE", - [LOGLEVEL_DEBUG] = "TRACE_DEBUG", +const char *plugin_options[] = { + "color", + "output-path", + "debug-info-dir", + "debug-info-target-prefix", + "debug-info-full-path", + "no-delta", + "clock-cycles", + "clock-seconds", + "clock-date", + "clock-gmt", + "verbose", + "name-default", /* show/hide */ + "name-payload", + "name-context", + "name-scope", + "name-header", + "field-default", /* show/hide */ + "field-trace", + "field-trace:hostname", + "field-trace:domain", + "field-trace:procname", + "field-trace:vpid", + "field-loglevel", + "field-emf", }; static void destroy_text_data(struct text_component *text) { + (void) g_string_free(text->string, TRUE); + g_free(text->options.output_path); + g_free(text->options.debug_info_dir); + g_free(text->options.debug_info_target_prefix); g_free(text); } @@ -70,11 +89,20 @@ struct text_component *create_text(void) if (!text) { goto end; } + text->string = g_string_new(""); + if (!text->string) { + goto error; + } end: return text; + +error: + g_free(text); + return NULL; } -static void destroy_text(struct bt_component *component) +static +void destroy_text(struct bt_component *component) { void *data = bt_component_get_private_data(component); @@ -82,11 +110,10 @@ static void destroy_text(struct bt_component *component) } static -enum bt_component_status handle_notification(struct bt_component *component, - struct bt_notification *notification) +enum bt_component_status handle_notification(struct text_component *text, + struct bt_notification *notification) { enum bt_component_status ret = BT_COMPONENT_STATUS_OK; - struct text_component *text = bt_component_get_private_data(component); if (!text) { ret = BT_COMPONENT_STATUS_ERROR; @@ -94,7 +121,7 @@ enum bt_component_status handle_notification(struct bt_component *component, } switch (bt_notification_get_type(notification)) { - case BT_NOTIFICATION_TYPE_PACKET_START: + case BT_NOTIFICATION_TYPE_PACKET_BEGIN: puts(""); break; case BT_NOTIFICATION_TYPE_PACKET_END: @@ -110,6 +137,7 @@ enum bt_component_status handle_notification(struct bt_component *component, goto end; } ret = text_print_event(text, event); + bt_put(event); if (ret != BT_COMPONENT_STATUS_OK) { goto end; } @@ -125,9 +153,522 @@ end: return ret; } +static +enum bt_component_status run(struct bt_component *component) +{ + enum bt_component_status ret; + struct bt_notification *notification = NULL; + struct bt_notification_iterator *it; + struct text_component *text = bt_component_get_private_data(component); + + ret = bt_component_sink_get_input_iterator(component, 0, &it); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + if (likely(text->processed_first_event)) { + enum bt_notification_iterator_status it_ret; + + it_ret = bt_notification_iterator_next(it); + switch (it_ret) { + case BT_NOTIFICATION_ITERATOR_STATUS_ERROR: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + case BT_NOTIFICATION_ITERATOR_STATUS_END: + ret = BT_COMPONENT_STATUS_END; + goto end; + default: + break; + } + } + notification = bt_notification_iterator_get_notification(it); + if (!notification) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + ret = handle_notification(text, notification); + text->processed_first_event = true; +end: + bt_put(it); + bt_put(notification); + return ret; +} + +static +enum bt_component_status add_params_to_map(struct bt_value *plugin_opt_map) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + unsigned int i; + + for (i = 0; i < BT_ARRAY_SIZE(plugin_options); i++) { + const char *key = plugin_options[i]; + enum bt_value_status status; + + status = bt_value_map_insert(plugin_opt_map, key, bt_value_null); + switch (status) { + case BT_VALUE_STATUS_OK: + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + } +end: + return ret; +} + +static +bool check_param_exists(const char *key, struct bt_value *object, void *data) +{ + struct text_component *text = data; + struct bt_value *plugin_opt_map = text->plugin_opt_map; + + if (!bt_value_map_get(plugin_opt_map, key)) { + fprintf(text->err, + "[warning] Parameter \"%s\" unknown to \"text\" plugin\n", key); + } + return true; +} + +static +enum bt_component_status apply_one_string(const char *key, + struct bt_value *params, + char **option) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_value *value = NULL; + enum bt_value_status status; + const char *str; + + value = bt_value_map_get(params, key); + if (!value) { + goto end; + } + if (bt_value_is_null(value)) { + goto end; + } + status = bt_value_string_get(value, &str); + switch (status) { + case BT_VALUE_STATUS_OK: + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + *option = g_strdup(str); +end: + bt_put(value); + return ret; +} + +static +enum bt_component_status apply_one_bool(const char *key, + struct bt_value *params, + bool *option, + bool *found) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + struct bt_value *value = NULL; + enum bt_value_status status; + + value = bt_value_map_get(params, key); + if (!value) { + goto end; + } + status = bt_value_bool_get(value, option); + switch (status) { + case BT_VALUE_STATUS_OK: + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (found) { + *found = true; + } +end: + bt_put(value); + return ret; +} + +static +void warn_wrong_color_param(struct text_component *text) +{ + fprintf(text->err, + "[warning] Accepted values for the \"color\" parameter are:\n \"always\", \"auto\", \"never\"\n"); +} + +static +enum bt_component_status apply_params(struct text_component *text, + struct bt_value *params) +{ + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; + enum bt_value_status status; + bool value, found; + char *str = NULL; + + text->plugin_opt_map = bt_value_map_create(); + if (!text->plugin_opt_map) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + ret = add_params_to_map(text->plugin_opt_map); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + /* Report unknown parameters. */ + status = bt_value_map_foreach(params, check_param_exists, text); + switch (status) { + case BT_VALUE_STATUS_OK: + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + /* Known parameters. */ + text->options.color = TEXT_COLOR_OPT_AUTO; + if (bt_value_map_has_key(params, "color")) { + struct bt_value *color_value; + const char *color; + + color_value = bt_value_map_get(params, "color"); + if (!color_value) { + goto end; + } + + ret = bt_value_string_get(color_value, &color); + if (ret) { + warn_wrong_color_param(text); + } else { + if (strcmp(color, "never") == 0) { + text->options.color = TEXT_COLOR_OPT_NEVER; + } else if (strcmp(color, "auto") == 0) { + text->options.color = TEXT_COLOR_OPT_AUTO; + } else if (strcmp(color, "always") == 0) { + text->options.color = TEXT_COLOR_OPT_ALWAYS; + } else { + warn_wrong_color_param(text); + } + } + + bt_put(color_value); + } + + ret = apply_one_string("output-path", + params, + &text->options.output_path); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + ret = apply_one_string("debug-info-dir", + params, + &text->options.debug_info_dir); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + ret = apply_one_string("debug-info-target-prefix", + params, + &text->options.debug_info_target_prefix); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + value = false; /* Default. */ + ret = apply_one_bool("debug-info-full-path", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + text->options.debug_info_full_path = value; + + value = false; /* Default. */ + ret = apply_one_bool("no-delta", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + text->options.print_delta_field = !value; /* Reverse logic. */ + + value = false; /* Default. */ + ret = apply_one_bool("clock-cycles", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + text->options.print_timestamp_cycles = value; + + value = false; /* Default. */ + ret = apply_one_bool("clock-seconds", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + text->options.clock_seconds = value; + + value = false; /* Default. */ + ret = apply_one_bool("clock-date", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + text->options.clock_date = value; + + value = false; /* Default. */ + ret = apply_one_bool("clock-gmt", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + text->options.clock_gmt = value; + + value = false; /* Default. */ + ret = apply_one_bool("verbose", params, &value, NULL); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + text->options.verbose = value; + + /* Names. */ + ret = apply_one_string("name-default", params, &str); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (!str) { + text->options.name_default = TEXT_DEFAULT_UNSET; + } else if (!strcmp(str, "show")) { + text->options.name_default = TEXT_DEFAULT_SHOW; + } else if (!strcmp(str, "hide")) { + text->options.name_default = TEXT_DEFAULT_HIDE; + } else { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + g_free(str); + str = NULL; + + switch (text->options.name_default) { + case TEXT_DEFAULT_UNSET: + text->options.print_payload_field_names = true; + text->options.print_context_field_names = true; + text->options.print_header_field_names = false; + text->options.print_scope_field_names = false; + break; + case TEXT_DEFAULT_SHOW: + text->options.print_payload_field_names = true; + text->options.print_context_field_names = true; + text->options.print_header_field_names = true; + text->options.print_scope_field_names = true; + break; + case TEXT_DEFAULT_HIDE: + text->options.print_payload_field_names = false; + text->options.print_context_field_names = false; + text->options.print_header_field_names = false; + text->options.print_scope_field_names = false; + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + value = false; + found = false; + ret = apply_one_bool("name-payload", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_payload_field_names = value; + } + + value = false; + found = false; + ret = apply_one_bool("name-context", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_context_field_names = value; + } + + value = false; + found = false; + ret = apply_one_bool("name-header", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_header_field_names = value; + } + + value = false; + found = false; + ret = apply_one_bool("name-scope", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_scope_field_names = value; + } + + /* Fields. */ + ret = apply_one_string("field-default", params, &str); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (!str) { + text->options.field_default = TEXT_DEFAULT_UNSET; + } else if (!strcmp(str, "show")) { + text->options.field_default = TEXT_DEFAULT_SHOW; + } else if (!strcmp(str, "hide")) { + text->options.field_default = TEXT_DEFAULT_HIDE; + } else { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + g_free(str); + str = NULL; + + switch (text->options.field_default) { + case TEXT_DEFAULT_UNSET: + text->options.print_trace_field = false; + text->options.print_trace_hostname_field = true; + text->options.print_trace_domain_field = false; + text->options.print_trace_procname_field = true; + text->options.print_trace_vpid_field = true; + text->options.print_loglevel_field = false; + text->options.print_emf_field = false; + text->options.print_emf_field = false; + break; + case TEXT_DEFAULT_SHOW: + text->options.print_trace_field = true; + text->options.print_trace_hostname_field = true; + text->options.print_trace_domain_field = true; + text->options.print_trace_procname_field = true; + text->options.print_trace_vpid_field = true; + text->options.print_loglevel_field = true; + text->options.print_emf_field = true; + text->options.print_emf_field = true; + break; + case TEXT_DEFAULT_HIDE: + text->options.print_trace_field = false; + text->options.print_trace_hostname_field = false; + text->options.print_trace_domain_field = false; + text->options.print_trace_procname_field = false; + text->options.print_trace_vpid_field = false; + text->options.print_loglevel_field = false; + text->options.print_emf_field = false; + text->options.print_emf_field = false; + break; + default: + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + + value = false; + found = false; + ret = apply_one_bool("field-trace", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_trace_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-trace:hostname", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_trace_hostname_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-trace:domain", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_trace_domain_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-trace:procname", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_trace_procname_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-trace:vpid", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_trace_vpid_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-loglevel", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_loglevel_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-emf", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_emf_field = value; + } + + value = false; + found = false; + ret = apply_one_bool("field-emf", params, &value, &found); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + if (found) { + text->options.print_emf_field = value; + } + +end: + bt_put(text->plugin_opt_map); + text->plugin_opt_map = NULL; + g_free(str); + return ret; +} + +static +void set_use_colors(struct text_component *text) +{ + switch (text->options.color) { + case TEXT_COLOR_OPT_ALWAYS: + text->use_colors = true; + break; + case TEXT_COLOR_OPT_AUTO: + text->use_colors = text->out == stdout && + bt_common_colors_supported(); + break; + case TEXT_COLOR_OPT_NEVER: + text->use_colors = false; + break; + } +} + static enum bt_component_status text_component_init( - struct bt_component *component, struct bt_value *params) + struct bt_component *component, struct bt_value *params, + UNUSED_VAR void *init_method_data) { enum bt_component_status ret; struct text_component *text = create_text(); @@ -137,25 +678,26 @@ enum bt_component_status text_component_init( goto end; } - ret = bt_component_set_destroy_cb(component, - destroy_text); - if (ret != BT_COMPONENT_STATUS_OK) { - goto error; - } + text->out = stdout; + text->err = stderr; - ret = bt_component_set_private_data(component, text); + text->delta_cycles = -1ULL; + text->last_cycles_timestamp = -1ULL; + + text->delta_real_timestamp = -1ULL; + text->last_real_timestamp = -1ULL; + + ret = apply_params(text, params); if (ret != BT_COMPONENT_STATUS_OK) { goto error; } - ret = bt_component_sink_set_handle_notification_cb(component, - handle_notification); + set_use_colors(text); + + ret = bt_component_set_private_data(component, text); if (ret != BT_COMPONENT_STATUS_OK) { goto error; } - - text->out = stdout; - text->err = stderr; end: return ret; error: @@ -164,13 +706,13 @@ error: } /* Initialize plug-in entry points. */ -BT_PLUGIN_NAME("text"); +BT_PLUGIN(text); BT_PLUGIN_DESCRIPTION("Babeltrace text output plug-in."); BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); +BT_PLUGIN_SINK_COMPONENT_CLASS(text, run); +BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(text, text_component_init); +BT_PLUGIN_SINK_COMPONENT_CLASS_DESTROY_METHOD(text, destroy_text); +BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(text, + "Formats CTF-IR to text. Formerly known as ctf-text."); -BT_PLUGIN_COMPONENT_CLASSES_BEGIN -BT_PLUGIN_SINK_COMPONENT_CLASS_ENTRY("text", - "Formats CTF-IR to text. Formerly known as ctf-text.", - text_component_init) -BT_PLUGIN_COMPONENT_CLASSES_END