Пример #1
0
static int
refresh_net_dev_ipv6_addr(pmInDom indom)
{
    FILE *fp;
    char addr6p[8][5];
    char addr6[40], devname[20+1];
    char addr[INET6_ADDRSTRLEN];
    char buf[MAXPATHLEN];
    struct sockaddr_in6 sin6;
    int sts, plen, scope, dad_status, if_idx;
    net_addr_t *netip;
    static uint32_t cache_err;

    if ((fp = linux_statsfile("/proc/net/if_inet6", buf, sizeof(buf))) == NULL)
	return 0;

    while (fscanf(fp, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
		  addr6p[0], addr6p[1], addr6p[2], addr6p[3],
		  addr6p[4], addr6p[5], addr6p[6], addr6p[7],
		  &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
	sts = pmdaCacheLookupName(indom, devname, NULL, (void **)&netip);
	if (sts == PM_ERR_INST || (sts >= 0 && netip == NULL)) {
	    /* first time since re-loaded, else new one */
	    netip = (net_addr_t *)calloc(1, sizeof(net_addr_t));
	}
	else if (sts < 0) {
	    if (cache_err++ < 10) {
		fprintf(stderr, "refresh_net_dev_ipv6_addr: "
				"pmdaCacheLookupName(%s, %s, ...) failed: %s\n",
		    pmInDomStr(indom), devname, pmErrStr(sts));
	    }
	    continue;
	}
	if ((sts = pmdaCacheStore(indom, PMDA_CACHE_ADD, devname, (void *)netip)) < 0) {
	    if (cache_err++ < 10) {
		fprintf(stderr, "refresh_net_dev_ipv6_addr: "
			"pmdaCacheStore(%s, PMDA_CACHE_ADD, %s, "
			PRINTF_P_PFX "%p) failed: %s\n",
		    pmInDomStr(indom), devname, netip, pmErrStr(sts));
	    }
	    continue;
	}

	sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
		addr6p[0], addr6p[1], addr6p[2], addr6p[3],
		addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
	if (inet_pton(AF_INET6, addr6, sin6.sin6_addr.s6_addr) != 1)
	    continue;

	sin6.sin6_family = AF_INET6;
	sin6.sin6_port = 0;
	if (!inet_ntop(AF_INET6, &sin6.sin6_addr, addr, INET6_ADDRSTRLEN))
	    continue;
	snprintf(netip->ipv6, sizeof(netip->ipv6), "%s/%d", addr, plen);
	netip->ipv6scope = (uint16_t)scope;
	netip->has_ipv6 = 1;
    }
    fclose(fp);
    return 0;
}
Пример #2
0
static int
refresh_net_dev_ipv4_addr(pmInDom indom, linux_container_t *container)
{
    int n, fd, sts, numreqs = 30;
    struct ifconf ifc;
    struct ifreq *ifr;
    net_addr_t *netip;
    static uint32_t cache_err;

    if ((fd = refresh_inet_socket(container)) < 0)
	return fd;

    ifc.ifc_buf = NULL;
    for (;;) {
	ifc.ifc_len = sizeof(struct ifreq) * numreqs;
	ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);

	if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
	    free(ifc.ifc_buf);
	    return -oserror();
	}
	if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
	    /* assume it overflowed and try again */
	    numreqs *= 2;
	    continue;
	}
	break;
    }

    for (n = 0, ifr = ifc.ifc_req;
	 n < ifc.ifc_len;
	 n += sizeof(struct ifreq), ifr++) {
	sts = pmdaCacheLookupName(indom, ifr->ifr_name, NULL, (void **)&netip);
	if (sts == PM_ERR_INST || (sts >= 0 && netip == NULL)) {
	    /* first time since re-loaded, else new one */
	    netip = (net_addr_t *)calloc(1, sizeof(net_addr_t));
	}
	else if (sts < 0) {
	    if (cache_err++ < 10) {
		fprintf(stderr, "refresh_net_dev_ipv4_addr: "
			"pmdaCacheLookupName(%s, %s, ...) failed: %s\n",
		    pmInDomStr(indom), ifr->ifr_name, pmErrStr(sts));
	    }
	    continue;
	}
	if ((sts = pmdaCacheStore(indom, PMDA_CACHE_ADD, ifr->ifr_name, (void *)netip)) < 0) {
	    if (cache_err++ < 10) {
		fprintf(stderr, "refresh_net_dev_ipv4_addr: "
			"pmdaCacheStore(%s, PMDA_CACHE_ADD, %s, "
			PRINTF_P_PFX "%p) failed: %s\n",
		    pmInDomStr(indom), ifr->ifr_name, netip, pmErrStr(sts));
	    }
	    continue;
	}

	refresh_net_ipv4_addr(ifr->ifr_name, netip, container);
    }
    free(ifc.ifc_buf);
    return 0;
}
Пример #3
0
static void
dumpInDom(__pmContext *ctxp)
{
    int		i;
    int		j;
    __pmHashNode	*hp;
    __pmLogInDom	*idp;
    __pmLogInDom	*ldp;

    printf("\nInstance Domains in the Log ...\n");
    for (i = 0; i < ctxp->c_archctl->ac_log->l_hashindom.hsize; i++) {
	for (hp = ctxp->c_archctl->ac_log->l_hashindom.hash[i]; hp != NULL; hp = hp->next) {
	    printf("InDom: %s\n", pmInDomStr((pmInDom)hp->key));
	    /*
	     * in reverse chronological order, so iteration is a bit funny
	     */
	    ldp = NULL;
	    for ( ; ; ) {
		for (idp = (__pmLogInDom *)hp->data; idp->next != ldp; idp =idp->next)
			;
		tv.tv_sec = idp->stamp.tv_sec;
		tv.tv_usec = idp->stamp.tv_usec;
		__pmPrintStamp(stdout, &tv);
		printf(" %d instances\n", idp->numinst);
		for (j = 0; j < idp->numinst; j++) {
		    printf("                 %d or \"%s\"\n",
			idp->instlist[j], idp->namelist[j]);
		}
		if (idp == (__pmLogInDom *)hp->data)
		    break;
		ldp = idp;
	    }
	}
    }
}
Пример #4
0
static int
addindom(__pmLogCtl *lcp, pmInDom indom, const __pmTimeval *tp, int numinst, 
         int *instlist, char **namelist, int *indom_buf, int allinbuf)
{
    __pmLogInDom	*idp;
    __pmHashNode	*hp;
    int		sts;

    if ((idp = (__pmLogInDom *)malloc(sizeof(__pmLogInDom))) == NULL)
	return -errno;
    idp->stamp = *tp;		/* struct assignment */
    idp->numinst = numinst;
    idp->instlist = instlist;
    idp->namelist = namelist;
    idp->buf = indom_buf;
    idp->allinbuf = allinbuf;

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_LOGMETA)
	fprintf(stderr, "addindom( ..., %s, %s, numinst=%d)\n",
	    pmInDomStr(indom), StrTimeval((__pmTimeval *)tp), numinst);
