diff --git a/qa/248 b/qa/248 index 3cec5ae..80ab6df 100755 --- a/qa/248 +++ b/qa/248 @@ -2,6 +2,7 @@ # PCP QA Test No. 248 # is pmlogger tolerant of metric lookup within a group? # +# Copyright (c) 2014 Red Hat. # Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved. # @@ -63,7 +64,7 @@ log advisory on 200 msec { } End-of-File -pmlogger -c $tmp.config -Dappl1 -s 6 -l $tmp.log $tmp >$tmp.err 2>&1 & +pmlogger -c $tmp.config -s 6 -l $tmp.log $tmp >$tmp.err 2>&1 & logger_pid=$! wait diff --git a/qa/248.out.2 b/qa/248.out.2 index 05830d7..0d8547e 100644 --- a/qa/248.out.2 +++ b/qa/248.out.2 @@ -7,12 +7,6 @@ Reason: Unknown metric name Warning [CONFIG, line 8-or-9] Description unavailable for metric "sample.bad.unknown" ... not logged Reason: Unknown or illegal metric identifier -Warning [CONFIG, line 10] -Eliminating duplicate metric "sample.milliseconds" -Warning [CONFIG, line 11] -Eliminating duplicate metric "sample.daemon_pid" -Warning [CONFIG, line 14-or-15] -Eliminating duplicate metric "sample.daemon_pid" Warning [CONFIG, line 14-or-15] Description unavailable for metric "sample.bad.unknown" ... not logged Reason: Unknown or illegal metric identifier diff --git a/qa/418 b/qa/418 index 36a55b2..f43b281 100755 --- a/qa/418 +++ b/qa/418 @@ -38,7 +38,7 @@ else exit fi -pmdumplog $tmp | _filter_pmdumplog | grep sample +pmdumplog $tmp | _filter_pmdumplog | grep sample | sort -n -k2 pmdumplog $tmp >>$seq.full echo @@ -61,7 +61,7 @@ else exit fi -pmdumplog $tmp | _filter_pmdumplog | grep sample +pmdumplog $tmp | _filter_pmdumplog | grep sample | sort -n -k2 pmdumplog $tmp >>$seq.full # success, all done diff --git a/qa/418.out b/qa/418.out index 936daa6..3accce3 100644 --- a/qa/418.out +++ b/qa/418.out @@ -1,12 +1,12 @@ QA output created by 418 expect 2 x one and 0 x million -TIMESTAMP 29.0.15 (sample.float.one): value 1 TIMESTAMP 29.0.10 (sample.long.one): value 1 +TIMESTAMP 29.0.15 (sample.float.one): value 1 expect 2 x one and 4 x million -TIMESTAMP 29.0.18 (sample.float.million): value 1000000 +TIMESTAMP 29.0.10 (sample.long.one): value 1 +TIMESTAMP 29.0.13 (sample.long.million): value 1000000 TIMESTAMP 29.0.13 (sample.long.million): value 1000000 TIMESTAMP 29.0.15 (sample.float.one): value 1 -TIMESTAMP 29.0.10 (sample.long.one): value 1 TIMESTAMP 29.0.18 (sample.float.million): value 1000000 -TIMESTAMP 29.0.13 (sample.long.million): value 1000000 +TIMESTAMP 29.0.18 (sample.float.million): value 1000000 diff --git a/qa/465 b/qa/465 index f8b0a3d..e891098 100755 --- a/qa/465 +++ b/qa/465 @@ -2,6 +2,7 @@ # PCP QA Test No. 465 # pmdumplog -s # +# Copyright (c) 2014 Red Hat. # Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved. # @@ -15,7 +16,11 @@ echo "QA output created by $seq" . ./localconfig rm -f $seq.out -if [ $PCP_VER -ge 3810 ] +if [ $PCP_VER -ge 3811 ] +then + ln $seq.out.4 $seq.out + echo "[Version for PCP 3.8.11 or later]" +elif [ $PCP_VER -ge 3810 ] then ln $seq.out.3 $seq.out echo "[Version for PCP 3.8.10 or later]" @@ -38,7 +43,7 @@ status=1 # failure is the default! trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15 # real QA test starts here -cat <&1 \ diff --git a/qa/465.out.4 b/qa/465.out.4 new file mode 100644 index 0000000..fe07c7c --- /dev/null +++ b/qa/465.out.4 @@ -0,0 +1,20 @@ +QA output created by 465 +[Version for PCP 3.8.11 or later] + +[272 bytes] +TIMESTAMP 29.0.31 (sample.string.hullo): value "hullo world!" + 29.0.30 (sample.string.null): value "" + 29.0.25 (sample.double.one): value 1 + 29.0.15 (sample.float.one): value 1 + 29.0.10 (sample.long.one): value 1 + 29.0.6 (sample.bin): + inst [100 or "bin-100"] value 100 + inst [200 or "bin-200"] value 200 + inst [300 or "bin-300"] value 300 + inst [400 or "bin-400"] value 400 + inst [500 or "bin-500"] value 500 + inst [600 or "bin-600"] value 600 + inst [700 or "bin-700"] value 700 + inst [800 or "bin-800"] value 800 + inst [900 or "bin-900"] value 900 + 29.0.0 (sample.control): value 0 diff --git a/qa/466 b/qa/466 index 5f9aac0..f290565 100755 --- a/qa/466 +++ b/qa/466 @@ -15,15 +15,11 @@ echo "QA output created by $seq" . ./common.check . ./localconfig -if [ $PCP_EOE_VER -eq 2000 -o \ - \( $PCP_EOE_VER -ge 6500 -a $PCP_EOE_VER -le 6501 \) ] ; then - echo "This test is applicable on PCP 2.1 or Irix 6.5.2 or later" > $seq.notrun - echo "$seq: [not run] `cat $seq.notrun`" - exit 0 -fi - rm -f $seq.out -if [ $PCP_VER -ge 3810 ] +if [ $PCP_VER -ge 3811 ] +then + ln $seq.out.3 $seq.out || exit 1 +elif [ $PCP_VER -ge 3810 ] then ln $seq.out.1 $seq.out || exit 1 else diff --git a/qa/466.out.3 b/qa/466.out.3 new file mode 100644 index 0000000..5058934 --- /dev/null +++ b/qa/466.out.3 @@ -0,0 +1,29 @@ +QA output created by 466 + +Group [7 metrics] { + sample.string.hullo + sample.string.null + sample.double.one + sample.float.one + sample.long.one + sample.bin + sample.control +} logged once: 272 bytes + +Metric sample.control logged every 0.500 sec: 40 bytes or 6.59 Mbytes/day + +Group [2 metrics] { + sample.long.one + sample.control +} logged every 1 sec: 60 bytes or 4.94 Mbytes/day + +Group [6 metrics] { + sample.string.hullo + sample.string.null + sample.double.one + sample.float.one + sample.bin + sample.control +} logged every 2 sec: 252 bytes or 10.38 Mbytes/day +pmlogger: End of run time, exiting + diff --git a/qa/726 b/qa/726 new file mode 100755 index 0000000..b563578 --- /dev/null +++ b/qa/726 @@ -0,0 +1,72 @@ +#!/bin/sh +# PCP QA Test No. 726 +# Exercise optimal pmlogger handling of config duplicates +# (metrics and instances). +# +# Copyright (c) 2014 Red Hat. +# + +seq=`basename $0` +echo "QA output created by $seq" + +# get standard environment, filters and checks +. ./common.product +. ./common.filter +. ./common.check + +test $PCP_VER -ge 3811 || _notrun Need newer pmlogger version + +status=1 # failure is the default! +$sudo rm -rf $tmp.* $seq.full +trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15 + +# real QA test starts here +cat <> $seq.full +cat $tmp.log >> $seq.full + +echo "pmlogger archive contents" >> $seq.full +pmdumplog -s $tmp 2>&1 \ +| tee -a $seq.full \ +| _filter_pmdumplog \ +| sed -e '1,/pmcd.pmlogger.archive/d' + +# success, all done +status=0 +exit diff --git a/qa/726.out b/qa/726.out new file mode 100644 index 0000000..3eca35a --- /dev/null +++ b/qa/726.out @@ -0,0 +1,14 @@ +QA output created by 726 + +[232 bytes] +TIMESTAMP 29.0.31 (sample.string.hullo): value "hullo world!" + 29.0.30 (sample.string.null): value "" + 29.0.25 (sample.double.one): value 1 + 29.0.15 (sample.float.one): value 1 + 29.0.10 (sample.long.one): value 1 + 29.0.6 (sample.bin): + inst [100 or "bin-100"] value 100 + inst [500 or "bin-500"] value 500 + inst [700 or "bin-700"] value 700 + inst [800 or "bin-800"] value 800 + 29.0.0 (sample.control): value 0 diff --git a/qa/group b/qa/group index a5fd816..2881356 100644 --- a/qa/group +++ b/qa/group @@ -879,6 +879,7 @@ avahi 723 pmda.proc local oss 724 pmfind local oss 725 pmda.jbd2 local oss +726 pmlogger pmdumplog local oss 733 pmie pmval pmdumplog local oss 735 pmda.proc local oss 736 pmlogrewrite local oss diff --git a/src/pmlogger/src/callback.c b/src/pmlogger/src/callback.c index 03194d1..809e1b7 100644 --- a/src/pmlogger/src/callback.c +++ b/src/pmlogger/src/callback.c @@ -317,7 +317,7 @@ lookupTaskCacheNames(pmID pmid, char ***namesptr) for (tp = tasklist; tp != NULL; tp = tp->t_next) { for (i = 0; i < tp->t_numpmid; i++) { - if (tp->t_pmidlist[i] != pmid || tp->t_namelist[i] == NULL) + if (tp->t_pmidlist[i] != pmid) continue; len += strlen(tp->t_namelist[i]) + 1; numnames++; @@ -328,7 +328,7 @@ lookupTaskCacheNames(pmID pmid, char ***namesptr) data = (char *)names + (numnames * sizeof(names[0])); for (tp = tasklist, len = 0; tp != NULL; tp = tp->t_next) { for (i = 0; i < tp->t_numpmid; i++) { - if (tp->t_pmidlist[i] != pmid || tp->t_namelist[i] == NULL) + if (tp->t_pmidlist[i] != pmid) continue; names[len++] = data; strcpy(data, tp->t_namelist[i]); diff --git a/src/pmlogger/src/dopdu.c b/src/pmlogger/src/dopdu.c index 258a1ab..544b1e8 100644 --- a/src/pmlogger/src/dopdu.c +++ b/src/pmlogger/src/dopdu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Red Hat. All Rights Reserved. + * Copyright (c) 2012-2014 Red Hat. All Rights Reserved. * Copyright (c) 1995-2001 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it @@ -80,11 +80,8 @@ reality_check(void) } } } - - } -/* Call this in dbx to dump the task list (dbx doesn't know about stdout) */ void dumpit(void) { @@ -153,16 +150,6 @@ die(char *name, int sts) exit(1); } -static void -linkback(task_t *tp) -{ - fetchctl_t *fcp; - - /* link the new fetch groups back to their task */ - for (fcp = tp->t_fetch; fcp != NULL; fcp = fcp->f_next) - fcp->f_aux = (void *)tp; -} - optreq_t * findoptreq(pmID pmid, int inst) { @@ -180,7 +167,7 @@ findoptreq(pmID pmid, int inst) * structures lying about, i.e. MAYBE (mandatory) is the default, * and does not have to be explicitly stored, while OFF (advisory) * reverts to MAYBE (mandatory). - * There is one execption to the above assumption, namely for + * There is one exception to the above assumption, namely for * cases where the initial specification includes "all" instances, * then some later concurrent specification may refer to specific * instances ... in this case, the specific optreq_t structure is @@ -746,31 +733,6 @@ update_metric(pmValueSet *vsp, int reqstate, int mflags, task_t **result) return 0; } -/* Given a state and a delta, return in result the first matching task. - * Return true if a matching task was found - */ -static int -find_task(int state, int delta, task_t **result) -{ - task_t *tp; - int tdelta; - - /* Never return a "once only" task, it may have gone off already and just - * be hanging around - * TODO: cleanup once only tasks after callback invoked - */ - if (delta == 0) - return 0; - - for (tp = tasklist; tp != NULL; tp = tp->t_next) { - tdelta = tp->t_delta.tv_sec * 1000 + (tp->t_delta.tv_usec / 1000); - if (state == (tp->t_state & 0x3) && delta == tdelta) - break; - } - *result = tp; - return tp != NULL; -} - /* Return a mask containing the history flags for a given metric/instance. * the history flags indicate whether the metric/instance is in the log at all * and whether the last fetch of the metric/instance was successful. @@ -781,7 +743,7 @@ find_task(int state, int delta, task_t **result) static int gethistflags(pmID pmid, int inst) { - __pmHashNode *hp; + __pmHashNode *hp; pmidhist_t *php; insthist_t *ihp; int i, found; @@ -1051,6 +1013,7 @@ do_control(__pmPDU *pb) /* update the logging status of metrics */ task_t *newtp = NULL; /* task for metrics/insts in request */ + struct timeval tdelta = { 0 }; int newtask; int mflags; @@ -1069,8 +1032,16 @@ do_control(__pmPDU *pb) PMLC_SET_MAND(reqstate, 1); } - /* try to find an existing task for the request */ - newtask = !find_task(reqstate, delta, &newtp); + /* try to find an existing task for the request + * Never return a "once only" task, it may have gone off already and just + * be hanging around like a bad smell. + */ + if (delta != 0) { + tdelta.tv_sec = delta / 1000; + tdelta.tv_usec = (delta % 1000) * 1000; + newtp = findtask(reqstate, &tdelta); + } + newtask = (newtp == NULL); for (i = 0; i < request->numpmid; i++) { vsp = request->vset[i]; @@ -1112,14 +1083,13 @@ do_control(__pmPDU *pb) /* use only the MAND/ADV and ON/OFF bits of reqstate */ newtp->t_state = reqstate & 0x3; if (PMLC_GET_ON(reqstate)) { - newtp->t_delta.tv_sec = delta / 1000; - newtp->t_delta.tv_usec = (delta % 1000) * 1000; - newtp->t_afid = __pmAFregister(&newtp->t_delta, (void *)newtp, + newtp->t_delta = tdelta; + newtp->t_afid = __pmAFregister(&tdelta, (void *)newtp, log_callback); } else newtp->t_delta.tv_sec = newtp->t_delta.tv_usec = 0; - linkback(newtp); /* TODO: really needed? (no) */ + linkback(newtp); } } } diff --git a/src/pmlogger/src/gram.y b/src/pmlogger/src/gram.y index 7b3feb4..7518e1f 100644 --- a/src/pmlogger/src/gram.y +++ b/src/pmlogger/src/gram.y @@ -1,4 +1,5 @@ /* + * Copyright (c) 2013-2014 Red Hat. * Copyright (c) 1995-2001 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it @@ -31,22 +32,17 @@ #include "impl.h" #include "logger.h" -int mystate = GLOBAL; +int mystate = GLOBAL; /* config file parser state */ __pmHashCtl pm_hash; task_t *tasklist; -fetchctl_t *fetchroot; -static int sts; +static task_t *tp; static int numinst; static int *intlist; static char **extlist; -static task_t *tp; -static fetchctl_t *fp; -static int numvalid; -static int warn = 1; - -extern int lineno; +static int state; /* logging state, current block */ +static char *metricName; /* current metric, current block */ typedef struct _hl { struct _hl *hl_next; @@ -54,15 +50,18 @@ typedef struct _hl { int hl_line; } hostlist_t; -static hostlist_t *hl_root = NULL; -static hostlist_t *hl_last = NULL; +static hostlist_t *hl_root; +static hostlist_t *hl_last; static hostlist_t *hlp; static hostlist_t *prevhlp; -static int opmask = 0; -static int specmask = 0; -static int allow; -static int state = 0; -static char * metricName; +static int opmask; /* operations mask */ +static int specmask; /* specifications mask */ +static int allow; /* host allow/disallow state */ + +static int lookup_metric_name(const char *); +static void activate_new_metric(const char *); +static void activate_cached_metric(const char *, int); + %} %union { long lval; @@ -107,40 +106,35 @@ spec : stmt stmt : dowhat somemetrics { - mystate = GLOBAL; - if (numvalid) { - PMLC_SET_MAYBE(tp->t_state, 0); /* clear req */ - tp->t_next = tasklist; - tasklist = tp; - tp->t_fetch = fetchroot; - for (fp = fetchroot; fp != NULL; fp = fp->f_next) - /* link fetchctl back to task */ - fp->f_aux = (void *)tp; - - if (PMLC_GET_ON(state)) - tp->t_afid = __pmAFregister(&tp->t_delta, - (void *)tp, - log_callback); - } - else - free(tp); - - fetchroot = NULL; - state = 0; + mystate = GLOBAL; + state = 0; } ; dowhat : logopt action { - if ((tp = (task_t *)calloc(1, sizeof(task_t))) == NULL) { - char emess[256]; - snprintf(emess, sizeof(emess), "malloc failed: %s", osstrerror()); - yyerror(emess); - } - tp->t_delta.tv_sec = $2 / 1000; - tp->t_delta.tv_usec = 1000 * ($2 % 1000); - tp->t_state = state; - } + struct timeval delta; + + delta.tv_sec = $2 / 1000; + delta.tv_usec = 1000 * ($2 % 1000); + + /* + * Search for an existing task for this state/interval; + * only allocate and setup a new task if none exists. + */ + if ((tp = findtask(state, &delta)) == NULL) { + if ((tp = (task_t *)calloc(1, sizeof(task_t))) == NULL) { + char emess[256]; + snprintf(emess, sizeof(emess), "malloc failed: %s", osstrerror()); + yyerror(emess); + } else { + tp->t_delta = delta; + tp->t_state = state; + tp->t_next = tasklist; + tasklist = tp; + } + } + } ; logopt : LOG @@ -199,7 +193,7 @@ timeunits : MSEC { $$ = 1; } | HOUR { $$ = 3600000; } ; -somemetrics : LBRACE { numvalid = 0; mystate = INSPEC; } metriclist RBRACE +somemetrics : LBRACE { mystate = INSPEC; } metriclist RBRACE | metricspec ; @@ -208,46 +202,39 @@ metriclist : metricspec | metriclist COMMA metricspec ; -metricspec : NAME - { +metricspec : NAME + { if ((metricName = strdup($1)) == NULL) { char emess[256]; snprintf(emess, sizeof(emess), "malloc failed: %s", osstrerror()); yyerror(emess); } } - optinst + optinst { + int index, sts; + /* - * search cache for previously seen metrics for this task + * search names for previously seen metrics for this task + * (note that name may be non-terminal in the PMNS here); + * if already found in this task, skip namespace PDUs. */ - int j; - for (j = 0; j < tp->t_numpmid; j++) { - if (tp->t_namelist[j] != NULL && - strcmp(tp->t_namelist[j], metricName) == 0) { - break; - } - } - if (j < tp->t_numpmid) { - /* found in cache */ - dometric(metricName); - } - else { - /* - * either a new metric, and so it may be a - * non-terminal in the PMNS - */ - if ((sts = pmTraversePMNS(metricName, dometric)) < 0 ) { + if ((index = lookup_metric_name(metricName)) < 0) { + if ((sts = pmTraversePMNS(metricName, activate_new_metric)) < 0 ) { char emess[256]; - snprintf(emess, sizeof(emess), "Problem with lookup for metric \"%s\" " - "... logging not activated",metricName); + snprintf(emess, sizeof(emess), + "Problem with lookup for metric \"%s\" " + "... logging not activated", metricName); yywarn(emess); fprintf(stderr, "Reason: %s\n", pmErrStr(sts)); } } - freeinst(&numinst, intlist, extlist); - free (metricName); - } + else { /* name is cached already, handle instances */ + activate_cached_metric(metricName, index); + } + freeinst(&numinst, intlist, extlist); + free(metricName); + } ; optinst : LSQB instancelist RSQB @@ -276,6 +263,8 @@ ctl : allow hostlist COLON operation SEMICOLON { prevhlp = NULL; for (hlp = hl_root; hlp != NULL; hlp = hlp->hl_next) { + int sts; + if (prevhlp != NULL) { free(prevhlp->hl_name); free(prevhlp); @@ -309,9 +298,11 @@ hostlist : host host : hostspec { - hlp = (hostlist_t *)malloc(sts = sizeof(hostlist_t)); + size_t sz = sizeof(hostlist_t); + + hlp = (hostlist_t *)malloc(sz); if (hlp == NULL) { - __pmNoMem("adding new host", sts, PM_FATAL_ERR); + __pmNoMem("adding new host", sz, PM_FATAL_ERR); } if (hl_last != NULL) { hl_last->hl_next = hlp; @@ -364,78 +355,79 @@ op : ADVISORY { opmask |= PM_OP_LOG_ADV; } %% /* + * Search the cache for previously seen metrics for active task. + * Returns -1 if not found, else an index into tp->t_namelist. + */ +static int +lookup_metric_name(const char *name) +{ + int j; + + for (j = 0; j < tp->t_numpmid; j++) + if (strcmp(tp->t_namelist[j], name) == 0) + return j; + return -1; +} + +/* * Assumed calling context ... - * tp the correct task for the requested metric + * tp task for the requested metric * numinst number of instances associated with this request * extlist[] external instance names if numinst > 0 * intlist[] internal instance identifier if numinst > 0 and * corresponding extlist[] entry is NULL */ - -void -dometric(const char *name) +static void +activate_cached_metric(const char *name, int index) { - int sts = 0; /* initialize to pander to gcc */ + int sts = 0; int inst; int i; int j; - int dup = -1; - int skip; + int skip = 0; pmID pmid; pmDesc *dp; optreq_t *rqp; - extern char *chk_emess[]; - char emess[1024]; - - /* - * search cache for previously seen metrics for this task - */ - for (j = 0; j < tp->t_numpmid; j++) { - if (tp->t_namelist[j] != NULL && - strcmp(tp->t_namelist[j], name) == 0) { - dup = j; - break; - } - } + char emess[1024]; /* - * need new malloc'd pmDesc, even if metric found in cache + * need new malloc'd pmDesc, even if metric found in cache, as + * the fetchctl keeps its own (non-realloc-movable!) pointer. */ dp = (pmDesc *)malloc(sizeof(pmDesc)); if (dp == NULL) goto nomem; - if (dup == -1) { - - /* Cast away const, pmLookupName should never modify name */ + if (index < 0) { if ((sts = pmLookupName(1, (char **)&name, &pmid)) < 0 || pmid == PM_ID_NULL) { - snprintf(emess, sizeof(emess), "Metric \"%s\" is unknown ... not logged", name); - goto defer; + snprintf(emess, sizeof(emess), + "Metric \"%s\" is unknown ... not logged", name); + goto snarf; } - if ((sts = pmLookupDesc(pmid, dp)) < 0) { - snprintf(emess, sizeof(emess), "Description unavailable for metric \"%s\" ... not logged", name); - - goto defer; + snprintf(emess, sizeof(emess), + "Description unavailable for metric \"%s\" ... not logged", + name); + goto snarf; } } else { - *dp = tp->t_desclist[dup]; - pmid = tp->t_pmidlist[dup]; + *dp = tp->t_desclist[index]; + pmid = tp->t_pmidlist[index]; } tp->t_numpmid++; - tp->t_pmidlist = (pmID *)realloc(tp->t_pmidlist, tp->t_numpmid * sizeof(pmID)); - if (tp->t_pmidlist == NULL) - goto nomem; tp->t_namelist = (char **)realloc(tp->t_namelist, tp->t_numpmid * sizeof(char *)); if (tp->t_namelist == NULL) goto nomem; + if ((tp->t_namelist[tp->t_numpmid-1] = strdup(name)) == NULL) + goto nomem; + tp->t_pmidlist = (pmID *)realloc(tp->t_pmidlist, tp->t_numpmid * sizeof(pmID)); + if (tp->t_pmidlist == NULL) + goto nomem; tp->t_desclist = (pmDesc *)realloc(tp->t_desclist, tp->t_numpmid * sizeof(pmDesc)); if (tp->t_desclist == NULL) goto nomem; - if ((tp->t_namelist[tp->t_numpmid-1] = strdup(name)) == NULL) - goto nomem; tp->t_pmidlist[tp->t_numpmid-1] = pmid; tp->t_desclist[tp->t_numpmid-1] = *dp; /* struct assignment */ @@ -444,7 +436,7 @@ dometric(const char *name) goto nomem; rqp->r_desc = dp; rqp->r_numinst = numinst; - skip = 0; + if (numinst) { /* * malloc here, and keep ... gets buried in optFetch data structures @@ -457,7 +449,9 @@ dometric(const char *name) if (extlist[i] != NULL) { sts = pmLookupInDom(dp->indom, extlist[i]); if (sts < 0) { - snprintf(emess, sizeof(emess), "Instance \"%s\" is not defined for the metric \"%s\"", extlist[i], name); + snprintf(emess, sizeof(emess), + "Instance \"%s\" is not defined for the metric \"%s\"", + extlist[i], name); yywarn(emess); rqp->r_numinst--; continue; @@ -468,7 +462,9 @@ dometric(const char *name) char *p; sts = pmNameInDom(dp->indom, intlist[i], &p); if (sts < 0) { - snprintf(emess, sizeof(emess), "Instance \"%d\" is not defined for the metric \"%s\"", intlist[i], name); + snprintf(emess, sizeof(emess), + "Instance \"%d\" is not defined for the metric \"%s\"", + intlist[i], name); yywarn(emess); rqp->r_numinst--; continue; @@ -477,7 +473,9 @@ dometric(const char *name) inst = intlist[i]; } if ((sts = chk_one(tp, pmid, inst)) < 0) { - snprintf(emess, sizeof(emess), "Incompatible request for metric \"%s\" and instance \"%s\"", name, extlist[i]); + snprintf(emess, sizeof(emess), + "Incompatible request for metric \"%s\"" + "and instance \"%s\"", name, extlist[i]); yywarn(emess); fprintf(stderr, "%s\n", chk_emess[-sts]); rqp->r_numinst--; @@ -490,7 +488,8 @@ dometric(const char *name) } else { if ((sts = chk_all(tp, pmid)) < 0) { - snprintf(emess, sizeof(emess), "Incompatible request for metric \"%s\"", name); + snprintf(emess, sizeof(emess), + "Incompatible request for metric \"%s\"", name); yywarn(emess); skip = 1; @@ -498,34 +497,18 @@ dometric(const char *name) } if (!skip) { - __pmOptFetchAdd(&fetchroot, rqp); + __pmOptFetchAdd(&tp->t_fetch, rqp); if ((sts = __pmHashAdd(pmid, (void *)rqp, &pm_hash)) < 0) { - snprintf(emess, sizeof(emess), "__pmHashAdd failed for metric \"%s\" ... logging not activated", name); - + snprintf(emess, sizeof(emess), "__pmHashAdd failed " + "for metric \"%s\" ... logging not activated", name); goto snarf; } - numvalid++; + tp->t_numvalid++; } else { free(dp); free(rqp); } - - return; - -defer: - /* EXCEPTION PCP 2.0 - * The idea here is that we will sort all logging request into "good" and - * "bad" (like pmie) ... the "bad" ones are "deferred" and at some point - * later pmlogger would (periodically) revisit the "deferred" ones and see - * if they can be added to the "good" set. - */ - if (warn) { - yywarn(emess); - fprintf(stderr, "Reason: %s\n", pmErrStr(sts)); - } - if (dp != NULL) - free(dp); return; nomem: @@ -535,6 +518,32 @@ nomem: snarf: yywarn(emess); fprintf(stderr, "Reason: %s\n", pmErrStr(sts)); - free(dp); + if (dp != NULL) + free(dp); return; } + +static void +activate_new_metric(const char *name) +{ + activate_cached_metric(name, lookup_metric_name(name)); +} + +/* + * Complete the delayed processing of task elements, which can only + * be done once all configuration file parsing is complete. + */ +void +yyend(void) +{ + task_t *prev; + + for (tp = prev = tasklist; tp != NULL; prev = tp, tp = tp->t_next) { + if (tp->t_numvalid == 0) + continue; + linkback(tp); + PMLC_SET_MAYBE(tp->t_state, 0); /* clear req */ + if (PMLC_GET_ON(tp->t_state)) + tp->t_afid = __pmAFregister(&tp->t_delta, (void *)tp, log_callback); + } +} diff --git a/src/pmlogger/src/logger.h b/src/pmlogger/src/logger.h index 7c136b9..965e011 100644 --- a/src/pmlogger/src/logger.h +++ b/src/pmlogger/src/logger.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2014 Red Hat. * Copyright (c) 1995-2001 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it @@ -10,12 +11,7 @@ * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - #ifndef _LOGGER_H #define _LOGGER_H @@ -24,13 +20,16 @@ #include /* - * a task is a bundle of fetches to be done together + * a task is a bundle of fetches to be done together - it + * originally corresponded one-to-one with a configuration + * file curly-brace-enclosed block, but no longer does. */ -typedef struct _task { - struct _task *t_next; +typedef struct task_s { + struct task_s *t_next; struct timeval t_delta; int t_state; /* logging state */ int t_numpmid; + int t_numvalid; pmID *t_pmidlist; char **t_namelist; pmDesc *t_desclist; @@ -118,13 +117,15 @@ extern void yyerror(char *); extern void yywarn(char *); extern int yylex(void); extern int yyparse(void); -extern void dometric(const char *); +extern void yyend(void); extern void buildinst(int *, int **, char ***, int, char *); extern void freeinst(int *, int *, char **); +extern void linkback(task_t *); +extern task_t *findtask(int, struct timeval *); +extern optreq_t *findoptreq(pmID, int); extern void log_callback(int, void *); extern int chk_one(task_t *, pmID, int); extern int chk_all(task_t *, pmID); -extern optreq_t *findoptreq(pmID, int); extern int newvolume(int); extern void disconnect(int); #if CAN_RECONNECT @@ -135,6 +136,7 @@ extern void run_done(int,char *); extern __pmPDU *rewrite_pdu(__pmPDU *, int); extern int putmark(void); extern int do_flush(void); +extern void dumpit(void); #include extern char pmlc_host[]; diff --git a/src/pmlogger/src/pmlogger.c b/src/pmlogger/src/pmlogger.c index 4d70e77..d4c6d0f 100644 --- a/src/pmlogger/src/pmlogger.c +++ b/src/pmlogger/src/pmlogger.c @@ -751,10 +751,9 @@ Options:\n\ if (yyparse() != 0) exit(1); - - if ( configfile != NULL ) { + if (configfile != NULL) fclose(yyin); - } + yyend(); #ifdef PCP_DEBUG fprintf(stderr, "Config parsed\n"); @@ -762,7 +761,6 @@ Options:\n\ fprintf(stderr, "Starting %slogger for host \"%s\" via \"%s\"\n", primary ? "primary " : "", pmcd_host, pmcd_host_conn); - #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOG) { fprintf(stderr, "optFetch Cost Parameters: pmid=%d indom=%d fetch=%d scope=%d\n", diff --git a/src/pmlogger/src/util.c b/src/pmlogger/src/util.c index 0dfc47d..b812ee6 100644 --- a/src/pmlogger/src/util.c +++ b/src/pmlogger/src/util.c @@ -70,3 +70,33 @@ freeinst(int *numinst, int *intlist, char **extlist) *numinst = 0; } } + +/* + * Given a logging state and an interval, return a matching task + * or NULL if none exists for that value pair. + */ +task_t * +findtask(int state, struct timeval *delta) +{ + task_t *tp; + + for (tp = tasklist; tp != NULL; tp = tp->t_next) { + if (state == (tp->t_state & 0x3) && + delta->tv_sec == tp->t_delta.tv_sec && + delta->tv_usec == tp->t_delta.tv_usec) + break; + } + return tp; +} + +/* + * Link the new fetch groups back to their task structure + */ +void +linkback(task_t *tp) +{ + fetchctl_t *fcp; + + for (fcp = tp->t_fetch; fcp != NULL; fcp = fcp->f_next) + fcp->f_aux = (void *)tp; +}