From 3d18ee134f5ac6215035a1f2cc3729867a6292c0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jan=20Posp=C3=AD=C5=A1il?= Date: Sun, 11 May 2008 18:37:36 +0000 Subject: [PATCH] - full support of all version 2 attributes (attr2) - the code is generated - attrs2 now default, version 1 attributes available by -1 option - fix for bug #21085 - corrected XML escaping in XML structured attributes (added dependency on org.glite.lbjp-common.trio) - added several messages to the verbose mode --- org.glite.lb.utils/Makefile | 18 ++- org.glite.lb.utils/src/process_attrs.c | 220 +++++++++++++++++++++++++++ org.glite.lb.utils/src/process_attrs2.c.T | 85 +++++++++++ org.glite.lb.utils/src/statistics.c | 240 ++++-------------------------- 4 files changed, 347 insertions(+), 216 deletions(-) create mode 100644 org.glite.lb.utils/src/process_attrs.c create mode 100644 org.glite.lb.utils/src/process_attrs2.c.T diff --git a/org.glite.lb.utils/Makefile b/org.glite.lb.utils/Makefile index 299b3b7..e4e98d5 100644 --- a/org.glite.lb.utils/Makefile +++ b/org.glite.lb.utils/Makefile @@ -20,7 +20,12 @@ version=${module.version} VPATH=${top_srcdir}/src:${top_srcdir}/doc CC=gcc +AT3=${stagedir}/sbin/glite-lb-at3 + +SUFFIXES = .T + DEBUG:=-g -O0 -Wall + CFLAGS:= \ ${WS_CFLAGS} ${DEBUG} \ -DVERSION=\"${version}\" \ @@ -51,6 +56,7 @@ CLIENT_LIB:=-lglite_lb_client_${nothrflavour} JP_LIBS:=-lglite_jp_common_${nothrflavour} UTILS:=mon purge dump load dump_exporter +STATISTICS_OBJS:=statistics.o process_attrs.o process_attrs2.o MAN_GZ:=glite-lb-mon.1.gz MAN = $(MAN_GZ:.gz=) @@ -60,14 +66,11 @@ default: all compile all: ${UTILS} ${MAN_GZ} statistics -%.o: %.c - ${CC} ${CFLAGS} -c $< - ${UTILS}: %: %.o ${LINK} -o $@ $< ${COMMON_LIB} ${CLIENT_LIB} ${EXT_LIBS} -lglite_lbu_maildir -statistics: statistics.o - ${LINK} -rdynamic -o $@ $< ${COMMON_LIB} ${JP_LIBS} ${EXT_LIBS} +statistics: ${STATISTICS_OBJS} + ${LINK} -rdynamic -o $@ ${STATISTICS_OBJS} ${COMMON_LIB} ${JP_LIBS} ${EXT_LIBS} check: compile @@ -101,3 +104,8 @@ clean: %.o: %.c ${COMPILE} -c $< +%.c: %.c.T + rm -f $@ + ${AT3} $< >$@ || rm -f $@ + chmod -w $@ >/dev/null + diff --git a/org.glite.lb.utils/src/process_attrs.c b/org.glite.lb.utils/src/process_attrs.c new file mode 100644 index 0000000..9b03c46 --- /dev/null +++ b/org.glite.lb.utils/src/process_attrs.c @@ -0,0 +1,220 @@ +#include +#include +#include + +#include "glite/lbu/trio.h" + +#include "glite/jp/types.h" +#include "glite/jp/context.h" +#include "glite/jp/file_plugin.h" +#include "glite/jp/attr.h" +#include "glite/lb/job_attrs.h" + +/* + * free the array of JP attr + */ +static void free_attrs(glite_jp_attrval_t *av) { + glite_jp_attrval_t *item; + + item = av; + while (item->name) { + glite_jp_attrval_free(item++, 0); + } + free(av); +} + +/* + * process attributes + */ +void process_attrs(glite_jp_context_t jpctx, glite_jpps_fplug_data_t plugin_data, void *data_handle, FILE *outfile) { + + glite_jp_attrval_t *attrval; + + /*
*/ + trio_fprintf(outfile,"\n\n"); + trio_fprintf(outfile,"value); + free_attrs(attrval); + } else { + trio_fprintf(outfile,"jobid=\"default\"\n"); + } + trio_fprintf(outfile,">\n"); + /*
*/ + + /* */ + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_user, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_parent, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_VO, &attrval); + if (attrval) { + trio_fprintf(stdout,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_aTag, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_rQType, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_eDuration, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_eNodes, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_eProc, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_RB, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_CE, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_host, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_UIHost, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_CPUTime, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_NProc, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_finalStatus, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_finalDoneStatus, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_finalStatusDate, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_finalStatusReason, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_LRMSDoneStatus, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_LRMSStatusReason, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_retryCount, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_additionalReason, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_jobType, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_nsubjobs, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_subjobs, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_lastStatusHistory, &attrval); + if (attrval) { + trio_fprintf(outfile,"%s\n",attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_fullStatusHistory, &attrval); + if (attrval) { + trio_fprintf(outfile,"%s\n",attrval->value); + free_attrs(attrval); + } + + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_JDL, &attrval); + if (attrval) { + trio_fprintf(outfile,"%|Xs\n", attrval->value); + free_attrs(attrval); + } + + /* */ + + trio_fprintf(outfile,"\n\n"); +} diff --git a/org.glite.lb.utils/src/process_attrs2.c.T b/org.glite.lb.utils/src/process_attrs2.c.T new file mode 100644 index 0000000..3467d29 --- /dev/null +++ b/org.glite.lb.utils/src/process_attrs2.c.T @@ -0,0 +1,85 @@ +#ident "$Header$" +/* +@@@AUTO +*/ +@@@LANG: C + +#include +#include +#include + +#include "glite/lbu/trio.h" + +#include "glite/jp/types.h" +#include "glite/jp/context.h" +#include "glite/jp/file_plugin.h" +#include "glite/jp/attr.h" +#include "glite/lb/job_attrs2.h" + +/* + * free the array of JP attr + */ +static void free_attrs(glite_jp_attrval_t *av) { + glite_jp_attrval_t *item; + + item = av; + while (item->name) { + glite_jp_attrval_free(item++, 0); + } + free(av); +} + +/* + * process attributes + */ +void process_attrs2(glite_jp_context_t jpctx, glite_jpps_fplug_data_t plugin_data, void *data_handle, FILE *outfile) { + + glite_jp_attrval_t *attrval; + + /*
*/ + fprintf(outfile,"\n\n"); + fprintf(outfile,"value); + free_attrs(attrval); + } else { + fprintf(outfile,"jobid=\"default\"\n"); + } + fprintf(outfile,">\n"); + /*
*/ + + /* */ +@@@{ +# elems + for my $n ($status->getAllFieldsOrdered) { + my $f = selectField $status $n; +# my $type = getType $f; + my $type = $f->{type}; + my $name = getName $f; + +# $type = 'jobtypeType' if $name eq 'jobtype'; + + @ln = split /_/,$name; + my $un = shift @ln; $un .= ucfirst shift @ln while (@ln); + my $c = getComment $f; + my $strformat = "%s"; + if ($type eq 'string') { $strformat = "%|Xs"; } + + gen qq{ + /** $c */ + plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_$un, &attrval); + if (attrval) { + trio_fprintf(outfile,"<$un>$strformat\\n", attrval->value); + free_attrs(attrval); + } +}; + + } +@@@} + fprintf(outfile,"\n\n"); + + /* */ +} diff --git a/org.glite.lb.utils/src/statistics.c b/org.glite.lb.utils/src/statistics.c index aef0842..5736c4a 100644 --- a/org.glite.lb.utils/src/statistics.c +++ b/org.glite.lb.utils/src/statistics.c @@ -30,16 +30,19 @@ typedef int init_f(glite_jp_context_t ctx, glite_jpps_fplug_data_t *data); typedef void done_f(glite_jp_context_t ctx, glite_jpps_fplug_data_t *data); +void process_attrs(glite_jp_context_t jpctx, glite_jpps_fplug_data_t plugin_data, void *data_handle, FILE *outfile); +void process_attrs2(glite_jp_context_t jpctx, glite_jpps_fplug_data_t plugin_data, void *data_handle, FILE *outfile); + static const char rcsid[] = "@(#)$Id$"; static int verbose = 0; static char *infilename = NULL; static char *outfilename = NULL; -static int jdl = 0; +static int versionone = 0; static struct option const long_options[] = { { "file", required_argument, 0, 'f' }, { "outfile", required_argument, 0, 'o' }, - { "jdl", no_argument, 0, 'j' }, + { "versionone", no_argument, 0, '1' }, { "help", no_argument, 0, 'h' }, { "verbose", no_argument, 0, 'v' }, { "version", no_argument, 0, 'V' }, @@ -60,7 +63,7 @@ usage(char *program_name) { "-v, --verbose print extensive debug output to stderr\n" "-f, --file dump file to process\n" "-o, --outfile output filename\n" - "-j, --jdl prit also JDL in the XML\n\n", + "-1, --versionone use version 1 of the attributes (obsolete now)\n\n", program_name); } @@ -82,19 +85,6 @@ int glite_jppsbe_pread(glite_jp_context_t ctx, void *handle, void *buf, size_t n } /* - * free the array of JP attr - */ -static void free_attrs(glite_jp_attrval_t *av) { - glite_jp_attrval_t *item; - - item = av; - while (item->name) { - glite_jp_attrval_free(item++, 0); - } - free(av); -} - -/* * main */ int main(int argc, char *argv[]) @@ -103,7 +93,6 @@ int main(int argc, char *argv[]) glite_jpps_fplug_data_t plugin_data; void *data_handle, *lib_handle; FILE *infile,*outfile = NULL; - glite_jp_attrval_t *attrval; char *err; init_f *plugin_init; done_f *plugin_done; @@ -113,7 +102,7 @@ int main(int argc, char *argv[]) while ((opt = getopt_long(argc,argv, "f:" /* input file */ "o:" /* output file */ - "j" /* jdl */ + "1" /* version one of the attributes */ "h" /* help */ "v" /* verbose */ "V", /* version */ @@ -124,7 +113,7 @@ int main(int argc, char *argv[]) case 'v': verbose = 1; break; case 'f': infilename = optarg; break; case 'o': outfilename = optarg; break; - case 'j': jdl = 1; break; + case '1': versionone = 1; break; case 'h': default: usage(argv[0]); return(0); @@ -136,21 +125,22 @@ int main(int argc, char *argv[]) err = dlerror() ? :"unknown error"; fprintf(stderr,"lb_statistics: can't load L&B plugin (%s)\n", err); return 1; - } + } else if (verbose) fprintf(stdout,"lb_statistics: loaded L&B plugin\n"); + if ((plugin_init = dlsym(lib_handle, "init")) == NULL || (plugin_done = dlsym(lib_handle, "done")) == NULL) { err = dlerror() ? : "unknown error"; fprintf(stderr,"lb_statistics: can't find symbol 'init' or 'done' (%s)\n", err); dlclose(lib_handle); return 1; - } + } else if (verbose) fprintf(stdout,"lb_statistics: L&B plugin check o.k.\n"); /* dump file with events */ if ((infile = fopen(infilename, "rt")) == NULL) { fprintf(stderr,"lb_statistics: Error opening file %s: %s\n", infilename, strerror(errno)); dlclose(lib_handle); return 1; - } + } else if (verbose) fprintf(stdout,"lb_statistics: opened input file %s\n", infilename); /* output filename */ if (outfilename) { @@ -158,13 +148,14 @@ int main(int argc, char *argv[]) fprintf(stderr,"lb_statistics: Error opening file %s: %s\n", outfilename, strerror(errno)); dlclose(lib_handle); fclose(infile); - } + } else if (verbose) fprintf(stdout,"lb_statistics: opened output file %s\n", outfilename); } else { outfile = stdout; + if (verbose) fprintf(stdout,"lb_statistics: output will go to stdout\n"); } - jpctx = calloc(1,sizeof *jpctx); /* use the plugin */ + jpctx = calloc(1,sizeof *jpctx); plugin_init(jpctx, &plugin_data); jpctx->plugins = calloc(2,sizeof(*jpctx->plugins)); @@ -173,201 +164,28 @@ int main(int argc, char *argv[]) plugin_data.ops.open(jpctx, infile, "uri://", &data_handle); if (data_handle) { - /*
*/ - fprintf(outfile,"\n\n"); - fprintf(outfile,"value); - free_attrs(attrval); - } else { - fprintf(outfile,"\tjobid=\"default\"\n"); - } - fprintf(outfile,">\n"); - /*
*/ - - /* */ - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_user, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_parent, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_VO, &attrval); - if (attrval) { - fprintf(stdout,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_aTag, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_rQType, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_eDuration, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_eNodes, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_eProc, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_RB, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_CE, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_host, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_UIHost, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_CPUTime, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_NProc, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_finalStatus, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_finalDoneStatus, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_finalStatusDate, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_finalStatusReason, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_LRMSDoneStatus, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_LRMSStatusReason, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_retryCount, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_additionalReason, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_jobType, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_nsubjobs, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_subjobs, &attrval); - if (attrval) { - fprintf(outfile,"\t\n%s\t\n", attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_lastStatusHistory, &attrval); - if (attrval) { - fprintf(outfile,"\t\n%s\t\n",attrval->value); - free_attrs(attrval); - } - - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_fullStatusHistory, &attrval); - if (attrval) { - fprintf(outfile,"\t\n%s\t\n",attrval->value); - free_attrs(attrval); - } - - if (jdl) { - plugin_data.ops.attr(jpctx, data_handle, GLITE_JP_LB_JDL, &attrval); - if (attrval) { - fprintf(outfile,"\t%s\n", attrval->value); - free_attrs(attrval); - } + if (versionone) { + process_attrs(jpctx, plugin_data, data_handle, outfile); + } else { + process_attrs2(jpctx, plugin_data, data_handle, outfile); } - fprintf(outfile,"\n"); - - /* */ plugin_data.ops.close(jpctx, data_handle); } plugin_done(jpctx, &plugin_data); fclose(infile); - if (outfile) fclose(outfile); + if (verbose) fprintf(stdout,"lb_statistics: closed input file %s\n", infilename); + + if (outfile) { + fclose(outfile); + if (verbose) fprintf(stdout,"lb_statistics: closed output file %s\n", outfilename); + } + dlclose(lib_handle); + if (verbose) fprintf(stdout,"lb_statistics: L&B plugin closed\n"); + return 0; } + -- 1.8.2.3