1 /*
2 * Metric metadata support for pmlogrewrite
3 *
4 * Copyright (c) 2011 Ken McDonell. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "pmapi.h"
18 #include "impl.h"
19 #include "logger.h"
20 #include <assert.h>
21
22 /*
23 * Find or create a new metricspec_t
24 */
25 metricspec_t *
26 start_metric(pmID pmid)
27 {
28 metricspec_t *mp;
29 int sts;
30
31 #if PCP_DEBUG
32 if ((pmDebug & (DBG_TRACE_APPL0 | DBG_TRACE_APPL1)) == (DBG_TRACE_APPL0 | DBG_TRACE_APPL1))
33 fprintf(stderr, "start_metric(%s)", pmIDStr(pmid));
34 #endif
35
36 for (mp = metric_root; mp != NULL; mp = mp->m_next) {
37 if (pmid == mp->old_desc.pmid) {
38 #if PCP_DEBUG
39 if ((pmDebug & (DBG_TRACE_APPL0 | DBG_TRACE_APPL1)) == (DBG_TRACE_APPL0 | DBG_TRACE_APPL1))
40 fprintf(stderr, " -> %s\n", mp->old_name);
41 #endif
42 break;
43 }
44 }
45 if (mp == NULL) {
46 char *name;
47 pmDesc desc;
48
49 sts = pmNameID(pmid, &name);
50 if (sts < 0) {
51 if (wflag) {
52 snprintf(mess, sizeof(mess), "Metric %s pmNameID: %s", pmIDStr(pmid), pmErrStr(sts));
53 yywarn(mess);
54 }
55 return NULL;
56 }
57 sts = pmLookupDesc(pmid, &desc);
58 if (sts < 0) {
59 if (wflag) {
60 snprintf(mess, sizeof(mess), "Metric %s: pmLookupDesc: %s", mp->old_name, pmErrStr(sts));
61 yywarn(mess);
62 }
63 return NULL;
64 }
65
66 mp = (metricspec_t *)malloc(sizeof(metricspec_t));
67 if (mp == NULL) {
68 fprintf(stderr, "metricspec malloc(%d) failed: %s\n", (int)sizeof(metricspec_t), strerror(errno));
69 abandon();
70 }
71 mp->m_next = metric_root;
72 metric_root = mp;
73 mp->output = OUTPUT_ALL;
74 mp->one_inst = 0;
75 mp->one_name = NULL;
76 mp->old_name = name;
77 mp->old_desc = desc;
78 mp->new_desc = mp->old_desc;
79 mp->flags = 0;
80 mp->ip = NULL;
81 #if PCP_DEBUG
82 if ((pmDebug & (DBG_TRACE_APPL0 | DBG_TRACE_APPL1)) == (DBG_TRACE_APPL0 | DBG_TRACE_APPL1))
83 fprintf(stderr, " -> %s [new entry]\n", mp->old_name);
84 #endif
85 }
86
87 return mp;
88 }
89
90 typedef struct {
91 __pmLogHdr hdr;
92 pmDesc desc;
93 int numnames;
94 char strbuf[1];
95 } desc_t;
96
97 /*
98 * reverse the logic of __pmLogPutDesc()
99 */
100 static void
101 _pmUnpackDesc(__pmPDU *pdubuf, pmDesc *desc, int *numnames, char ***names)
102 {
103 desc_t *pp;
104 int i;
105 char *p;
106 int slen;
107
108 pp = (desc_t *)pdubuf;
109 desc->type = ntohl(pp->desc.type);
110 desc->sem = ntohl(pp->desc.sem);
111 desc->indom = __ntohpmInDom(pp->desc.indom);
112 desc->units = __ntohpmUnits(pp->desc.units);
113 desc->pmid = __ntohpmID(pp->desc.pmid);
114 *numnames = ntohl(pp->numnames);
115 *names = (char **)malloc(*numnames * sizeof(names[1]));
116 if (names == NULL) {
|
Event suspicious_sizeof: |
Passing argument "strerror(*__errno_location())" of type "char **" and argument "*numnames * sizeof (names[1]) /*8*/" to function "fprintf" is suspicious. Did you intend to use "sizeof(*names[1])" instead of "sizeof (names[1])" ? In this particular case sizeof(char **) happens to be equal to sizeof(char *), but this is not a portable assumption. |
117 fprintf(stderr, "_pmUnpackDesc malloc(%d) failed: %s\n", (int)(*numnames * sizeof(names[1])), strerror(errno));
118 abandon();
119 }
120
121 p = pp->strbuf;
122 for (i = 0; i < *numnames; i++) {
123 memcpy(&slen, p, LENSIZE);
124 slen = ntohl(slen);
125 p += LENSIZE;
126 (*names)[i] = malloc(slen+1);
127 if ((*names)[i] == NULL) {
128 fprintf(stderr, "_pmUnpackDesc malloc(%d) failed: %s\n", slen+1, strerror(errno));
129 abandon();
130 }
131 strncpy((*names)[i], p, slen);
132 (*names)[i][slen] = '\0';
133 p += slen;
134 }
135
136 return;
137 }
138
139 /*
140 * rewrite pmDesc from metadata, returns
141 * -1 delete this pmDesc
142 * 0 no change
143 * 1 changed
144 */
145 void
146 do_desc(void)
147 {
148 metricspec_t *mp;
149 pmDesc desc;
150 int i;
151 int sts;
152 int numnames;
153 char **names;
154 long out_offset;
155
156 out_offset = ftell(outarch.logctl.l_mdfp);
157 _pmUnpackDesc(inarch.metarec, &desc, &numnames, &names);
158
159 for (mp = metric_root; mp != NULL; mp = mp->m_next) {
160 if (desc.pmid != mp->old_desc.pmid || mp->flags == 0)
161 continue;
162 if (mp->flags & METRIC_DELETE) {
163 #if PCP_DEBUG
164 if (pmDebug & DBG_TRACE_APPL1)
165 fprintf(stderr, "Delete: pmDesc for %s\n", pmIDStr(desc.pmid));
166 #endif
167 goto done;
168 }
169 #if PCP_DEBUG
170 if (pmDebug & DBG_TRACE_APPL1)
171 fprintf(stderr, "Rewrite: pmDesc for %s\n", pmIDStr(desc.pmid));
172 #endif
173 if (mp->flags & METRIC_CHANGE_PMID)
174 desc.pmid = mp->new_desc.pmid;
175 if (mp->flags & METRIC_CHANGE_NAME) {
176 for (i = 0; i < numnames; i++) {
177 if (strcmp(names[i], mp->old_name) == 0) {
178 free(names[i]);
179 names[i] = strdup(mp->new_name);
180 if (names[i] == NULL) {
181 fprintf(stderr, "do_desc strdup(%s) failed: %s\n", mp->new_name, strerror(errno));
182 abandon();
183 }
184 }
185 break;
186 }
187 if (i == numnames) {
188 fprintf(stderr, "%s: Botch: old name %s not found in list of %d names for pmid %s ...",
189 pmProgname, mp->old_name, numnames, pmIDStr(mp->old_desc.pmid));
190 for (i = 0; i < numnames; i++) {
191 if (i > 0) fputc(',', stderr);
192 fprintf(stderr, " %s", names[i]);
193 }
194 fputc('\n', stderr);
195 abandon();
196 }
197 }
198 if (mp->flags & METRIC_CHANGE_TYPE)
199 desc.type = mp->new_desc.type;
200 if (mp->flags & METRIC_CHANGE_INDOM)
201 desc.indom = mp->new_desc.indom;
202 if (mp->flags & METRIC_CHANGE_SEM)
203 desc.sem = mp->new_desc.sem;
204 if (mp->flags & METRIC_CHANGE_UNITS)
205 desc.units = mp->new_desc.units; /* struct assignment */
206 break;
207 }
208 if ((sts = __pmLogPutDesc(&outarch.logctl, &desc, numnames, names)) < 0) {
209 fprintf(stderr, "%s: Error: __pmLogPutDesc: %s (%s): %s\n",
210 pmProgname, names[0], pmIDStr(desc.pmid), pmErrStr(sts));
211 abandon();
212 }
213 #if PCP_DEBUG
214 if (pmDebug & DBG_TRACE_APPL0)
215 fprintf(stderr, "Metadata: write PMID %s @ offset=%ld\n", pmIDStr(desc.pmid), out_offset);
216 #endif
217
218 done:
219 for (i = 0; i < numnames; i++)
220 free(names[i]);
221 free(names);
222 return;
223 }