Exemple #1
0
static void
foo(FILE *f, char *fn, int i)
{
    int		sts;
    int		j;
    int		numinst;
    int		*inst;
    char	**name;
    char	*tmp;


    if (desclist[i].indom == PM_INDOM_NULL) {
	fprintf(f, "%s: %s: singular\n", fn, namelist[i]);
	return;
    }
    if ((sts = pmGetInDom(desclist[i].indom, &inst, &name)) < 0) {
	fprintf(f, "%s: %s: pmGetInDom Error: %s\n", fn, namelist[i], pmErrStr(sts));
	pthread_exit("botch");
    }
    numinst = sts;
    fprintf(f, "%s: %s: indom contains %d instances: ", fn, namelist[i], numinst);
    for (j = 0; j < numinst; j++) {
	if ((sts = pmNameInDom(desclist[i].indom, inst[j], &tmp)) < 0) {
	    fprintf(f, "\n%s: inst %d: pmNameInDom Error: %s\n", fn, inst[j], pmErrStr(sts));
	    pthread_exit("botch");
	}
	if (strcmp(tmp, name[j]) != 0) {
	    fprintf(f, "\n%s: inst %d: expecting \"%s\", got \"%s\"\n",  fn, inst[j], name[j], tmp);
	    pthread_exit("botch");
	}
	fputc('i', f);
	free(tmp);
    }
    fputc(' ', f);
    for (j = 0; j < numinst; j++) {
	if ((sts = pmLookupInDom(desclist[i].indom, name[j])) < 0) {
	    fprintf(f, "\n%s: inst \"%s\": pmLookupInDom Error: %s\n", fn, name[j], pmErrStr(sts));
	    pthread_exit("botch");
	}
	if (sts != inst[j]) {
	    fprintf(f, "\n%s: inst \"%s\": expecting %d, got %d\n",  fn, name[j], inst[j], sts);
	    pthread_exit("botch");
	}
	fputc('n', f);
    }
    fputc('\n', f);

    free(inst);
    free(name);
}
Exemple #2
0
static void
get_sample(info_t *ip)
{
    static pmResult	*crp = NULL;	/* current */
    static pmResult	*prp = NULL;	/* prior */
    static int		first = 1;
    static int		numpmid;
    static pmID		*pmidlist;
    static pmDesc	*desclist;
    static int		inst1;
    static int		inst15;
    static pmUnits	mbyte_scale;

    int			sts;
    int			i;
    float		u;
    pmAtomValue		tmp;
    pmAtomValue		atom;
    double		dt;

    if (first) {
	/* first time initialization */
	mbyte_scale.dimSpace = 1;
	mbyte_scale.scaleSpace = PM_SPACE_MBYTE;

	numpmid = sizeof(pmclient_sample) / sizeof(char *);
	if ((pmidlist = (pmID *)malloc(numpmid * sizeof(pmidlist[0]))) == NULL) {
	    fprintf(stderr, "%s: get_sample: malloc: %s\n", pmProgname, osstrerror());
	    exit(1);
	}
	if ((desclist = (pmDesc *)malloc(numpmid * sizeof(desclist[0]))) == NULL) {
	    fprintf(stderr, "%s: get_sample: malloc: %s\n", pmProgname, osstrerror());
	    exit(1);
	}
	if ((sts = pmLookupName(numpmid, pmclient_sample, pmidlist)) < 0) {
	    printf("%s: pmLookupName: %s\n", pmProgname, pmErrStr(sts));
	    for (i = 0; i < numpmid; i++) {
		if (pmidlist[i] == PM_ID_NULL)
		    fprintf(stderr, "%s: metric \"%s\" not in name space\n", pmProgname, pmclient_sample[i]);
	    }
	    exit(1);
	}
	for (i = 0; i < numpmid; i++) {
	    if ((sts = pmLookupDesc(pmidlist[i], &desclist[i])) < 0) {
		fprintf(stderr, "%s: cannot retrieve description for metric \"%s\" (PMID: %s)\nReason: %s\n",
		    pmProgname, pmclient_sample[i], pmIDStr(pmidlist[i]), pmErrStr(sts));
		exit(1);
	    }
	}
    }

    /* fetch the current metrics */
    if ((sts = pmFetch(numpmid, pmidlist, &crp)) < 0) {
	fprintf(stderr, "%s: pmFetch: %s\n", pmProgname, pmErrStr(sts));
	exit(1);
    }

    /*
     * minor gotcha ... for archives, it helps to do the first fetch of
     * real data before interrogating the instance domains ... this
     * forces us to be "after" the first batch of instance domain info
     * in the meta data files
     */
    if (first) {
	/*
	 * from now on, just want the 1 minute and 15 minute load averages,
	 * so limit the instance profile for this metric
	 */
	pmDelProfile(desclist[LOADAV].indom, 0, NULL);	/* all off */
	if ((inst1 = pmLookupInDom(desclist[LOADAV].indom, "1 minute")) < 0) {
	    fprintf(stderr, "%s: cannot translate instance for 1 minute load average\n", pmProgname);
	    exit(1);
	}
	pmAddProfile(desclist[LOADAV].indom, 1, &inst1);
	if ((inst15 = pmLookupInDom(desclist[LOADAV].indom, "15 minute")) < 0) {
	    fprintf(stderr, "%s: cannot translate instance for 15 minute load average\n", pmProgname);
	    exit(1);
	}
	pmAddProfile(desclist[LOADAV].indom, 1, &inst15);

	first = 0;
    }

    /* if the second or later sample, pick the results apart */
    if (prp !=  NULL) {
	
	dt = __pmtimevalSub(&crp->timestamp, &prp->timestamp);
	ip->cpu_util = 0;
	ip->peak_cpu_util = -1;	/* force re-assignment at first CPU */
	for (i = 0; i < ncpu; i++) {
	    pmExtractValue(crp->vset[CPU_USR]->valfmt,
			   &crp->vset[CPU_USR]->vlist[i],
			   desclist[CPU_USR].type, &atom, PM_TYPE_FLOAT);
	    u = atom.f;
	    pmExtractValue(prp->vset[CPU_USR]->valfmt,
			   &prp->vset[CPU_USR]->vlist[i],
			   desclist[CPU_USR].type, &atom, PM_TYPE_FLOAT);
	    u -= atom.f;
	    pmExtractValue(crp->vset[CPU_SYS]->valfmt,
			   &crp->vset[CPU_SYS]->vlist[i],
			   desclist[CPU_SYS].type, &atom, PM_TYPE_FLOAT);
	    u += atom.f;
	    pmExtractValue(prp->vset[CPU_SYS]->valfmt,
			   &prp->vset[CPU_SYS]->vlist[i],
			   desclist[CPU_SYS].type, &atom, PM_TYPE_FLOAT);
	    u -= atom.f;
	    /*
	     * really should use pmConvertValue, but I _know_ the times
	     * are in msec!
	     */
	    u = u / (1000 * dt);

	    if (u > 1.0)
		/* small errors are possible, so clip the utilization at 1.0 */
		u = 1.0;
	    ip->cpu_util += u;
	    if (u > ip->peak_cpu_util) {
		ip->peak_cpu_util = u;
		ip->peak_cpu = i;
	    }
	}
	ip->cpu_util /= ncpu;

	/* freemem - expect just one value */
	pmExtractValue(crp->vset[FREEMEM]->valfmt, crp->vset[FREEMEM]->vlist,
		    desclist[FREEMEM].type, &tmp, PM_TYPE_FLOAT);
	/* convert from today's units at the collection site to Mbytes */
	pmConvScale(PM_TYPE_FLOAT, &tmp, &desclist[FREEMEM].units,
		    &atom, &mbyte_scale);
	ip->freemem = atom.f;

	/* disk IOPS - expect just one value, but need delta */
	pmExtractValue(crp->vset[DKIOPS]->valfmt, crp->vset[DKIOPS]->vlist,
		    desclist[DKIOPS].type, &atom, PM_TYPE_U32);
	ip->dkiops = atom.ul;
	pmExtractValue(prp->vset[DKIOPS]->valfmt, prp->vset[DKIOPS]->vlist,
		    desclist[DKIOPS].type, &atom, PM_TYPE_U32);
	ip->dkiops -= atom.ul;
	ip->dkiops = ((float)(ip->dkiops) + 0.5) / dt;

	/* load average ... process all values, matching up the instances */
	for (i = 0; i < crp->vset[LOADAV]->numval; i++) {
	    pmExtractValue(crp->vset[LOADAV]->valfmt,
			   &crp->vset[LOADAV]->vlist[i],
			   desclist[LOADAV].type, &atom, PM_TYPE_FLOAT);
	    if (crp->vset[LOADAV]->vlist[i].inst == inst1)
		ip->load1 = atom.f;
	    else if (crp->vset[LOADAV]->vlist[i].inst == inst15)
		ip->load15 = atom.f;
	}

	/* free very old result */
	pmFreeResult(prp);
    }
    ip->timestamp = crp->timestamp;

    /* swizzle result pointers */
    prp = crp;
}
Exemple #3
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);
    }
}
Exemple #4
0
void
test_instance(void)
{
    int		sts;
    int		i;

    print_banner_start("instance");
    if (indom == PM_INDOM_NULL)
	return;

    fflush(stdout);
    if ((child_pid=fork()) == 0) {
	/* child sleeps and then exits */
	sleep(2*refresh+1);
	exit(0);
    }
    printf("cpid=%" FMT_PID "\n", child_pid);
 
    if (is_hotproc) {
	/* sleep so that hotprocs can update active list */
        sleep(2*refresh);
    }
    printf("\n--- GetInDom ---\n");
    sts = pmGetInDom(indom, &all_inst, &all_names);
    if (sts < 0) {
	printf("%s: pmGetInDom: %s\n", pmProgname, pmErrStr(sts));
	exit(1);
    }
    else
	all_n = sts;

    /* print the instance id's (i.e. pids) match the first field in the name */
    for (i=0; i < all_n; i++) {
	int	inst;
        if (verbose)
	  printf("  instance map [%d \"%s\"]\n", all_inst[i], all_names[i]);

	/* e.g. inst=0, name="00000 sched" */
	if (sscanf(all_names[i], proc_fmt, &inst) != 1) {
	    printf("%s: Error: cannot get PID from instname\n", pmProgname);
	    printf("%s: <id,name> = <%ld,\"%s\">\n", pmProgname,
		   (long)all_inst[i], all_names[i]);
	    exit(1);
	}
	if (inst != all_inst[i]) {
	    printf("%s: Error: instname is wrong\n", pmProgname);
	    printf("%s: <id,name> = <%ld,\"%s\"> != %d (fmt=%s)\n", pmProgname,
		   (long)all_inst[i], all_names[i], inst, proc_fmt);
	    exit(1);
	}
    }

    /* parent waits for child to exit */
    /* so that the the following lookups will NOT be able to find it */
    wait(&sts);


    printf("\n--- LookupInDom ---\n");
    for (i = 0; i < all_n; i++) {
	int inst, x;
	sts = pmLookupInDom(indom, all_names[i]);
	if (sts < 0) {
	    if (sts == PM_ERR_INST) {
		if (all_inst[i] == child_pid)
		    printf("  Death of child detected, pid=%" FMT_PID "\n", child_pid); 
		/* ignore deaths */
		continue;
	    }
	    else {
		printf("%s: pmLookupInDom: %s\n", pmProgname, pmErrStr(sts));
		exit(1);
	    }
	}
	inst = sts;
	if (verbose)
	    printf("  instance lookup \"%s\" --> %d\n", all_names[i], inst);  
	sscanf(all_names[i], proc_fmt, &x);
	if (x != inst) {
	    printf("%s: Error: inst is wrong, expect: %d got: %d\n",
		pmProgname, inst, x);
	    printf("%s: Expected=%d, Actual=%d\n", pmProgname, x, inst);
	    exit(1);
	}
    }/*for*/

    printf("\n--- NameInDom ---\n");
    for (i = 0; i < all_n; i++) {
	char *name;
        char x[100];

	sts = pmNameInDom(indom, all_inst[i], &name);
	if (sts < 0) {
	    if (sts == PM_ERR_INST) {
		if (all_inst[i] == child_pid)
		    printf("  Death of child detected\n"); 
		/* ignore deaths */
		continue;
	    }
	    else {
		printf("%s: pmNameInDom: %s\n", pmProgname, pmErrStr(sts));
		exit(1);
	    }
	}
	if (verbose)
	    printf("  instance name %d --> \"%s\"\n", all_inst[i], name);  
	sprintf(x, proc_fmt, all_inst[i]);
	if (strncmp(name, x, strlen(x)) != 0 ||
	    (name[strlen(x)] != '\0' && name[strlen(x)] != ' ')) {
	    /* try w/out leading zeroes */
	    char	*q;
	    sprintf(x, "%d", all_inst[i]);
	    for (q = name; *q && *q == '0'; q++)
		;
	    if (strncmp(q, x, strlen(x)) != 0 ||
		(q[strlen(x)] != '\0' && q[strlen(x)] != ' ')) {
		printf("%s: Error: name is wrong\n", pmProgname);
		printf("%s: Expected=\"%s\", Actual=\"%s\"\n", pmProgname, x, name);
		exit(1);
	    }
	}
	free(name);
    }/*for*/

    print_banner_end("instance");
}
Exemple #5
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);
}
Exemple #6
0
int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    int sts;
    char *metric[] = { request->key + strlen(ZBX_PCP_METRIC_PREFIX) };
    char *inst;
    pmID pmid[1];
    pmDesc desc[1];
    pmResult *rp;
    pmAtomValue atom;
    int iid = 0;
    int i;

    /* Parameter is the instance.  */
    switch(request->nparam) {
        case 0:
            inst = NULL;
            break;
        case 1:
            inst = get_rparam(request, 0);
            break;
        default:
            SET_MSG_RESULT(result, strdup("Extraneous instance specification."));
            return SYSINFO_RET_FAIL;
            break;
    }

    /* Preparations and sanity checks.  */
    sts = pmLookupName(1, metric, pmid);
    if (sts < 0) return SYSINFO_RET_FAIL;
    sts = pmLookupDesc(pmid[0], desc);
    if (sts < 0) return SYSINFO_RET_FAIL;
    if (inst != NULL && desc[0].indom == PM_INDOM_NULL) {
        SET_MSG_RESULT(result, strdup("Extraneous instance specification."));
        return SYSINFO_RET_FAIL;
    }
    if ((inst == NULL && desc[0].indom != PM_INDOM_NULL) ||
        (request->nparam == 1 && !strlen(inst))) {
        SET_MSG_RESULT(result, strdup("Missing instance specification."));
        return SYSINFO_RET_FAIL;
    }
    if (desc[0].indom != PM_INDOM_NULL) {
        iid = pmLookupInDom(desc[0].indom, inst);
        if (iid < 0) {
            SET_MSG_RESULT(result, strdup("Instance not available."));
            return SYSINFO_RET_FAIL;
        }
    }

    /* Fetch the metric values.  */
    sts = pmFetch(1, pmid, &rp);
    if (sts < 0) return SYSINFO_RET_FAIL;
    if (rp->vset[0]->numval < 1) {
        pmFreeResult(rp);
        SET_MSG_RESULT(result, strdup("No value available."));
        return SYSINFO_RET_FAIL;
    }

    /* Locate the correct instance.  */
    for (i = 0; desc[0].indom != PM_INDOM_NULL && i < rp->vset[0]->numval; i++) {
        if (rp->vset[0]->vlist[i].inst == iid) {
            break;
        }
    }
    if (i == rp->vset[0]->numval) {
        pmFreeResult(rp);
        return SYSINFO_RET_FAIL;
    }

    /* Extract the wanted value.  */
    sts = pmExtractValue(rp->vset[0]->valfmt, &rp->vset[0]->vlist[i],
                         desc[0].type, &atom, desc[0].type);
    pmFreeResult(rp);
    if (sts < 0) return SYSINFO_RET_FAIL;

    /* Hand it to the caller.  */
    switch(desc[0].type) {
        case PM_TYPE_32:
            SET_UI64_RESULT(result, atom.l);
            break;
        case PM_TYPE_U32:
            SET_UI64_RESULT(result, atom.ul);
            break;
        case PM_TYPE_64:
            SET_UI64_RESULT(result, atom.ll);
            break;
        case PM_TYPE_U64:
            SET_UI64_RESULT(result, atom.ull);
            break;
        case PM_TYPE_FLOAT:
            SET_DBL_RESULT(result, atom.f);
            break;
        case PM_TYPE_DOUBLE:
            SET_DBL_RESULT(result, atom.d);
            break;
        case PM_TYPE_STRING:
            SET_STR_RESULT(result, strdup(atom.cp));
            break;
        default:
            SET_MSG_RESULT(result, strdup("Unsupported metric value type."));
            return SYSINFO_RET_FAIL;
            break;
    }

    /* Success.  */
    return SYSINFO_RET_OK;
}
Exemple #7
0
int
main(int argc, char **argv)
{
    int		sts;
    int		n;
    int		c;
    int		i;
    char	*p;
    char	*source;
    char	*namelist[1];
    pmID	pmidlist[1];
    pmResult	*result;
    char	**instnames = NULL;
    int		numinst = 0;
    int		force = 0;
    pmDesc	desc;
    pmAtomValue	nav;
    pmValueSet	*vsp;
    char        *subopt;

    while ((c = pmGetOptions(argc, argv, &opts)) != EOF) {
	switch (c) {
        case 'f':
            force++;
            break;

	case 'i':	/* list of instances */
#define WHITESPACE ", \t\n"
	    subopt = strtok(opts.optarg, WHITESPACE);
	    while (subopt != NULL) {
		numinst++;
		n = numinst * sizeof(char *);
		instnames = (char **)realloc(instnames, n);
		if (instnames == NULL)
		    __pmNoMem("pmstore.instnames", n, PM_FATAL_ERR);
		instnames[numinst-1] = subopt;
		subopt = strtok(NULL, WHITESPACE);
	    }
#undef WHITESPACE
	    break;

	default:
	    opts.errors++;
	    break;
	}
    }

    if (opts.errors || opts.optind != argc - 2) {
	pmUsageMessage(&opts);
	exit(1);
    }

    if (opts.context == PM_CONTEXT_HOST)
	source = opts.hosts[0];
    else if (opts.context == PM_CONTEXT_LOCAL)
	source = NULL;
    else {
	opts.context = PM_CONTEXT_HOST;
	source = "local:";
    }
    if ((sts = pmNewContext(opts.context, source)) < 0) {
	if (opts.context == PM_CONTEXT_LOCAL)
	    fprintf(stderr, "%s: Cannot make standalone local connection: %s\n",
		    pmProgname, pmErrStr(sts));
	else
	    fprintf(stderr, "%s: Cannot connect to PMCD on host \"%s\": %s\n",
		    pmProgname, source, pmErrStr(sts));
	exit(1);
    }

    namelist[0] = argv[opts.optind++];
    if ((n = pmLookupName(1, namelist, pmidlist)) < 0) {
	printf("%s: pmLookupName: %s\n", namelist[0], pmErrStr(n));
	exit(1);
    }
    if (pmidlist[0] == PM_ID_NULL) {
	printf("%s: unknown metric\n", namelist[0]);
	exit(1);
    }
    if ((n = pmLookupDesc(pmidlist[0], &desc)) < 0) {
	printf("%s: pmLookupDesc: %s\n", namelist[0], pmErrStr(n));
	exit(1);
    }
    if (desc.type == PM_TYPE_AGGREGATE || desc.type == PM_TYPE_AGGREGATE_STATIC) {
	fprintf(stderr, "%s: Cannot modify values for PM_TYPE_AGGREGATE metrics\n",
	    pmProgname);
	exit(1);
    }
    if (desc.type == PM_TYPE_EVENT || desc.type == PM_TYPE_HIGHRES_EVENT) {
	fprintf(stderr, "%s: Cannot modify values for event type metrics\n",
	    pmProgname);
	exit(1);
    }
    if (instnames != NULL) {
	pmDelProfile(desc.indom, 0, NULL);
	for (i = 0; i < numinst; i++) {
	    if ((n = pmLookupInDom(desc.indom, instnames[i])) < 0) {
		printf("pmLookupInDom %s[%s]: %s\n",
		    namelist[0], instnames[i], pmErrStr(n));
		exit(1);
	    }
	    if ((sts = pmAddProfile(desc.indom, 1, &n)) < 0) {
		printf("pmAddProfile %s[%s]: %s\n",
		    namelist[0], instnames[i], pmErrStr(sts));
		exit(1);
	    }
	}
    }
    if ((n = pmFetch(1, pmidlist, &result)) < 0) {
	printf("%s: pmFetch: %s\n", namelist[0], pmErrStr(n));
	exit(1);
    }

    /* value is argv[opts.optind] */
    mkAtom(&nav, desc.type, argv[opts.optind]);

    vsp = result->vset[0];
    if (vsp->numval < 0) {
	printf("%s: Error: %s\n", namelist[0], pmErrStr(vsp->numval));
	exit(1);
    }

    if (vsp->numval == 0) {
        if (!force) {
            printf("%s: No value(s) available!\n", namelist[0]);
            exit(1);
        }
        else {
            pmAtomValue tmpav;

            mkAtom(&tmpav, PM_TYPE_STRING, "(none)");

            vsp->numval = 1;
            vsp->valfmt = __pmStuffValue(&tmpav, &vsp->vlist[0], PM_TYPE_STRING);
        }
    }

    for (i = 0; i < vsp->numval; i++) {
	pmValue	*vp = &vsp->vlist[i];
	printf("%s", namelist[0]);
	if (desc.indom != PM_INDOM_NULL) {
	    if ((n = pmNameInDom(desc.indom, vp->inst, &p)) < 0)
		printf(" inst [%d]", vp->inst);
	    else {
		printf(" inst [%d or \"%s\"]", vp->inst, p);
		free(p);
	    }
	}
	printf(" old value=");
	pmPrintValue(stdout, vsp->valfmt, desc.type, vp, 1);
	vsp->valfmt = __pmStuffValue(&nav, &vsp->vlist[i], desc.type);
	printf(" new value=");
	pmPrintValue(stdout, vsp->valfmt, desc.type, vp, 1);
	putchar('\n');
    }
    if ((n = pmStore(result)) < 0) {
	printf("%s: pmStore: %s\n", namelist[0], pmErrStr(n));
	exit(1);
    }
    pmFreeResult(result);
    exit(0);
}