#endif


    if ((hp = __pmHashSearch((unsigned int)indom, &lcp->l_hashindom)) == NULL) {
	idp->next = NULL;
	sts = __pmHashAdd((unsigned int)indom, (void *)idp, &lcp->l_hashindom);
    }
    else {
	idp->next = (__pmLogInDom *)hp->data;
	hp->data = (void *)idp;
	sts = 0;
    }
    return sts;
}
Пример #5
0
static int
refresh_net_dev_hw_addr(pmInDom indom)
{
    int sts;
    DIR *dp;
    char *devname;
    struct dirent *dentry;
    char path[MAXPATHLEN];
    net_addr_t *netip;

    static uint32_t cache_err;

    snprintf(path, sizeof(path), "%s/sys/class/net", linux_statspath);
    if ((dp = opendir(path)) != NULL) {
	while ((dentry = readdir(dp)) != NULL) {
	    if (dentry->d_name[0] == '.')
		continue;
	    devname = dentry->d_name;
	    sts = pmdaCacheLookupName(indom, devname, NULL, (void **)&netip);
	    if (sts == PM_ERR_INST || (sts >= 0 && netip == NULL)) {
		/* first time since re-loaded, else new one */
		netip = (net_addr_t *)calloc(1, sizeof(net_addr_t));
	    }
	    else if (sts < 0) {
		if (cache_err++ < 10) {
		    fprintf(stderr, "refresh_net_dev_hw_addr: "
				"pmdaCacheLookupName(%s, %s, ...) failed: %s\n",
			pmInDomStr(indom), devname, pmErrStr(sts));
		}
		continue;
	    }
	    if ((sts = pmdaCacheStore(indom, PMDA_CACHE_ADD, devname, (void *)netip)) < 0) {
		if (cache_err++ < 10) {
		    fprintf(stderr, "refresh_net_dev_hw_addr: "
				"pmdaCacheStore(%s, PMDA_CACHE_ADD, %s, "
				PRINTF_P_PFX "%p) failed: %s\n",
			    pmInDomStr(indom), devname, netip, pmErrStr(sts));
		}
		continue;
	    }

	    refresh_net_hw_addr(devname, netip);
	}
	closedir(dp);
    }
    return 0;
}
Пример #6
0
int
QmcContext::lookupInDom(QmcDesc *descPtr, uint_t& indom)
{
    int i, sts;
    QmcIndom *indomPtr;

    if ((sts = pmUseContext(my.context)) < 0)
        return sts;

    indom = UINT_MAX;
    if (descPtr->desc().indom != PM_INDOM_NULL) {
        for (i = 0; i < my.indoms.size(); i++)
            if (my.indoms[i]->id() == (int)descPtr->desc().indom)
                break;
        if (i == my.indoms.size()) {
            indomPtr = new QmcIndom(my.source->type(), *descPtr);
            if (indomPtr->status() < 0) {
                sts = indomPtr->status();
                delete indomPtr;
                return sts;
            }
            my.indoms.append(indomPtr);
            indom = my.indoms.size() - 1;
            if (pmDebug & DBG_TRACE_PMC) {
                QTextStream cerr(stderr);
                cerr << "QmcContext::lookupInDom: Add indom for "
                     << pmInDomStr(indomPtr->id()) << endl;
            }
        }
        else {
            indomPtr = my.indoms[i];
            indom = i;
            if (pmDebug & DBG_TRACE_PMC) {
                QTextStream cerr(stderr);
                cerr << "QmcContext::lookupInDom: Reusing indom "
                     << pmInDomStr(indomPtr->id()) << endl;
            }
        }
    }
    return 0;
}
Пример #7
0
/*
 * we only ever have one metric
 */
