summaryrefslogtreecommitdiff
path: root/src/pmlogreduce/rewrite.c
blob: eae00e46614ef6a225b3176c8e9d1eaeb38bc390 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include "pmlogreduce.h"
#include <inttypes.h>

static pmResult	*orp;

/*
 * Must either re-write the pmResult, or return NULL for non-fatal
 * errors, else report and exit for catastrophic errors ...
 */
pmResult *
rewrite(pmResult *rp)
{
    int			i;
    int			sts;

    if ((orp = (pmResult *)malloc(sizeof(pmResult) +
			(rp->numpmid - 1) * sizeof(pmValueSet *))) == NULL) {
	fprintf(stderr,
		"%s: rewrite: cannot malloc pmResult for %d metrics\n",
		    pmProgname, rp->numpmid);
	    exit(1);
    }
    orp->numpmid = 0;
    orp->timestamp = rp->timestamp;	/* struct assignment */

    for (i = 0; i < rp->numpmid; i++) {
	metric_t	*mp;
	value_t		*vp;
	pmValueSet	*vsp = rp->vset[i];
	pmValueSet	*ovsp;
	int		j;
	int		need;

	if (pmidlist[i] != vsp->pmid) {
	    fprintf(stderr,
		"%s: rewrite: Arrgh, mismatched PMID %s vs %s\n",
		    pmProgname, pmIDStr(pmidlist[i]), pmIDStr(vsp->pmid));
	    exit(1);
	}

	if (vsp->numval > 0)
	    need = (vsp->numval - 1) * sizeof(pmValue);
	else
	    need = 0;
	ovsp = (pmValueSet *)malloc(sizeof(pmValueSet) +
				need*sizeof(pmValue));
	if (ovsp == NULL) {
	    __uint64_t bytes = (sizeof(pmValueSet) + need * sizeof(pmValue));
	    fprintf(stderr,
		"%s: rewrite: Arrgh, cannot malloc %"PRIi64" bytes for ovsp\n",
		    pmProgname, bytes);
	    exit(1);
	}
	ovsp->pmid = vsp->pmid;
	ovsp->valfmt = vsp->valfmt;
	if (vsp->numval <= 0) {
	    ovsp->numval = vsp->numval;
	    orp->vset[orp->numpmid] = ovsp;
	    orp->numpmid++;
	}
	else {
	    ovsp->numval = 0;
	    mp = &metriclist[i];
	    if (mp->mode != MODE_SKIP) {
		for (j = 0; j < vsp->numval; j++) {
		    for (vp = mp->first; vp != NULL; vp = vp->next) {
			if (vp->inst == vsp->vlist[j].inst)
			    break;
		    }
		    if (vp == NULL) {
			fprintf(stderr,
			    "%s: rewrite: Arrgh: cannot find inst %d in value_t list for %s (%s)\n",
				pmProgname, vsp->vlist[j].inst, namelist[i], pmIDStr(vsp->pmid));
			exit(1);
		    }
		    if ((vp->control & (V_SEEN|V_INIT)) == 0)
			continue;
		    /*
		     * we've seen this metric-instance pair in the last
		     * interval, or it is the first time for this one
		     */
		    if (mp->mode == MODE_REWRITE) {
			pmAtomValue	av;
			int		k;
			sts = pmExtractValue(vsp->valfmt, &vsp->vlist[j], mp->idesc.type, &av, mp->odesc.type);
			if (sts < 0) {
			    fprintf(stderr,
				"%s: rewrite: pmExtractValue failed for pmid %s value %d: %s\n",
				    pmProgname, pmIDStr(vsp->pmid), j, pmErrStr(sts));
			    exit(1);
			}
			ovsp->pmid = vsp->pmid;
			ovsp->vlist[ovsp->numval].inst = vsp->vlist[j].inst;
			k = __pmStuffValue(&av, &ovsp->vlist[ovsp->numval], mp->odesc.type);
			if (k < 0) {
			    fprintf(stderr,
				"%s: rewrite: __pmStuffValue failed for pmid %s value %d: %s\n",
				    pmProgname, pmIDStr(vsp->pmid), j, pmErrStr(sts));
			    exit(1);
			}
			if (ovsp->numval == 0)
			    ovsp->valfmt = k;
			ovsp->numval++;
			vp->timestamp = rp->timestamp;
			vp->value = av;
		    }
		    else {
			ovsp->vlist[ovsp->numval] = vsp->vlist[j];
			ovsp->numval++;
		    }
		    vp->control &= ~V_INIT;
		}
	    }
	    if (ovsp->numval > 0) {
		orp->vset[orp->numpmid] = ovsp;
		orp->numpmid++;
	    }
	    else
		free(ovsp);
	}
    }

    if (orp->numpmid == 0) {
	/*
	 * very unlikely that all metrics are either skipped or have
	 * no values, but it might happen ... do not allow this record
	 * to be written because it looks like a "mark" record with
	 * numpmid == 0
	 */
	free(orp);
	orp = NULL;
    }

    return orp;
}

void
rewrite_free(void)
{
    int			i;

    if (orp == NULL)
	return;

    for (i = 0; i < orp->numpmid; i++) {
	pmValueSet	*vsp = orp->vset[i];
	int		j;
	metric_t	*mp;

	for (j = 0; j < numpmid; j++) {
	    if (vsp->pmid == pmidlist[j])
		break;
	}
	if (j == numpmid) {
	    fprintf(stderr,
		"%s: rewrite_free: Arrgh, cannot find pmid %s in pmidlist[]\n",
		    pmProgname, pmIDStr(vsp->pmid));
	    exit(1);
	}
	mp = &metriclist[j];

	if (vsp->numval > 0 && mp->mode == MODE_REWRITE) {
	    /*
	     * MODE_REWRITE implies the value was promoted to 64-bit
	     * and the pval in the pmResult came from the __pmStuffValue()
	     * call above, so free it here
	     */
	    for (j = 0; j < vsp->numval; j++) {
		free(vsp->vlist[j].value.pval);
	    }
	}

	free(vsp);
    }

    free(orp);
    orp = NULL;
}