Hi all,
On Thu, 16 Oct 2008 11:51:03 -0700 Darren Hart <[EMAIL PROTECTED]> wrote:
> Gilles Carry wrote:
> > From: gilles.carry <[EMAIL PROTECTED]>
> >
>
> Hi Gilles,
>
> > This patch is to allow user to have results and statistics dumped
> > as XML files.
> > This patch does not alter the LTP/RT traditional data dump.
> > A new global command line option is used: -x <id>
> > Using this option makes results to be dumped as XML files if the test
> > implements it.
> > Combining '-s -x' dumps stats both in traditionnal format and XML format
> > (into separate files).
> > The main goal here is to have the ability to store and compare results
> > and stats of testruns for different configurations and architectures.
> > The XML files created, not only store stats data but also system information
> > and timestamps, useful to identify how the test was run.
> > The choice of XML allows future format modifications while still being
> > able to compare old and new dumps.
>
> So certainly no objection to improving the flexibility of the data
> logging. However, here are a couple of points I think we should
> consider prior to incorporating the xml changes:
>
> o We should consider the LTP as a whole and see if there is some
> possibilty of an integrated output format.
> o If we add XML logging support I feel it should be self contained (not
> added in to libstats.
> o The test writer should not be required to explicitly print xml tags,
> I'd expact such a logger to be used something more like this:
>
> xml_element *xe = xml_log_init("matrix_mult")
> xml_element *se = xml_log_new_element(xe, "sequential")
> xml_log_add_stats(se, seq_dat) /* seq_dat is a stats_container_t * */
> xml_log_end_element(se)
> xml_element *ce = xml_log_new_element(xe, "concurrent")
> xml_log_add_stats(ce, con_dat)
> xml_log_close(xe)
>
> This will enable the xml lib to handle things like indentation, proper
> quoting of the CDATA elements, proper newlines (which should probably
> \r\n as these may be read/processed on non UNIX platforms, etc. And if
> we're going to go to this extreme, we would probably be best served by
> using an existing XML library. I've used the python framework, I
> suspect there is something similar for C. The build should be able to
> detect the availability of this lib and then build with xml or without
> accordingly.
>
> --
> Darren
While I'm not really fond of this xml thing (and all those meta languages as
well) wouldn't it be possible to do this in a post processing phase from the
raw stats data we already have.
That way we would not need any extra stuff running on the test box. I'm
particularly thinking of embedded hardware here, yes I know memory is getting
bigger by the day, but still I would rather do the minimum on the hardware we
want to test and defer post processing to more capable HW via scripts.
I may be working on big SMP boxes, but the embedded stuff is never far
away in my thoughts.
Sebastien.
>
>
>
>
> > ---
> > testcases/realtime/include/librttest.h | 1 +
> > testcases/realtime/include/libstats.h | 20 +++
> > testcases/realtime/lib/librttest.c | 33 +++++-
> > testcases/realtime/lib/libstats.c | 210
> > +++++++++++++++++++++++---------
> > 4 files changed, 208 insertions(+), 56 deletions(-)
> >
> > diff --git a/testcases/realtime/include/librttest.h
> > b/testcases/realtime/include/librttest.h
> > index bb30ee7..3c41046 100644
> > --- a/testcases/realtime/include/librttest.h
> > +++ b/testcases/realtime/include/librttest.h
> > @@ -131,6 +131,7 @@ extern char * _print_buffer;
> > extern int _print_buffer_offset;
> > extern int _dbg_lvl;
> > extern double pass_criteria;
> > +extern char testrun_start_time[200];
> >
> > /* function prototypes */
> >
> > diff --git a/testcases/realtime/include/libstats.h
> > b/testcases/realtime/include/libstats.h
> > index 05c26d8..abf9882 100644
> > --- a/testcases/realtime/include/libstats.h
> > +++ b/testcases/realtime/include/libstats.h
> > @@ -72,6 +72,9 @@ typedef struct stats_quantiles {
> > } stats_quantiles_t;
> >
> > extern int save_stats;
> > +extern int xml_dump;
> > +extern char *test_name;
> > +extern char *kernel_dev_id;
> >
> > /* function prototypes */
> >
> > @@ -162,4 +165,21 @@ void stats_hist_print(stats_container_t *hist);
> > */
> > int stats_container_save(char *filename, char *title, char *labelx, char
> > *labely, stats_container_t *data, char *mode);
> >
> > +/* xml_dump_init - create an xml dump file and add all necessary headers
> > + * or xml markups (start time, uname...) to identify the test
> > + * filename: the filename to save the data. File will actually be named:
> > + * <filename>.<timestamp>.xml
> > + * root_mrkup: the name of the root xml markup
> > + * title: the test title
> > + * Returns: the descriptor of the file to write into
> > + */
> > +FILE * xml_dump_init(char *filename, char *root_mrkup, char *title);
> > +
> > +/* xml_dump_close - add all necessary footer xml markups and close
> > + * the file.
> > + * dat_fd: the descriptor of the file to close
> > + * root_mrkup: the name of the root xml markup
> > + */
> > +void xml_dump_close(FILE *dat_fd, char *root_mrkup);
> > +
> > #endif /* LIBSTAT_H */
> > diff --git a/testcases/realtime/lib/librttest.c
> > b/testcases/realtime/lib/librttest.c
> > index c82fb95..61cb983 100644
> > --- a/testcases/realtime/lib/librttest.c
> > +++ b/testcases/realtime/lib/librttest.c
> > @@ -68,6 +68,7 @@ char * _print_buffer = NULL;
> > int _print_buffer_offset = 0;
> > int _dbg_lvl = 0;
> > double pass_criteria;
> > +char testrun_start_time[200];
> >
> > static int _use_pi = 1;
> >
> > @@ -79,9 +80,30 @@ void rt_help(void)
> > printf(" -p(0,1) 0:don't use pi mutexes, 1:use pi mutexes\n");
> > printf(" -v[0-4] 0:no debug, 1:DBG_ERR, 2:DBG_WARN, 3:DBG_INFO,
> > 4:DBG_DEBUG\n");
> > printf(" -s Enable saving stats data (default disabled)\n");
> > + printf(" -x <kernel_dev_id> Enable saving of stats as xml data
> > (default disabled)\n");
> > + printf(" kernel_dev_id (mandatory arg) string inserted
> > into xml dump\n");
> > printf(" -c Set pass criteria\n");
> > }
> >
> > +void set_start_time(void) {
> > + time_t t;
> > + struct tm *tmp;
> > +
> > + t = time(NULL);
> > + tmp = localtime(&t);
> > + if (tmp == NULL) {
> > + perror("localtime");
> > + exit(EXIT_FAILURE);
> > + }
> > +
> > + if (strftime(testrun_start_time, sizeof(testrun_start_time),
> > "%Y-%m-%d-%H-%M-%S", tmp) == 0) {
> > + fprintf(stderr, "strftime returned 0");
> > + exit(EXIT_FAILURE);
> > + }
> > +
> > + printf("Test start time:\"%s\"\n", testrun_start_time);
> > +}
> > +
> > int rt_init(const char *options, int (*parse_arg)(int option, char
> > *value), int argc, char *argv[])
> > {
> > int use_buffer = 1;
> > @@ -89,7 +111,7 @@ int rt_init(const char *options, int (*parse_arg)(int
> > option, char *value), int
> > int c;
> > opterr = 0;
> > char *all_options, *opt_ptr;
> > - static const char my_options[] = "b:p:v:sc:";
> > + static const char my_options[] = "b:p:v:sx:c:";
> >
> > if (options) {
> > opt_ptr = all_options = (char *)malloc(sizeof(my_options) +
> > strlen(options) + 1);
> > @@ -127,6 +149,12 @@ int rt_init(const char *options, int (*parse_arg)(int
> > option, char *value), int
> > case 's':
> > save_stats = 1;
> > break;
> > + case 'x':
> > + xml_dump = 1;
> > + kernel_dev_id = optarg;
> > + if (!strcmp("", kernel_dev_id))
> > + return -1;
> > + break;
> > default:
> > if (parse_arg) {
> > if (!parse_arg(c, optarg)) {
> > @@ -140,6 +168,9 @@ int rt_init(const char *options, int (*parse_arg)(int
> > option, char *value), int
> > if (use_buffer)
> > buffer_init();
> >
> > + /* Time stamp for stat files */
> > + set_start_time();
> > +
> > /*
> > * atexit() order matters here - buffer_print() will be called before
> > * buffer_fini().
> > diff --git a/testcases/realtime/lib/libstats.c
> > b/testcases/realtime/lib/libstats.c
> > index 29e7ea7..1cfad54 100644
> > --- a/testcases/realtime/lib/libstats.c
> > +++ b/testcases/realtime/lib/libstats.c
> > @@ -42,9 +42,14 @@
> > #include <errno.h>
> > #include <unistd.h>
> > #include <math.h>
> > +#include <sys/utsname.h>
> > #include <libstats.h>
> > +#include <librttest.h>
> >
> > int save_stats = 0;
> > +int xml_dump = 0;
> > +char *test_name = "";
> > +char *kernel_dev_id = "";
> >
> > /* static helper functions */
> > static int stats_record_compare(const void * a, const void * b) {
> > @@ -291,67 +296,162 @@ void stats_hist_print(stats_container_t *hist)
> > }
> > }
> >
> > -int stats_container_save(char *filename, char *title, char *xlabel, char
> > *ylabel, stats_container_t *data, char *mode)
> > +static int _stats_container_save(int xml, char *filename, char *title,
> > char *xlabel, char *ylabel, stats_container_t *data, char *mode)
> > {
> > - int i;
> > - int minx = 0, maxx = 0, miny = 0, maxy = 0;
> > - FILE *dat_fd;
> > - FILE *plt_fd;
> > - char *datfile;
> > - char *pltfile;
> > - stats_record_t *rec;
> > -
> > - if (!save_stats)
> > - return 0;
> > -
> > - /* generate the filenames */
> > - if (asprintf(&datfile, "%s.dat", filename) == -1) {
> > + int i;
> > + long minx = 0, maxx = 0, miny = 0, maxy = 0;
> > + FILE *dat_fd;
> > + FILE *plt_fd;
> > + char *datfile;
> > + char *pltfile;
> > + stats_record_t *rec;
> > + int rc;
> > +
> > + /* generate the filenames */
> > + if (xml)
> > + rc = asprintf(&datfile, "%s.%s.xml", filename,
> > testrun_start_time);
> > + else
> > + rc = asprintf(&datfile, "%s.dat", filename);
> > +
> > + if (rc == -1) {
> > fprintf(stderr, "Failed to allocate string for data
> > filename\n");
> > return -1;
> > }
> > - if (asprintf(&pltfile, "%s.plt", filename) == -1) {
> > +
> > + if (!xml && asprintf(&pltfile, "%s.plt", filename) == -1) {
> > fprintf(stderr, "Failed to allocate string for plot
> > filename\n");
> > return -1;
> > }
> >
> > - /* generate the data file */
> > - if (!(dat_fd = fopen(datfile, "w"))) {
> > - perror("Failed to open dat file");
> > - return -1;
> > - } else {
> > - minx = maxx = data->records[0].x;
> > - miny = maxy = data->records[0].y;
> > - for (i = 0; i < data->size; i++) {
> > - rec = &data->records[i];
> > - minx = MIN(minx, rec->x);
> > - maxx = MAX(maxx, rec->x);
> > - miny = MIN(miny, rec->y);
> > - maxy = MAX(maxy, rec->y);
> > - fprintf(dat_fd, "%ld %ld\n", rec->x, rec->y);
> > - }
> > - fclose(dat_fd);
> > - }
> > -
> > - /* generate the plt file */
> > - if (!(plt_fd = fopen(pltfile, "w"))) {
> > - perror("Failed to open plt file");
> > - return -1;
> > - } else {
> > - fprintf(plt_fd, "set terminal png\n");
> > - fprintf(plt_fd, "set output \"%s.png\"\n", pltfile);
> > - fprintf(plt_fd, "set title \"%s\"\n", title);
> > - fprintf(plt_fd, "set xlabel \"%s\"\n", xlabel);
> > - fprintf(plt_fd, "set ylabel \"%s\"\n", ylabel);
> > -
> > - // exact range mode
> > - //fprintf(plt_fd, "plot [%d:%d] [%d:%d] \"%s\" with %s\n",
> > - // minx, maxx, miny, maxy, datfile, mode);
> > -
> > - // expanded range mode - slightly more intuitive I think...
> > - fprintf(plt_fd, "plot [0:%d] [0:%d] \"%s\" with %s\n",
> > - maxx+1, maxy+1, datfile, mode);
> > - fclose(plt_fd);
> > - }
> > -
> > - return 0;
> > + /* generate the data file */
> > + if (xml)
> > + dat_fd = xml_dump_init(datfile, "ltp-sample", title);
> > + else
> > + dat_fd = fopen(datfile, "w");
> > +
> > + if (!dat_fd) {
> > + perror("Failed to open data file");
> > + return -1;
> > + }
> > +
> > + minx = maxx = data->records[0].x;
> > + miny = maxy = data->records[0].y;
> > + if (xml) {
> > + struct utsname u;
> > +
> > + uname(&u);
> > +
> > + fprintf(dat_fd, "<xlabel>%s</xlabel>\n",xlabel);
> > + fprintf(dat_fd, "<ylabel>%s</ylabel>\n",xlabel);
> > + fprintf(dat_fd, "<mode>%s</mode>\n",mode);
> > + fprintf(dat_fd, "<data>\n");
> > + }
> > + for (i = 0; i < data->size; i++) {
> > + rec = &data->records[i];
> > + minx = MIN(minx, rec->x);
> > + maxx = MAX(maxx, rec->x);
> > + miny = MIN(miny, rec->y);
> > + maxy = MAX(maxy, rec->y);
> > + if (xml)
> > + fprintf(dat_fd,
> > "\t<e><r>%d</r><x>%ld</x><y>%ld</y></e>\n", i, rec->x, rec->y);
> > + else
> > + fprintf(dat_fd, "%ld %ld\n", rec->x, rec->y);
> > + }
> > + if (xml) {
> > + fprintf(dat_fd, "</data>\n");
> > + fprintf(dat_fd, "<sample-size>%ld</sample-size>\n", data->size);
> > + fprintf(dat_fd, "<minx>%ld</minx>\n<maxx>%ld</maxx>\n", minx,
> > maxx);
> > + fprintf(dat_fd, "<miny>%ld</miny>\n<maxy>%ld</maxy>\n", miny,
> > maxy);
> > + xml_dump_close(dat_fd, "ltp-sample");
> > + return 0;
> > + }
> > +
> > +
> > + fclose(dat_fd);
> > +
> > +
> > + /* generate the plt file */
> > + if (!(plt_fd = fopen(pltfile, "w"))) {
> > + perror("Failed to open plt file");
> > + return -1;
> > + }
> > +
> > + fprintf(plt_fd, "set terminal png\n");
> > + fprintf(plt_fd, "set output \"%s.png\"\n", pltfile);
> > + fprintf(plt_fd, "set title \"%s\"\n", title);
> > + fprintf(plt_fd, "set xlabel \"%s\"\n", xlabel);
> > + fprintf(plt_fd, "set ylabel \"%s\"\n", ylabel);
> > +
> > + // exact range mode
> > + //fprintf(plt_fd, "plot [%d:%d] [%d:%d] \"%s\" with %s\n",
> > + // minx, maxx, miny, maxy, datfile, mode);
> > +
> > + // expanded range mode - slightly more intuitive I think...
> > + fprintf(plt_fd, "plot [0:%ld] [0:%ld] \"%s\" with %s\n",
> > + maxx+1, maxy+1, datfile, mode);
> > + fclose(plt_fd);
> > +
> > + return 0;
> > +}
> > +
> > +/*
> > + * Create XML dump file and initialise markup headers.
> > + * Does not close fd but returns it. fd is to be reused by subsequent
> > + * xml_dump... functions calls.
> > + */
> > +FILE * xml_dump_init(char *filename, char *root_mrkup, char *title)
> > +{
> > + FILE *dat_fd;
> > + struct utsname u;
> > + char *xmlfile;
> > +
> > + if (-1 == asprintf(&xmlfile, "%s.%s.xml", filename,
> > testrun_start_time)) {
> > + fprintf(stderr, "xml_dump_init: Failed to allocate string for
> > data filename\n");
> > + return NULL;
> > + }
> > +
> > + /* generate the data file */
> > + if (!(dat_fd = fopen(filename, "a+")))
> > + return NULL;
> > +
> > + uname(&u);
> > +
> > + fprintf(dat_fd, "<%s>\n", root_mrkup);
> > + fprintf(dat_fd, "<start-time>%s</start-time>\n",testrun_start_time);
> > + fprintf(dat_fd, "<uname>\n");
> > + fprintf(dat_fd, "\t<sysname>%s</sysname>\n",u.sysname);
> > + fprintf(dat_fd, "\t<nodename>%s</nodename>\n",u.nodename);
> > + fprintf(dat_fd, "\t<release>%s</release>\n",u.release);
> > + fprintf(dat_fd, "\t<version>%s</version>\n",u.version);
> > + fprintf(dat_fd, "\t<machine>%s</machine>\n",u.machine);
> > + fprintf(dat_fd, "</uname>\n");
> > + fprintf(dat_fd, "<kernel-dev-id>%s</kernel-dev-id>\n",kernel_dev_id);
> > + fprintf(dat_fd,
> > "<online-cpus>%ld</online-cpus>\n",sysconf(_SC_NPROCESSORS_ONLN));
> > + fprintf(dat_fd, "<testname>%s</testname>\n",test_name);
> > + fprintf(dat_fd, "<title>%s</title>\n",title);
> > +
> > + return dat_fd;
> > +}
> > +
> > +
> > +void xml_dump_close(FILE *dat_fd, char *root_mrkup)
> > +{
> > + fprintf(dat_fd, "</%s>\n", root_mrkup);
> > + fclose(dat_fd);
> > + return;
> > }
> > +
> > +int stats_container_save(char *filename, char *title, char *xlabel, char
> > *ylabel, stats_container_t *data, char *mode)
> > +{
> > + int rc = 0, rc_xml = 0;
> > +
> > + if (save_stats) {
> > + rc = _stats_container_save(0, filename, title, xlabel, ylabel,
> > data, mode);
> > + if (xml_dump)
> > + rc = _stats_container_save(1, filename, title, xlabel,
> > ylabel, data, mode);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +
>
>
> --
> Darren Hart
> IBM Linux Technology Center
> Real-Time Linux Team
>
>
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list