static void
mydump(pmDesc *dp, pmValueSet *vsp, char *indent)
{
    int		j;
    char	*p;

    if (indent != NULL)
        printf("%s", indent);
    if (vsp->numval == 0) {
        printf("No value(s) available!\n");
        return;
    }
    else if (vsp->numval < 0) {
        printf("Error: %s\n", pmErrStr(vsp->numval));
        return;
    }

    for (j = 0; j < vsp->numval; j++) {
        pmValue	*vp = &vsp->vlist[j];
        if (dp->indom != PM_INDOM_NULL) {
            if ((p = lookup(dp->indom, vp->inst)) == NULL) {
                if (p_force) {
                    /* the instance disappeared; ignore it */
                    printf("    inst [%d \"%s\"]\n", vp->inst, "DISAPPEARED");
                    continue;
                }
                else {
                    /* report the error and give up */
                    printf("pmNameIndom: indom=%s inst=%d: %s\n",
                           pmInDomStr(dp->indom), vp->inst, pmErrStr(PM_ERR_INST));
                    printf("    inst [%d]", vp->inst);
                }
            }
            else
                printf("    inst [%d or \"%s\"]", vp->inst, p);
        }
        else
            printf("   ");
        printf(" value ");
        pmPrintValue(stdout, vsp->valfmt, dp->type, vp, 1);
        putchar('\n');
        if (!events)
            continue;
        if (dp->type == PM_TYPE_HIGHRES_EVENT)
            myeventdump(vsp, j, 1);
        else if (dp->type == PM_TYPE_EVENT)
            myeventdump(vsp, j, 0);
    }
}
Пример #8
0
void
dodso(int pdu)
{
    int			sts = 0;		/* initialize to pander to gcc */
    int			length;
    pmDesc		desc;
    pmDesc		*desc_list = NULL;
    pmResult		*result;
    __pmInResult	*inresult;
    int			i;
    int			j;
    char		*buffer;
    struct timeval	start;
    struct timeval	end;
    char		name[32];
    char		**namelist;
    int			*statuslist;
    pmID		pmid;

    if (timer != 0)
        __pmtimevalNow(&start);

    switch (pdu) {

    case PDU_DESC_REQ:
        printf("PMID: %s\n", pmIDStr(param.pmid));
        if ((sts = dodso_desc(param.pmid, &desc)) >= 0)
            __pmPrintDesc(stdout, &desc);
        else
            printf("Error: DSO desc() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_FETCH:
        printf("PMID(s):");
        for (i = 0; i < param.numpmid; i++)
            printf(" %s", pmIDStr(param.pmidlist[i]));
        putchar('\n');

        if (get_desc) {
            desc_list = (pmDesc *)malloc(param.numpmid * sizeof(pmDesc));
            if (desc_list == NULL) {
                printf("Error: DSO fetch() failed: %s\n", pmErrStr(ENOMEM));
                return;
            }
            for (i = 0; i < param.numpmid; i++) {
                if ((sts = dodso_desc(param.pmidlist[i], &desc_list[i])) < 0) {
                    printf("Error: DSO desc() failed: %s\n", pmErrStr(sts));
                    free(desc_list);
                    return;
                }
            }
        }
        sts = 0;
        if (profile_changed) {
#ifdef PCP_DEBUG
            if (pmDebug & DBG_TRACE_PDU)
                fprintf(stderr, "DSO profile()\n");
#endif
            sts = dispatch.version.any.profile(profile, dispatch.version.any.ext);
            if (sts < 0)
                printf("Error: DSO profile() failed: %s\n", pmErrStr(sts));
            else
                profile_changed = 0;
        }
        if (sts >= 0) {
#ifdef PCP_DEBUG
            if (pmDebug & DBG_TRACE_PDU)
                fprintf(stderr, "DSO fetch()\n");
#endif
            sts = dispatch.version.any.fetch(param.numpmid, param.pmidlist,
                                             &result, dispatch.version.any.ext);
            if (sts >= 0) {
                if (desc_list)
                    _dbDumpResult(stdout, result, desc_list);
                else
                    __pmDumpResult(stdout, result);
                /*
                 * DSO PMDA will manage the pmResult skelton, but
                 * we need to free the pmValueSets and values here
                 */
                __pmFreeResultValues(result);
            }
            else {
                printf("Error: DSO fetch() failed: %s\n", pmErrStr(sts));
            }
        }
        if (desc_list)
            free(desc_list);
        break;

    case PDU_INSTANCE_REQ:
        printf("pmInDom: %s\n", pmInDomStr(param.indom));
#ifdef PCP_DEBUG
        if (pmDebug & DBG_TRACE_PDU)
            fprintf(stderr, "DSO instance()\n");
#endif

        sts = dispatch.version.any.instance(param.indom, param.number,
                                            param.name, &inresult,
                                            dispatch.version.any.ext);
        if (sts >= 0)
            printindom(stdout, inresult);
        else
            printf("Error: DSO instance() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_RESULT:

        printf("PMID: %s\n", pmIDStr(param.pmid));
        printf("Getting description...\n");
        desc_list = &desc;
        if ((sts = dodso_desc(param.pmid, desc_list)) < 0) {
            printf("Error: DSO desc() failed: %s\n", pmErrStr(sts));
            return;
        }

        if (profile_changed) {
            printf("Sending Profile...\n");
            sts = dispatch.version.any.profile(profile, dispatch.version.any.ext);
            if (sts < 0) {
                printf("Error: DSO profile() failed: %s\n", pmErrStr(sts));
                return;
            }
            else
                profile_changed = 0;
        }

        printf("Getting Result Structure...\n");
        sts = dispatch.version.any.fetch(1, &(desc.pmid), &result,
                                         dispatch.version.any.ext);
        if (sts < 0) {
            printf("Error: DSO fetch() failed: %s\n", pmErrStr(sts));
            return;
        }

#ifdef PCP_DEBUG
        else if (pmDebug & DBG_TRACE_FETCH)
            _dbDumpResult(stdout, result, desc_list);
#endif

        sts = fillResult(result, desc.type);
        if (sts < 0) {
            pmFreeResult(result);
            return;
        }

        sts = dispatch.version.any.store(result, dispatch.version.any.ext);
        if (sts < 0)
            printf("Error: DSO store() failed: %s\n", pmErrStr(sts));

        break;

    case PDU_TEXT_REQ:
        if (param.number == PM_TEXT_PMID) {
            printf("PMID: %s\n", pmIDStr(param.pmid));
            i = param.pmid;
        }
        else {
            printf("pmInDom: %s\n", pmInDomStr(param.indom));
            i = param.indom;
        }

        for (j = 0; j < 2; j++) {

            if (j == 0)
                param.number |= PM_TEXT_ONELINE;
            else {
                param.number &= ~PM_TEXT_ONELINE;
                param.number |= PM_TEXT_HELP;
            }

            sts = dispatch.version.any.text(i, param.number, &buffer, dispatch.version.any.ext);
            if (sts >= 0) {
                if (j == 0) {
                    if (*buffer != '\0')
                        printf("[%s]\n", buffer);
                    else
                        printf("[<no one line help text specified>]\n");
                }
                else if (*buffer != '\0')
                    printf("%s\n", buffer);
                else
                    printf("<no help text specified>\n");
            }
            else
                printf("Error: DSO text() failed: %s\n", pmErrStr(sts));
        }
        break;

    case PDU_PMNS_IDS:
        if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
            printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
            break;
        }
        printf("PMID: %s\n", pmIDStr(param.pmid));
        sts = dispatch.version.four.name(param.pmid, &namelist, dispatch.version.four.ext);
        if (sts > 0) {
            for (i = 0; i < sts; i++) {
                printf("   %s\n", namelist[i]);
            }
            free(namelist);
        }
        else if (sts == 0)
            printf("Warning: DSO name() returns 0\n");
        else
            printf("Error: DSO name() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_PMNS_NAMES:
        if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
            printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
            break;
        }
        printf("Metric: %s\n", param.name);
        sts = dispatch.version.four.pmid(param.name, &pmid, dispatch.version.four.ext);
        if (sts >= 0)
            printf("   %s\n", pmIDStr(pmid));
        else
            printf("Error: DSO pmid() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_PMNS_CHILD:
        if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
            printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
            break;
        }
        printf("Metric: %s\n", param.name);
        sts = dispatch.version.four.children(param.name, 0, &namelist, &statuslist, dispatch.version.four.ext);
        if (sts > 0) {
            for (i = 0; i < sts; i++) {
                printf("   %8.8s %s\n", statuslist[i] == 1 ? "non-leaf" : "leaf", namelist[i]);
            }
            free(namelist);
            free(statuslist);
        }
        else if (sts == 0)
            printf("Warning: DSO children() returns 0\n");
        else
            printf("Error: DSO children() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_PMNS_TRAVERSE:
        if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
            printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
            break;
        }
        printf("Metric: %s\n", param.name);
        sts = dispatch.version.four.children(param.name, 1, &namelist, &statuslist, dispatch.version.four.ext);
        if (sts > 0) {
            for (i = 0; i < sts; i++) {
                printf("   %8.8s %s\n", statuslist[i] == 1 ? "non-leaf" : "leaf", namelist[i]);
            }
            free(namelist);
            free(statuslist);
        }
        else if (sts == 0)
            printf("Warning: DSO children() returns 0\n");
        else
            printf("Error: DSO children() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_AUTH:
        if (dispatch.comm.pmda_interface < PMDA_INTERFACE_6) {
            printf("Error: PMDA Interface %d does not support authentication\n", dispatch.comm.pmda_interface);
            break;
        }
        j = param.number;			/* attribute key */
        buffer = param.name;		/* attribute value */
        if (buffer)
            length = strlen(buffer) + 1;	/* length of value */
        else
            length = 0;
        i = 0;				/* client ID */

        __pmAttrKeyStr_r(j, name, sizeof(name)-1);
        name[sizeof(name)-1] = '\0';

        printf("Attribute: %s=%s\n", name, buffer ? buffer : "''");
        sts = dispatch.version.six.attribute(i, j, buffer, length, dispatch.version.six.ext);
        if (sts >= 0)
            printf("Success\n");
        else
            printf("Error: DSO attribute() failed: %s\n", pmErrStr(sts));
        break;

    default:
        printf("Error: DSO PDU (%s) botch!\n", __pmPDUTypeStr(pdu));
        break;
    }

    if (sts >= 0 && timer != 0) {
        __pmtimevalNow(&end);
        printf("Timer: %f seconds\n", __pmtimevalSub(&end, &start));
    }
}
Пример #9
0
Файл: indom.c Проект: Aconex/pcp
void
doindom(pmResult *rp)
{
    pmValueSet		*vsp;
    int			i;
    int			j;
    int			needti = 0;
    int			need;
    metric_t		*mp = NULL;
    int			*instlist;
    char		**namelist;
    int			sts;

    for (i = 0; i < rp->numpmid; i++) {
	vsp = rp->vset[i];
	if (vsp->numval <= 0)
	    continue;

	/*
	 * pmidlist[] and rp->vset[]->pmid may not be in 1:1
	 * correspondence because we come here after rewrite() has
	 * been called ... search for matching pmid
	 */
	for (j = 0; j < numpmid; j++) {
	    if (pmidlist[j] == vsp->pmid) {
		mp = &metriclist[j];
		break;
	    }
	}
	if (mp == NULL) {
	    fprintf(stderr,
		"%s: doindom: Arrgh, unexpected PMID %s @ vset[%d]\n",
		    pmProgname, pmIDStr(vsp->pmid), i);
	    __pmDumpResult(stderr, rp);
	    exit(1);
	}
	if (mp->idp == NULL)
	    continue;

	if ((sts = pmGetInDom(mp->idp->indom, &instlist, &namelist)) < 0) {
	    fprintf(stderr,
		"%s: doindom: pmGetInDom (%s) failed: %s\n",
		    pmProgname, pmInDomStr(mp->idp->indom), pmErrStr(sts));
	    exit(1);
	}

	need = 1;
	/*
	 * Need to output the indom if the number of instances changes
	 * or the set of instance ids are not the same from the last
	 * time.
	 */
	if (sts == mp->idp->numinst) {
	    for (j = 0; j < mp->idp->numinst; j++) {
		if (mp->idp->inst[j] != instlist[j])
		    break;
	    }
	    if (j == mp->idp->numinst) {
		/*
		 * Do we need to check the namelist elts as well, e.g.
		 * using strcmp()?
		 * Not at this stage ... if the instance ids are all the
		 * same, then only a very odd (and non-compliant) PMDA
		 * would change the mapping from id to name on the fly
		 */
		need = 0;
	    }
	}

	if (need) {
#if PCP_DEBUG
	    if (pmDebug & DBG_TRACE_APPL0) {
		fprintf(stderr, "Add metadata: indom %s for metric %s\n", pmInDomStr(mp->idp->indom), pmIDStr(vsp->pmid));
	    }
#endif
	    if (mp->idp->name != NULL) free(mp->idp->name);
	    if (mp->idp->inst != NULL) free(mp->idp->inst);
	    mp->idp->name = namelist;
	    mp->idp->inst = instlist;
	    mp->idp->numinst = sts;
	    if ((sts = __pmLogPutInDom(&logctl, mp->idp->indom, &current, mp->idp->numinst, mp->idp->inst, mp->idp->name)) < 0) {
		fprintf(stderr,
		    "%s: Error: failed to add pmInDom: indom %s (for pmid %s): %s\n",
			pmProgname, pmInDomStr(mp->idp->indom), pmIDStr(vsp->pmid), pmErrStr(sts));
		exit(1);
	    }
	    needti = 1;		/* requires a temporal index update */
	}
	else {
	    free(instlist);
	    free(namelist);
	}

    }

    if (needti) {
	fflush(logctl.l_mdfp);
	__pmLogPutIndex(&logctl, &current);
    }

}
Пример #10
0
/* Fill in current instances into given Context.
   Instances sorted by instance identifier.  */
static void
initinsts(Context *x)
{
    int      *ip;
    char     **np;
    InstPair *pp;
    int      n;
    int      e;
    int      i;

    if (x->desc.indom == PM_INDOM_NULL)
	x->inum = 0;
    else {

	/* fill in instance ids for given profile */
	if (! x->iall) {
	    n = x->inum;
	    np = x->inames;
	    ip = (int *)malloc(n * sizeof(int));
	    if (ip == NULL) {
		__pmNoMem("pmval.ip", n * sizeof(int), PM_FATAL_ERR);
	    }
	    x->iids = ip;
	    for (i = 0; i < n; i++) {
		if (opts.context == PM_CONTEXT_ARCHIVE)
		    e = pmLookupInDomArchive(x->desc.indom, *np);
		else
		    e = pmLookupInDom(x->desc.indom, *np);
		if (e < 0) {
            	    printf("%s: instance %s not available\n", pmProgname, *np);
            	    exit(EXIT_FAILURE);
		}
		*ip = e;
		np++;  ip++;
	    }
	    ip = x->iids;
	    np = x->inames;
	    if ((e = pmAddProfile(x->desc.indom, x->inum, x->iids)) < 0) {
		fprintf(stderr, "%s: pmAddProfile: %s\n", pmProgname, pmErrStr(e));
		exit(EXIT_FAILURE);
	    }
	}

	/* find all available instances */
	else {
	    if (opts.context == PM_CONTEXT_ARCHIVE)
		n = pmGetInDomArchive(x->desc.indom, &ip, &np);
	    else
		n = pmGetInDom(x->desc.indom, &ip, &np);
	    if (n < 0) {
                fprintf(stderr, "%s: pmGetInDom(%s): %s\n", pmProgname, pmInDomStr(x->desc.indom), pmErrStr(n));
                exit(EXIT_FAILURE);
	    }
            x->inum = n;
	    x->iids = ip;
	    x->inames = np;
	}

	/* build InstPair list and sort */
	pp = (InstPair *)malloc(n * sizeof(InstPair));
	if (pp == NULL) {
	    __pmNoMem("pmval.pp", n * sizeof(InstPair), PM_FATAL_ERR);
	}
	x->ipairs = pp;
	for (i = 0; i < n; i++) {
	    pp->id = *ip;
	    pp->name = *np;
	    ip++;  np++; pp++;
	}
	qsort(x->ipairs, (size_t)n, sizeof(InstPair), compare);
    }
}
Пример #11
0
void
QmcMetric::extractValues(pmValueSet const* set)
{
    int i, j, index, inst;
    pmValue const *value = NULL;
    bool found;
    QmcIndom *indomPtr = indom();

    Q_ASSERT(set->pmid == desc().id());

    if (set->numval > 0) {
	if (hasIndom()) {
	    // If the number of instances are not the expected number
	    // then mark the indom as changed
	    if (!my.explicitInst && (my.values.size() != set->numval)) {
		if (pmDebug & DBG_TRACE_INDOM) {
		    QTextStream cerr(stderr);
		    cerr << "QmcMetric::extractValues: implicit indom "
			 << pmInDomStr(indomPtr->id()) << " changed ("
			 << set->numval << " != " << my.values.size() << ')'
			 << endl;
		}
		indomPtr->hasChanged();
		updateIndom();
	    }

	    for (i = 0; i < numInst(); i++) {
		QmcMetricValue &valueRef = my.values[i];
		inst = my.values[i].instance();
		index = indomPtr->index(inst);
		found = false;

		// If the index is within range, try it first
		if (index >= 0 && index < set->numval) {
		    value = &(set->vlist[index]);

		    // Found it in the same spot as last time
		    if (value->inst == indomPtr->inst(inst))
			found = true;
		}

		// Search for it from the top
		for (j = 0; found == false && j < set->numval; j++) {
		    if (set->vlist[j].inst == indomPtr->inst(inst)) {
			index = j;
			value = &(set->vlist[j]);
			indomPtr->setIndex(inst, j);
			found = true;
		    }
		}

		if (found) {
		    if (real())
			extractNumericMetric(set, value, valueRef);
		    else if (!event())
			extractArrayMetric(set, value, valueRef);
		    else
			extractEventMetric(set, index, valueRef);
		}
		else {	// Cannot find it
		    if (pmDebug & DBG_TRACE_OPTFETCH) {
			QTextStream cerr(stderr);
			cerr << "QmcMetric::extractValues: "
			     << spec(true, true, i) << ": "
			     << pmErrStr(PM_ERR_VALUE) << endl;
		    }

		    if (valueRef.previousError() != PM_ERR_VALUE)
			indomPtr->hasChanged();

		    valueRef.setCurrentError(PM_ERR_VALUE);
		}
	    }
	}
	else if (set->numval == 1) {
	    // We have no instances at this point in time
	    if (my.values.size() == 0 && hasInstances())
		indomPtr->hasChanged();
	    else {
		QmcMetricValue &valueRef = my.values[0];
		value = &(set->vlist[0]);

		if (real())
		    extractNumericMetric(set, value, valueRef);
		else if (!event())
		    extractArrayMetric(set, value, valueRef);
		else
		    extractEventMetric(set, 0, valueRef);
	    }
	}
	else {	// Did not expect any instances
	    if (pmDebug & DBG_TRACE_OPTFETCH) {
		QTextStream cerr(stderr);
		cerr << "QmcMetric::extractValues: " << spec(true) 
		     << " is a singular metric but result contained "
		     << set->numval << " values" << endl;
	    }
	    setError(PM_ERR_VALUE);
	}
    }
    else if (set->numval == 0) {
	if (!(hasInstances() && numInst() == 0)) {
	    if (pmDebug & DBG_TRACE_OPTFETCH) {
		QTextStream cerr(stderr);
		cerr << "QmcMetric::extractValues: numval == 0: "
		     << spec(true, false) << ": " << pmErrStr(PM_ERR_VALUE)
		     << endl;
	    }
	    setError(PM_ERR_VALUE);
	    if (hasInstances())
		indomPtr->hasChanged();
	}
    }
    else {
	if (pmDebug & DBG_TRACE_OPTFETCH) {
	    QTextStream cerr(stderr);
	    cerr << "QmcMetric::extractValues: numval < 0: "
		 << spec(true, false)
		 << ": " << pmErrStr(set->numval) << endl;
	}
	setError(set->numval);
	if (hasInstances())
	    indomPtr->hasChanged();
    }
}
Пример #12
0
int
refresh_proc_net_dev(pmInDom indom, linux_container_t *container)
{
    static uint32_t	gen;	/* refresh generation number */
    static uint32_t	cache_err;	/* throttle messages */
    char		buf[1024];
    FILE		*fp;
    char		*p, *v;
    int			j, sts;
    net_interface_t	*netip;

    if ((fp = linux_statsfile("/proc/net/dev", buf, sizeof(buf))) == NULL)
    	return -oserror();

    if (gen == 0) {
	/*
	 * first time, reload cache from external file, and force any
	 * subsequent changes to be saved
	 */
	pmdaCacheOp(indom, PMDA_CACHE_LOAD);
	gen++;
    }

    /*
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo: 4060748   39057    0    0    0     0          0         0  4060748   39057    0    0    0     0       0          0
  eth0:       0  337614    0    0    0     0          0         0        0  267537    0    0    0 27346      62          0
     */

    pmdaCacheOp(indom, PMDA_CACHE_INACTIVE);

    while (fgets(buf, sizeof(buf), fp) != NULL) {
	if ((p = v = strchr(buf, ':')) == NULL)
	    continue;
	*p = '\0';
	for (p=buf; *p && isspace((int)*p); p++) {;}

	sts = pmdaCacheLookupName(indom, p, NULL, (void **)&netip);
	if (sts == PM_ERR_INST || (sts >= 0 && netip == NULL)) {
	    /* first time since re-loaded, else new one */
	    netip = (net_interface_t *)calloc(1, sizeof(net_interface_t));
#if PCP_DEBUG
	    if (pmDebug & DBG_TRACE_LIBPMDA) {
		fprintf(stderr, "refresh_proc_net_dev: initialize \"%s\"\n", p);
	    }
#endif
	}
	else if (sts < 0) {
	    if (cache_err++ < 10) {
		fprintf(stderr, "refresh_proc_net_dev: pmdaCacheLookupName(%s, %s, ...) failed: %s\n",
		    pmInDomStr(indom), p, pmErrStr(sts));
	    }
	    continue;
	}
	if ((sts = pmdaCacheStore(indom, PMDA_CACHE_ADD, p, (void *)netip)) < 0) {
	    if (cache_err++ < 10) {
		fprintf(stderr, "refresh_proc_net_dev: pmdaCacheStore(%s, PMDA_CACHE_ADD, %s, " PRINTF_P_PFX "%p) failed: %s\n",
		    pmInDomStr(indom), p, netip, pmErrStr(sts));
	    }
	    continue;
	}

	memset(&netip->ioc, 0, sizeof(netip->ioc));
	for (p=v, j=0; j < PROC_DEV_COUNTERS_PER_LINE; j++) {
	    for (; !isdigit((int)*p); p++) {;}
	    sscanf(p, "%llu", (long long unsigned int *)&netip->counters[j]);
	    for (; !isspace((int)*p); p++) {;}
	}
    }

    /* success */
    fclose(fp);

    if (!container)
	pmdaCacheOp(indom, PMDA_CACHE_SAVE);
    return 0;
}
Пример #13
0
static void
func(void)
{
    int			sts;
    char		**children;
    char		*p;

    if ((sts = pmUseContext(ctx)) < 0) {
	printf("pmUseContext(%d): %s\n", ctx, pmErrStr(sts));
	pthread_exit(NULL);
    }

    /*
     * expect this to fail for the second thread through when
     * using PM_CONTEXT_LOCAL
     */
    if ((sts = pmDupContext()) < 0)
	printf("pmDupContext: %s\n", pmErrStr(sts));
    else
	printf("pmDupContext: -> %d\n", sts);

    if ((sts = pmUseContext(ctx)) < 0) {
	printf("pmUseContext(%d): %s\n", ctx, pmErrStr(sts));
	pthread_exit(NULL);
    }
    else
	printf("pmUseContext(%d) -> %d\n", ctx, sts);

    if ((sts = pmLookupName(1, namelist, pmidlist)) < 0)
	printf("pmLookupName: %s\n", pmErrStr(sts));
    else
	printf("pmLookupName: -> %s\n", pmIDStr(pmidlist[0]));

    pthread_barrier_wait(&barrier);

    if (pmidlist[0] == 0)
	pthread_exit("Loser failed to get pmid!");

    if ((sts = pmGetPMNSLocation()) < 0)
	printf("pmGetPMNSLocation: %s\n", pmErrStr(sts));
    else
	printf("pmGetPMNSLocation: -> %d\n", sts);

    /* leaf node, expect no children */
    if ((sts = pmGetChildrenStatus(namelist[0], &children, NULL)) < 0)
	printf("pmGetChildrenStatus: %s\n", pmErrStr(sts));
    else
	printf("pmGetChildrenStatus: -> %d\n", sts);

    if ((sts = pmLookupDesc(pmidlist[0], &desc)) < 0)
	printf("pmLookupDesc: %s\n", pmErrStr(sts));
    else
	printf("pmLookupDesc: -> %s type=%s indom=%s\n", pmIDStr(desc.pmid), pmTypeStr(desc.type), pmInDomStr(desc.indom));

    pthread_barrier_wait(&barrier);

    if (desc.pmid == 0)
	pthread_exit("Loser failed to get pmDesc!");

    if ((sts = pmLookupText(pmidlist[0], PM_TEXT_ONELINE, &p)) < 0)
	printf("pmLookupText: %s\n", pmErrStr(sts));
    else
	printf("pmLookupText: -> %s\n", p);

    if ((sts = pmGetInDom(desc.indom, &instance, &instname)) < 0)
	printf("pmGetInDom: %s: %s\n", pmInDomStr(desc.indom), pmErrStr(sts));
    else
	printf("pmGetInDom: -> %d\n", sts);

    pthread_barrier_wait(&barrier);

    if (instance == NULL)
	pthread_exit("Loser failed to get indom!");

    if ((sts = pmNameInDom(desc.indom, instance[0], &p)) < 0)
	printf("pmNameInDom: %s\n", pmErrStr(sts));
    else
	printf("pmNameInDom: %d -> %s\n", instance[0], p);

    if ((sts = pmLookupInDom(desc.indom, instname[0])) < 0)
	printf("pmLookupInDom: %s\n", pmErrStr(sts));
    else
	printf("pmLookupInDom: %s -> %d\n", instname[0], sts);

    if ((sts = pmFetch(1, pmidlist, &rp)) < 0)
	printf("pmFetch: %s\n", pmErrStr(sts));
    else
	printf("pmFetch: -> OK\n");

    pthread_barrier_wait(&barrier);

    if (rp == NULL)
	pthread_exit("Loser failed to get pmResult!");

    if ((sts = pmStore(rp)) < 0)
	printf("pmStore: %s\n", pmErrStr(sts));
    else
	printf("pmStore: -> OK\n");

    pthread_exit(NULL);
}
Пример #14
0
static void
_b(void)
{
    int		i;
    int		j;
    int		inst;
    int		sts;
    char	cmd[2*MAXPATHLEN+30];

    indom = pmInDom_build(FORQA, 8);

    pmsprintf(cmd, sizeof(cmd), "rm -f %s/config/pmda/%s", pmGetConfig("PCP_VAR_DIR"), pmInDomStr(indom));
    sts = system(cmd);
    if (sts != 0)
	fprintf(stderr, "Warning: %s: exit status %d\n", cmd, sts);
    pmsprintf(cmd, sizeof(cmd), "[ -f %s/config/pmda/%s ] || exit 0; cat %s/config/pmda/%s", pmGetConfig("PCP_VAR_DIR"), pmInDomStr(indom), pmGetConfig("PCP_VAR_DIR"), pmInDomStr(indom));

    fprintf(stderr, "\nPopulate the instance domain ...\n");
    j = 1;
    for (i = 0; i < 20; i++) {
	strncpy(nbuf, xxx, ncount+3);
	pmsprintf(nbuf, sizeof(nbuf), "%03d", ncount);
	ncount++;
        inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, nbuf, (void *)((__psint_t)(0xbeef0000+ncount)));
	if (inst < 0)
	    fprintf(stderr, "PMDA_CACHE_ADD failed for \"%s\": %s\n", nbuf, pmErrStr(inst));
	else if (i > 14) {
	    sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE);
	    fprintf(stderr, "Save -> %d\n", sts);
	}
	if (i == j) {
	    j <<= 1;
	    inst = pmdaCacheStore(indom, PMDA_CACHE_HIDE, nbuf, NULL);
	    if (inst < 0)
		fprintf(stderr, "PMDA_CACHE_HIDE failed for \"%s\": %s\n", nbuf, pmErrStr(inst));
	}
	if (i == 6 || i == 13) {
	    fprintf(stderr, "Save ...\n");
	    fprintf(stderr, "Before:\n");
	    sts = system(cmd);
	    if (sts != 0)
		fprintf(stderr, "Warning: _b:1: %s: exit status %d\n", cmd, sts);
	    sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE);
	    fprintf(stderr, "return -> %d", sts);
	    if (sts < 0) fprintf(stderr, ": %s", pmErrStr(sts));
	    fputc('\n', stderr);
	    fprintf(stderr, "After:\n");
	    sts = system(cmd);
	    if (sts != 0)
		fprintf(stderr, "Warning: _b:2: %s: exit status %d\n", cmd, sts);
	}
	if (i == 14) {
	    fprintf(stderr, "Start save after changes ...\n");
	}
	if (i > 14) {
	    sts = system(cmd);
	    if (sts != 0)
		fprintf(stderr, "Warning: _b:3: %s: exit status %d\n", cmd, sts);
	}
    }
    __pmdaCacheDump(stderr, indom, 0);
    strncpy(nbuf, xxx, 11+3);
    pmsprintf(nbuf, sizeof(nbuf), "%03d", 11);
    fprintf(stderr, "\nHide %s ...\n", nbuf);
    inst = pmdaCacheStore(indom, PMDA_CACHE_HIDE, nbuf, NULL);
    if (inst < 0)
	fprintf(stderr, "PMDA_CACHE_HIDE failed for \"%s\": %s\n", nbuf, pmErrStr(inst));
    sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE);
    fprintf(stderr, "Save -> %d\n", sts);
    sts = system(cmd);
    if (sts != 0)
	fprintf(stderr, "Warning: _b:4: %s: exit status %d\n", cmd, sts);
    fprintf(stderr, "Add %s ...\n", nbuf);
    inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, nbuf, (void *)((__psint_t)0xdeadbeef));
    if (inst < 0)
	fprintf(stderr, "PMDA_CACHE_ADD failed for \"%s\": %s\n", nbuf, pmErrStr(inst));
    sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE);
    fprintf(stderr, "Save -> %d\n", sts);
    sts = system(cmd);
    if (sts != 0)
	fprintf(stderr, "Warning: _b:5: %s: exit status %d\n", cmd, sts);
    fprintf(stderr, "Cull %s ...\n", nbuf);
    inst = pmdaCacheStore(indom, PMDA_CACHE_CULL, nbuf, NULL);
    if (inst < 0)
	fprintf(stderr, "PMDA_CACHE_CULL failed for \"%s\": %s\n", nbuf, pmErrStr(inst));
    sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE);
    fprintf(stderr, "Save -> %d\n", sts);
    sts = system(cmd);
    if (sts != 0)
	fprintf(stderr, "Warning: _b:6: %s: exit status %d\n", cmd, sts);
    fprintf(stderr, "Add %s ...\n", nbuf);
    inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, nbuf, (void *)((__psint_t)0xdeadbeef));
    if (inst < 0)
	fprintf(stderr, "PMDA_CACHE_ADD failed for \"%s\": %s\n", nbuf, pmErrStr(inst));
    sts = pmdaCacheOp(indom, PMDA_CACHE_SAVE);
    fprintf(stderr, "Save -> %d\n", sts);
    sts = system(cmd);
    if (sts != 0)
	fprintf(stderr, "Warning: _b:7: %s: exit status %d\n", cmd, sts);

}
Пример #15
0
static void
newentry(char *buf)
{
    int		n;
    char	*p;
    char	*end_name;
    char	end_c;
    char	*name;
    pmID	pmid;
    char	*start;
    int		warn = 0;
    int		i;

    /* skip leading white space ... */
    for (p = buf; isspace((int)*p); p++)
	;
    /* skip over metric name or indom spec ... */
    name = p;
    for (p = buf; *p != '\n' && !isspace((int)*p); p++)
	;
    end_c = *p;
    *p = '\0';	/* terminate metric name */
    end_name = p;

    if ((n = pmLookupName(1, &name, &pmid)) < 0) {
	/* apparently not a metric name */
	int	domain;
	int	cluster;
	int	item;
	int	serial;
	pmID	*pmidp;
	if (sscanf(buf, "%d.%d.%d", &domain, &cluster, &item) == 3) {
	    /* a numeric pmid */
	    __pmID_int	ii;
	    ii.domain = domain;
	    ii.cluster = cluster;
	    ii.item = item;
	    ii.flag = 0;
	    pmidp = (pmID *)&ii;
	    pmid = *pmidp;
	}
	else if (sscanf(buf, "%d.%d", &domain, &serial) == 2) {
	    /* an entry for an instance domain */
	    __pmInDom_int	ii;
	    ii.domain = domain;
	    ii.serial = serial;
	    /* set a bit here to disambiguate pmInDom from pmID */
	    ii.flag = 1;
	    pmidp = (pmID *)&ii;
	    pmid = *pmidp;
	}
	else {
	    fprintf(stderr, "%s: [%s:%d] %s: %s, entry abandoned\n",
		    pmProgname, filename, ln, buf, pmErrStr(n));
	    status = 2;
	    return;
	}
    }
    else {
	if (pmid == PM_ID_NULL) {
	    fprintf(stderr, "%s: [%s:%d] %s: unknown metric, entry abandoned\n",
		    pmProgname, filename, ln, name);
	    status = 2;
	    return;
	}
    }

    for (i = 0; i < thisindex; i++) {
	if (hindex[thisindex].pmid == pmid) {
	    __pmInDom_int	*kp = (__pmInDom_int *)&pmid;
	    fprintf(stderr, "%s: [%s:%d] duplicate key (", 
		    pmProgname, filename, ln);
	    if (kp->flag == 0)
		fprintf(stderr, "%s", pmIDStr(pmid));
	    else {
		kp->flag = 0;
		fprintf(stderr, "%s", pmInDomStr((pmInDom)pmid));
	    }
	    fprintf(stderr, ") entry abandoned\n");
	    status = 2;
	    return;
	}
    }

    if (++thisindex >= numindex) {
	if (numindex == 0)
	    numindex = 128;
	else
	    numindex *= 2;
	if ((hindex = (help_idx_t *)realloc(hindex, numindex * sizeof(hindex[0]))) == NULL) {
	    __pmNoMem("newentry", numindex * sizeof(hindex[0]), PM_FATAL_ERR);
	}
    }

    fprintf(f, "\n@ %s ", name);

    hindex[thisindex].pmid = pmid;
    hindex[thisindex].off_oneline = ftell(f);

    /* skip white space ... to start of oneline */
    *p = end_c;
    if (*p != '\n')
	p++;
    for ( ; *p != '\n' && isspace((int)*p); p++)
	;
    start = p;

    /* skip to end of line ... */
    for ( ; *p != '\n'; p++)
	;
    *p = '\0';
    p++;
    
    if (p - start == 1 && verbose) {
	fprintf(stderr, "%s: [%s:%d] %s: warning, null oneline\n",
	    pmProgname, filename, ln, name);
	warn = 1;
	if (!status) status = 1;
    }

    if (fwrite(start, sizeof(*start), p - start, f) != p - start || ferror(f)) {
	fprintf(stderr, "%s: [%s:%d] %s: write oneline failed, entry abandoned\n",
		pmProgname, filename, ln, name);
	thisindex--;
	status = 2;
	return;
    }

    hindex[thisindex].off_text = ftell(f);

    /* trim all but last newline ... */
    i = (int)strlen(p) - 1;
    while (i >= 0 && p[i] == '\n')
	i--;
    if (i < 0)
	i = 0;
    else {
	/* really have text ... p[i] is last non-newline char */
	i++;
	if (version == 1)
	    p[i++] = '\n';
    }
    p[i] = '\0';

    if (i == 0 && verbose) {
	fprintf(stderr, "%s: [%s:%d] %s: warning, null help\n",
	    pmProgname, filename, ln, name);
	warn = 1;
	if (!status) status = 1;
    }

    if (fwrite(p, sizeof(*p), i+1, f) != i+1 || ferror(f)) {
	fprintf(stderr, 
		"%s: [%s:%d] %s: write help failed, entry abandoned\n",
		pmProgname, filename, ln, name);
	thisindex--;
	status = 2;
	return;
    }

    if (verbose && warn == 0) {
	*end_name = '\0';
	fprintf(stderr, "%s\n", name);
	*end_name = end_c;
    }
}
Пример #16
0
int
main(int argc, char **argv)
{
    int		sts;
    int		c;
    int		help = 0;
    int		oneline = 0;
    char	*pmnsfile = PM_NS_DEFAULT;
    int		errflag = 0;
    int		aflag = 0;
    int		eflag = 0;
    int		allpmid = 0;
    int		allindom = 0;
    char	*filename;
    char	*tp;
    char	*name;
    int		id;
    int		next_type;
    char	*endnum;

    __pmSetProgname(argv[0]);

    while ((c = getopt(argc, argv, "D:eHin:Opv:?")) != EOF) {
	switch (c) {

	case 'D':	/* debug flag */
	    sts = __pmParseDebug(optarg);
	    if (sts < 0) {
		fprintf(stderr, "%s: unrecognized debug flag specification (%s)\n",
		    pmProgname, optarg);
		errflag++;
	    }
	    else
		pmDebug |= sts;
	    break;

	case 'e':	/* help text exists? */
	    eflag = 1;
	    break;

	case 'H':	/* help text */
	    help = 1;
	    break;

	case 'i':
	    aflag++;
	    allindom = 1;
	    break;

	case 'n':	/* alternative namespace file */
	    pmnsfile = optarg;
	    break;

	case 'O':	/* oneline text */
	    oneline = 1;
	    break;

	case 'p':
	    aflag++;
	    allpmid = 1;
	    break;

	case 'v':	/* version 2 only these days */
	    version = (int)strtol(optarg, &endnum, 10);
	    if (*endnum != '\0') {
		fprintf(stderr, "%s: -v requires numeric argument\n", pmProgname);
		errflag++;
	    }
	    if (version != 2) {
		fprintf(stderr 
                       ,"%s: deprecated option - only version 2 is supported\n"
                       , pmProgname);
		errflag++;
	    }
	    break;

	case '?':
	default:
	    errflag++;
	    break;
	}
    }

    if (optind == argc) {
	fprintf(stderr, "%s: missing helpfile argument\n\n", pmProgname);
	errflag = 1;
    }

    if (aflag && optind < argc-1) {
	fprintf(stderr, "%s: metricname arguments cannot be used with -i or -p\n\n",
	    pmProgname);
	errflag = 1;
    }

    if (aflag == 0 && optind == argc-1 && oneline+help != 0) {
	fprintf(stderr, "%s: -O or -H require metricname arguments or -i or -p\n\n",
	    pmProgname);
	errflag = 1;
    }

    if (eflag && (allpmid || allindom)) {
	fprintf(stderr, "%s: -e cannot be used with -i or -p\n\n",
	    pmProgname);
	errflag = 1;
    }

    if (errflag || optind >= argc) {
	fprintf(stderr,
"Usage: %s helpfile\n"
"       %s [options] helpfile [metricname ...]\n"
"\n"
"Options:\n"
"  -e           exists check, only report metrics with no help text\n"
"  -H           display verbose help text\n"
"  -i           process all the instance domains\n"
"  -n pmnsfile  use an alternative PMNS\n"
"  -O           display the one line help summary\n"
"  -p           process all the metrics (PMIDs)\n"
"  -v version   deprecated (only version 2 format supported)\n"
"\n"
"No options implies silently check internal integrity of the helpfile.\n",
		pmProgname, pmProgname);
	exit(1);
    }

    filename = argv[optind++];
    if ((handle = pmdaOpenHelp(filename)) < 0) {
	fprintf(stderr, "pmdaOpenHelp: failed to open \"%s\": ", filename);
	if (handle == -EINVAL)
	    fprintf(stderr, "Bad format, not version %d PCP help text\n", version);
	else
	    fprintf(stderr, "%s\n", pmErrStr(handle));
	exit(1);
    }

    if ((sts = pmLoadASCIINameSpace(pmnsfile, 1)) < 0) {
	fprintf(stderr, "pmLoadASCIINameSpace(%s, 1): %s\n", pmnsfile, pmErrStr(sts));
	exit(1);
    }

    if (help + oneline == 0 && (optind < argc || aflag))
	/* if metric names, -p or -i => -O is default */
	oneline = 1;

    if (optind == argc && aflag == 0)
	/* no metric names, process all entries */
	aflag = 1;

    if (eflag) {
	if (optind == argc) {
	    sts = pmTraversePMNS("", dometric);
	    if (sts < 0) {
		fprintf(stderr, "Error: pmTraversePMNS(\"\", ...): %s\n", pmErrStr(sts));
	    }
	}
	else {
	    for ( ; optind < argc; optind++) {
		sts = pmTraversePMNS(argv[optind], dometric);
		if (sts < 0)
		    fprintf(stderr, "Error: pmTraversePMNS(\"%s\", ...): %s\n", argv[optind], pmErrStr(sts));
	    }
	}
	exit(0);
    }

    while (optind < argc || aflag) {
	if (aflag) {
	    if (next(&id, &next_type) == 0)
		break;
#ifdef PCP_DEBUG
	    if ((pmDebug & DBG_TRACE_APPL0) && allindom+allpmid == 0)
		fprintf(stderr, "next_type=%d id=0x%x\n", next_type, id);
#endif
	    if (next_type == 2) {
		if (!allindom)
		    continue;
		printf("\nInDom %s:", pmInDomStr((pmInDom)id));
	    }
	    else {
		char		**names;
		if (!allpmid)
		    continue;

		printf("\nPMID %s", pmIDStr((pmID)id));
		sts = pmNameAll(id, &names);
		if (sts > 0) {
		    printf(" ");
		    __pmPrintMetricNames(stdout, sts, names, " or ");
		    free(names);
		}
		putchar(':');
	    }
	}
	else {
	    next_type = 1;
	    name = argv[optind++];
	    if ((sts = pmLookupName(1, &name, (pmID *)&id)) < 0) {
		printf("\n%s: %s\n", name, pmErrStr(sts));
		continue;
	    }
	    if (id == PM_ID_NULL) {
		printf("\n%s: unknown metric\n", name);
		continue;
	    }
	    printf("\nPMID %s %s:", pmIDStr((pmID)id), name);
	}

	if (oneline) {
	    if (next_type == 1)
		tp = pmdaGetHelp(handle, (pmID)id, PM_TEXT_ONELINE);
	    else
		tp = pmdaGetInDomHelp(handle, (pmInDom)id, PM_TEXT_ONELINE);
	    if (tp != NULL)
		printf(" %s", tp);
	    putchar('\n');
	}

	if (help) {
	    if (next_type == 1)
		tp = pmdaGetHelp(handle, (pmID)id, PM_TEXT_HELP);
	    else
		tp = pmdaGetInDomHelp(handle, (pmInDom)id, PM_TEXT_HELP);
	    if (tp != NULL && *tp)
		printf("%s\n", tp);
	}

    }

    return 0;
}