* Vincent Attard ([email protected]) wrote:
> This new plugin prints a formated output of each events in a trace. The
> output format is defined as a parameter with printf like syntax.It provides
> a default format easy to read and the original textDump format for backward
> compatibility.
> 
> Signed-off-by: Vincent Attard <[email protected]>
> Reviewed-by: Yannick Brosseau <[email protected]>
> ---
>  lttv/modules/text/Makefile.am    |    3 +-
>  lttv/modules/text/formatedDump.c |  377 
> ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 379 insertions(+), 1 deletions(-)
>  create mode 100644 lttv/modules/text/formatedDump.c
> 
> diff --git a/lttv/modules/text/Makefile.am b/lttv/modules/text/Makefile.am
> index 29e8990..d95a4a0 100644
> --- a/lttv/modules/text/Makefile.am
> +++ b/lttv/modules/text/Makefile.am
> @@ -3,7 +3,7 @@ AM_LDFLAGS = $(MODULE_LDFLAGS)
>  
>  libdir = ${lttvplugindir}
>  
> -lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la libtextFilter.la 
> libprecomputeState.la libdepanalysis.la libsync_chain_batch.la
> +lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la libtextFilter.la 
> libprecomputeState.la libdepanalysis.la libsync_chain_batch.la 
> libformatedDump.la
>  
>  libtextDump_la_SOURCES = textDump.c
>  libbatchAnalysis_la_SOURCES = batchAnalysis.c
> @@ -11,6 +11,7 @@ libtextFilter_la_SOURCES = textFilter.c
>  libprecomputeState_la_SOURCES = precomputeState.c
>  libdepanalysis_la_SOURCES = depanalysis.c sstack.c
>  libsync_chain_batch_la_SOURCES = sync_chain_batch.c
> +libformatedDump_la_SOURCES = formatedDump.c
>  
>  noinst_HEADERS = \
>       batchanalysis.h \
> diff --git a/lttv/modules/text/formatedDump.c 
> b/lttv/modules/text/formatedDump.c
> new file mode 100644
> index 0000000..44f6589
> --- /dev/null
> +++ b/lttv/modules/text/formatedDump.c
> @@ -0,0 +1,377 @@
> +/* This file is part of the Linux Trace Toolkit viewer
> + * Copyright (C) 2003-2004 Michel Dagenais
> + *               2005 Mathieu Desnoyers
> + *               2011 Vincent Attard
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License Version 2 as
> + * published by the Free Software Foundation;
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, 
> + * MA 02111-1307, USA.
> + */
> +
> +/* Formated dump plugin prints a formated output of each events in a trace. 
> The
> + * output format is defined as a parameter. It provides a default format 
> easy to
> + * read and the original textDump format for backward compatibility.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#endif
> +
> +#include <lttv/lttv.h>
> +#include <lttv/option.h>
> +#include <lttv/module.h>
> +#include <lttv/hook.h>
> +#include <lttv/attribute.h>
> +#include <lttv/iattribute.h>
> +#include <lttv/stats.h>
> +#include <lttv/filter.h>
> +#include <lttv/print.h>
> +#include <ltt/ltt.h>
> +#include <ltt/event.h>
> +#include <ltt/trace.h>
> +#include <stdio.h>
> +#include <inttypes.h>
> +#include <string.h>
> +#include <stdlib.h>
> +
> +static gboolean
> +a_noevent,
> +a_no_field_names,
> +a_state,
> +a_text;
> +
> +static char
> +*a_file_name = NULL;
> +static char
> +*a_format = NULL;
> +
> +static LttvHooks
> +*before_traceset,
> +*event_hook;
> +
> +static char default_format[] =
> +             "tracefile:%f envent:%e timestamp:%t elapse:%l cpu:%c pid:%d 
> tgpid:%g "\
> +             "process:%p brand:%b ppid:%i state:%a";
> +
> +static char textDump_format[] =
> +             "%f.%e: %s.%n (%r/%f_%c), %d, %g, %p, %b, %i, %y, %a { %m }";
> +
> +static FILE *a_file;
> +
> +static GString *a_string;
> +
> +static gboolean open_output_file(void *hook_data, void *call_data)
> +{
> +  g_info("Open the output file");
> +
> +  if(a_file_name == NULL) a_file = stdout;
> +    else a_file = fopen(a_file_name, "w");
> +
> +     if(a_file == NULL) g_error("cannot open file %s", a_file_name);
> +      return FALSE;
> +}
> +
> +static int write_event_content(void *hook_data, void *call_data)
> +{
> +     gboolean result;
> +
> +     LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
> +
> +     LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
> +
> +     LttvTracefileState *tfs = (LttvTracefileState *)call_data;
> +
> +     LttEvent *e;
> +
> +     LttvAttributeValue value_filter;
> +
> +     LttvFilter *filter;
> +
> +     guint cpu = tfs->cpu;
> +     LttvTraceState *ts = (LttvTraceState*)tfc->t_context;
> +     LttvProcessState *process = ts->running_process[cpu];
> +
> +     if (a_noevent)
> +             return FALSE;
> +
> +     e = ltt_tracefile_get_event(tfc->tf);
> +
> +     result = lttv_iattribute_find_by_path(attributes, "filter/lttv_filter",
> +                     LTTV_POINTER, &value_filter);
> +     g_assert(result);
> +     filter = (LttvFilter*)*(value_filter.v_pointer);
> +
> +     /*
> +      * call to the filter if available
> +      */
> +     if(filter->head != NULL)
> +             if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
> +                             tfc->t_context->t,tfc,NULL,NULL))
> +                     return FALSE;
> +
> +     lttv_event_to_string(e, a_string, TRUE, !a_no_field_names, tfs);
> +
> +     if(a_state) {
> +             g_string_append_printf(a_string, "%s ",
> +                             g_quark_to_string(process->state->s));
> +     }
> +
> +
> +     g_string_append_printf(a_string,"\n");
> +
> +     fputs(a_string->str, a_file);
> +     return FALSE;
> +}
> +
> +void lttv_event_to_string(LttEvent *e, GString *s, gboolean mandatory_fields,
> +             gboolean field_names, LttvTracefileState *tfs)
> +{ 
> +     struct marker_field *field;
> +     struct marker_info *info;
> +     LttTime time;
> +     static LttTime time_prev = {0,0};
> +     LttTime elapse;
> +
> +
> +     guint cpu = tfs->cpu;
> +     LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
> +     LttvProcessState *process = ts->running_process[cpu];
> +
> +     s = g_string_set_size(s,0);
> +
> +     info = marker_get_info_from_id(tfs->parent.tf->mdata, e->event_id);
> +     if(mandatory_fields) {
> +             time = ltt_event_time(e);
> +     /* Calculate elapse between current and previous event time */
> +             if (time_prev.tv_sec==0 && time_prev.tv_nsec == 0) {
> +                     time_prev = ltt_event_time(e);
> +                     elapse.tv_sec = 0;
> +                     elapse.tv_nsec = 0;
> +             } else {
> +                     elapse = ltt_time_sub(time, time_prev);
> +                     time_prev = time;
> +             }
> +     }
> +
> +     char * fmt;
> +     int i;
> +     int fmt_len = 0;
> +     if(a_text) {
> +             /* textDump format (used with -T command option) */
> +             fmt = textDump_format;
> +             fmt_len = strlen(textDump_format);
> +     }
> +
> +     else if (!a_format) {
> +             /* Default format (used if no option) */
> +             fmt = default_format;
> +             fmt_len = strlen(default_format);
> +     } else {
> +             /* formatedDump format
> +              * (used with -F command option following by the desired 
> format) */
> +             fmt = a_format;
> +             fmt_len = strlen(a_format);
> +     }
> +
> +     char str[1024] = {0};
> +     /* Switch case:
> +      * all '%-' are replaced by the desired value in 'str' */
> +     char *str_pos = str;
> +     for (i = 0; i < strlen(fmt); i++){
> +             if (fmt[i] == '%'){
> +
> +                     switch (fmt[++i]){
> +                     case 't':
> +                             str_pos += sprintf(str_pos, 
> "%ldh%02ldm%02lds%09ldns",
> +                                             time.tv_sec/3600, 
> (time.tv_sec%3600)/60, time.tv_sec%60,
> +                                             time.tv_nsec);

is it me or this changes the timestamp output format compared to the
original textDump ?

Thanks,

Mathieu

> +                             break;
> +                     case 'f':
> +                             strcpy(str_pos,
> +                                             
> g_quark_to_string(ltt_tracefile_name(tfs->parent.tf)));
> +                             str_pos = str_pos + 
> strlen(g_quark_to_string(ltt_tracefile_name(tfs->parent.tf)));
> +                             break;
> +                     case 'e':
> +                             strcpy(str_pos,
> +                                             g_quark_to_string(info->name));
> +                             str_pos = str_pos + 
> strlen(g_quark_to_string(info->name));
> +                             break;
> +                     case 'd':
> +                             str_pos +=      sprintf(str_pos, "%u", 
> process->pid);
> +                             break;
> +                     case 's':
> +                             str_pos +=      sprintf(str_pos, "%lu", 
> time.tv_sec);
> +                             break;
> +                     case 'n':
> +                             str_pos +=      sprintf(str_pos, "%lu", 
> time.tv_nsec);
> +                             break;
> +                     case 'i':
> +                             str_pos +=      sprintf(str_pos, "%u", 
> process->ppid);
> +                             break;
> +                     case 'g':
> +                             str_pos +=      sprintf(str_pos, "%u", 
> process->tgid);
> +                             break;
> +                     case 'p':
> +                             
> strcpy(str_pos,g_quark_to_string(process->name));
> +                             str_pos = str_pos + 
> strlen(g_quark_to_string(process->name));
> +                             break;
> +                     case 'b':
> +                             
> strcpy(str_pos,g_quark_to_string(process->brand));
> +                             str_pos = str_pos + 
> strlen(g_quark_to_string(process->brand));
> +                             break;
> +                     case 'c':
> +                             str_pos += sprintf(str_pos,"%u", cpu);
> +                             break;
> +                     case 'l':
> +                             str_pos +=      sprintf(str_pos, "%lds%09ldns",
> +                                             elapse.tv_sec, elapse.tv_nsec);
> +                             break;
> +                     case 'a':
> +                             
> strcpy(str_pos,g_quark_to_string(process->state->t));
> +                             str_pos = str_pos + 
> strlen(g_quark_to_string(process->state->t));
> +                             break;
> +                     case 'm':
> +                             {
> +                                     GString *marker = g_string_new(0);
> +
> +                                     /* Get and print markers and 
> tracepoints fields into 'marker' */
> +                                     if(marker_get_num_fields(info) == 0) 
> return;
> +                                     for (field = marker_get_field(info, 0);
> +                                                     field != 
> marker_get_field(info, marker_get_num_fields(info));
> +                                                     field++) {
> +                                             if(field != 
> marker_get_field(info, 0)) {
> +                                                     
> g_string_append_printf(marker, ", ");
> +                                             }
> +                                             lttv_print_field(e, field, 
> marker, field_names, tfs);
> +
> +                                     }
> +                                     strcpy(str_pos,marker->str);
> +                                     str_pos = str_pos + marker->len;
> +                                     g_string_free(marker,0);
> +                             }
> +                             break;
> +                     case 'r':
> +                             strcpy(str_pos,g_quark_to_string(ltt_trace_name
> +                                              
> (ltt_tracefile_get_trace(tfs->parent.tf))));
> +                             str_pos = str_pos + 
> strlen(g_quark_to_string(ltt_trace_name
> +                                              
> (ltt_tracefile_get_trace(tfs->parent.tf))));
> +                             break;
> +                     case '%':
> +                             *str_pos = '%';
> +                             str_pos = str_pos + 1;
> +                             break;
> +                     case 'y':
> +                             str_pos +=      sprintf(str_pos, "0x%" PRIx64,
> +                                             process->current_function);
> +                             break;
> +
> +                     }
> +             }
> +             else
> +             {
> +                     /* Copy every character if not equals to '%' */
> +                     *str_pos = fmt[i];
> +                     str_pos++;
> +             }
> +     }
> +     *str_pos = '\0';
> +     g_string_append_printf(s, "%s", str);
> +}
> +
> +static void init()
> +{
> +     gboolean result;
> +
> +     LttvAttributeValue value;
> +
> +     LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
> +
> +     g_info("Init formatedDump.c");
> +
> +     a_string = g_string_new("");
> +
> +     a_file_name = NULL;
> +     lttv_option_add("output", 'o',
> +                     "output file where the text is written",
> +                     "file name",
> +                     LTTV_OPT_STRING, &a_file_name, NULL, NULL);
> +
> +     a_format= NULL;
> +     lttv_option_add("format", 'F',
> +                     "output the desired format\n\
> +                     FORMAT controls the output.  Interpreted sequences 
> are:\n\
> +                     \n\
> +                     %f   tracefile name\n\
> +                     %r   path to trace\n\
> +                     %e   event name\n\
> +                     %p   process name\n\
> +                     %t   timestamp  (e.g., 2h08m54s025684145ns)\n\
> +                     %s   seconds\n\
> +                     %n   nanoseconds\n\
> +                     %l   elapsed time with the previous event\n\
> +                     %d   pid\n\
> +                     %i   ppid\n\
> +                     %g   tgid\n\
> +                     %c   cpu\n\
> +                     %b   brand\n\
> +                     %a   state\n\
> +                     %m   markers and tracepoints fields\n",
> +                     "format string",
> +                     LTTV_OPT_STRING, &a_format, NULL, NULL);
> +
> +     a_text = FALSE;
> +     lttv_option_add("text", 'T',
> +                     "output the textDump format",
> +                     "",
> +                     LTTV_OPT_NONE, &a_text, NULL, NULL);
> +
> +     result = lttv_iattribute_find_by_path(attributes, "hooks/event",
> +                     LTTV_POINTER, &value);
> +     g_assert(result);
> +     event_hook = *(value.v_pointer);
> +     g_assert(event_hook);
> +     lttv_hooks_add(event_hook, write_event_content, NULL, 
> LTTV_PRIO_DEFAULT);
> +
> +     result = lttv_iattribute_find_by_path(attributes, 
> "hooks/traceset/before",
> +                     LTTV_POINTER, &value);
> +     g_assert(result);
> +     before_traceset = *(value.v_pointer);
> +     g_assert(before_traceset);
> +     lttv_hooks_add(before_traceset, open_output_file, NULL,
> +                     LTTV_PRIO_DEFAULT);
> +
> +}
> +
> +static void destroy()
> +{
> +     g_info("Destroy formatedDump");
> +
> +     lttv_option_remove("format");
> +
> +     lttv_option_remove("output");
> +
> +     lttv_option_remove("text");
> +
> +     g_string_free(a_string, TRUE);
> +
> +     lttv_hooks_remove_data(event_hook, write_event_content, NULL);
> +
> +     lttv_hooks_remove_data(before_traceset, open_output_file, NULL);
> +
> +}
> +
> +
> +LTTV_MODULE("formatedDump", "Print events with desired format in a file", \
> +             "Produce a detailed formated text printout of a trace", \
> +             init, destroy, "batchAnalysis", "option")
> +
> -- 
> 1.7.0.4
> 
> 
> _______________________________________________
> ltt-dev mailing list
> [email protected]
> http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev
> 

-- 
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com

_______________________________________________
ltt-dev mailing list
[email protected]
http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev

Reply via email to