1 /*
2 * Indom 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 indomspec_t
24 */
25 indomspec_t *
26 start_indom(pmInDom indom)
27 {
28 indomspec_t *ip;
29 int i;
30
31 for (ip = indom_root; ip != NULL; ip = ip->i_next) {
32 if (indom == ip->old_indom)
33 break;
34 }
35 if (ip == NULL) {
36 int numinst;
37 int *instlist;
38 char **namelist;
39
40 numinst = pmGetInDomArchive(indom, &instlist, &namelist);
41 if (numinst < 0) {
42 if (wflag) {
43 snprintf(mess, sizeof(mess), "Instance domain %s: %s", pmInDomStr(indom), pmErrStr(numinst));
44 yywarn(mess);
45 }
46 return NULL;
47 }
48
49 ip = (indomspec_t *)malloc(sizeof(indomspec_t));
50 if (ip == NULL) {
51 fprintf(stderr, "indomspec malloc(%d) failed: %s\n", (int)sizeof(indomspec_t), strerror(errno));
52 abandon();
53 }
54 ip->i_next = indom_root;
55 indom_root = ip;
56 ip->flags = (int *)malloc(numinst*sizeof(int));
57 if (ip->flags == NULL) {
58 fprintf(stderr, "indomspec flags malloc(%d) failed: %s\n", numinst*(int)sizeof(int), strerror(errno));
59 abandon();
60 }
61 for (i = 0; i < numinst; i++)
62 ip->flags[i] = 0;
63 ip->old_indom = indom;
64 ip->new_indom = indom;
65 ip->numinst = numinst;
66 ip->old_inst = instlist;
67 ip->new_inst = (int *)malloc(numinst*sizeof(int));
68 if (ip->new_inst == NULL) {
69 fprintf(stderr, "new_inst malloc(%d) failed: %s\n", numinst*(int)sizeof(int), strerror(errno));
70 abandon();
71 }
72 ip->old_iname = namelist;
73 ip->new_iname = (char **)malloc(numinst*sizeof(char *));
74 if (ip->new_iname == NULL) {
|
Event suspicious_sizeof: |
Passing argument "strerror(*__errno_location())" of type "char *" and argument "numinst * (int)sizeof (char *) /*8*/" to function "fprintf" is suspicious. |
75 fprintf(stderr, "new_iname malloc(%d) failed: %s\n", numinst*(int)sizeof(char *), strerror(errno));
76 abandon();
77 }
78 }
79
80 return ip;
81 }
82
83 int
84 change_inst_by_name(pmInDom indom, char *old, char *new)
85 {
86 int i;
87 indomspec_t *ip;
88
89 for (ip = indom_root; ip != NULL; ip = ip->i_next) {
90 if (indom == ip->old_indom)
91 break;
92 }
93 assert(ip != NULL);
94
95 for (i = 0; i < ip->numinst; i++) {
96 if (inst_name_eq(ip->old_iname[i], old) > 0) {
97 if ((new == NULL && ip->flags[i]) ||
98 (ip->flags[i] & (INST_CHANGE_INAME|INST_DELETE))) {
99 snprintf(mess, sizeof(mess), "Duplicate or conflicting clauses for instance [%d] \"%s\" of indom %s",
100 ip->old_inst[i], ip->old_iname[i], pmInDomStr(indom));
101 return -1;
102 }
103 break;
104 }
105 }
106 if (i == ip->numinst) {
107 if (wflag) {
108 snprintf(mess, sizeof(mess), "Unknown instance \"%s\" in iname clause for indom %s", old, pmInDomStr(indom));
109 yywarn(mess);
110 }
111 return 0;
112 }
113
114 if (new == NULL) {
115 ip->flags[i] |= INST_DELETE;
116 ip->new_iname[i] = NULL;
117 return 0;
118 }
119
120 if (strcmp(ip->old_iname[i], new) == 0) {
121 /* no change ... */
122 if (wflag) {
123 snprintf(mess, sizeof(mess), "Instance domain %s: Instance: \"%s\": No change", pmInDomStr(indom), ip->old_iname[i]);
124 yywarn(mess);
125 }
126 }
127 else {
128 ip->flags[i] |= INST_CHANGE_INAME;
129 ip->new_iname[i] = new;
130 }
131
132 return 0;
133 }
134
135 int
136 change_inst_by_inst(pmInDom indom, int old, int new)
137 {
138 int i;
139 indomspec_t *ip;
140
141 for (ip = indom_root; ip != NULL; ip = ip->i_next) {
142 if (indom == ip->old_indom)
143 break;
144 }
145 assert(ip != NULL);
146
147 for (i = 0; i < ip->numinst; i++) {
148 if (ip->old_inst[i] == old) {
149 if ((new == PM_IN_NULL && ip->flags[i]) ||
150 (ip->flags[i] & (INST_CHANGE_INST|INST_DELETE))) {
151 snprintf(mess, sizeof(mess), "Duplicate or conflicting clauses for instance [%d] \"%s\" of indom %s",
152 ip->old_inst[i], ip->old_iname[i], pmInDomStr(indom));
153 return -1;
154 }
155 break;
156 }
157 }
158 if (i == ip->numinst) {
159 if (wflag) {
160 snprintf(mess, sizeof(mess), "Unknown instance %d in inst clause for indom %s", old, pmInDomStr(indom));
161 yywarn(mess);
162 }
163 return 0;
164 }
165
166 if (new == PM_IN_NULL) {
167 ip->flags[i] |= INST_DELETE;
168 ip->new_inst[i] = PM_IN_NULL;
169 return 0;
170 }
171
172 if (ip->old_inst[i] == new) {
173 /* no change ... */
174 if (wflag) {
175 snprintf(mess, sizeof(mess), "Instance domain %s: Instance: %d: No change", pmInDomStr(indom), ip->old_inst[i]);
176 yywarn(mess);
177 }
178 }
179 else {
180 ip->new_inst[i] = new;
181 ip->flags[i] |= INST_CHANGE_INST;
182 }
183
184 return 0;
185 }
186
187 typedef struct {
188 __pmLogHdr hdr;
189 __pmTimeval stamp;
190 pmInDom indom;
191 int numinst;
192 char other[1];
193 } indom_t;
194
195 /*
196 * reverse the logic of __pmLogPutInDom()
197 */
198 static void
199 _pmUnpackInDom(__pmPDU *pdubuf, pmInDom *indom, __pmTimeval *tp, int *numinst, int **instlist, char ***inamelist)
200 {
201 indom_t *idp;
202 int i;
203 int *ip;
204 char *strbuf;
205
206 idp = (indom_t *)pdubuf;
207
208 tp->tv_sec = ntohl(idp->stamp.tv_sec);
209 tp->tv_usec = ntohl(idp->stamp.tv_usec);
210 *indom = __ntohpmInDom(idp->indom);
211 *numinst = ntohl(idp->numinst);
212 *instlist = (int *)malloc(*numinst * sizeof(int));
213 if (*instlist == NULL) {
214 fprintf(stderr, "_pmUnpackInDom instlist malloc(%d) failed: %s\n", (int)(*numinst * sizeof(int)), strerror(errno));
215 abandon();
216 }
217 ip = (int *)idp->other;
218 for (i = 0; i < *numinst; i++)
219 (*instlist)[i] = ntohl(*ip++);
220 *inamelist = (char **)malloc(*numinst * sizeof(char *));
221 if (*inamelist == NULL) {
222 fprintf(stderr, "_pmUnpackInDom inamelist malloc(%d) failed: %s\n", (int)(*numinst * sizeof(char *)), strerror(errno));
223 abandon();
224 }
225 /*
226 * ip[i] is stridx[i], which is offset into strbuf[]
227 */
228 strbuf = (char *)&ip[*numinst];
229 for (i = 0; i < *numinst; i++) {
230 (*inamelist)[i] = &strbuf[ntohl(ip[i])];
231 }
232 }
233
234 /*
235 * Note:
236 * We unpack the indom metadata record _again_ (was already done when
237 * the input archive was opened), but the data structure behind
238 * __pmLogCtl has differences for 32-bit and 64-bit pointers and
239 * modifying it as part of the rewrite could make badness break
240 * out later. It is safer to do it again, populate local copies
241 * of instlist[] and inamelist[], dink with 'em and then toss them
242 * away.
243 */
244 void
245 do_indom(void)
246 {
247 long out_offset;
248 pmInDom indom;
249 __pmTimeval stamp;
250 int numinst;
251 int *instlist;
252 char **inamelist;
253 indomspec_t *ip;
254 int sts;
255 int i;
256 int j;
257 int need_alloc = 0;
258
259 out_offset = ftell(outarch.logctl.l_mdfp);
260 _pmUnpackInDom(inarch.metarec, &indom, &stamp, &numinst, &instlist, &inamelist);
261
262 /*
263 * global time stamp adjustment (if any has already been done in the
264 * PDU buffer, so this is reflected in the unpacked value of stamp.
265 */
266 for (ip = indom_root; ip != NULL; ip = ip->i_next) {
267 if (ip->old_indom != indom)
268 continue;
269 if (ip->new_indom != ip->old_indom)
270 indom = ip->new_indom;
271 for (i = 0; i < ip->numinst; i++) {
272 for (j = 0; j < numinst; j++) {
273 if (ip->old_inst[i] == instlist[j])
274 break;
275 }
276 if (j == numinst)
277 continue;
278 if (ip->flags[i] & INST_DELETE) {
279 #if PCP_DEBUG
280 if (pmDebug & DBG_TRACE_APPL1)
281 fprintf(stderr, "Delete: instance %s (%d) for indom %s\n", ip->old_iname[i], ip->old_inst[i], pmInDomStr(ip->old_indom));
282 #endif
283 j++;
284 while (j < numinst) {
285 instlist[j-1] = instlist[j];
286 inamelist[j-1] = inamelist[j];
287 j++;
288 }
289 need_alloc = 1;
290 numinst--;
291 }
292 else {
293 if (ip->flags[i] & INST_CHANGE_INST)
294 instlist[j] = ip->new_inst[i];
295 if (ip->flags[i] & INST_CHANGE_INAME) {
296 inamelist[j] = ip->new_iname[i];
297 need_alloc = 1;
298 }
299 #if PCP_DEBUG
300 if ((ip->flags[i] & (INST_CHANGE_INST | INST_CHANGE_INAME)) && (pmDebug & DBG_TRACE_APPL1)) {
301 if ((ip->flags[i] & (INST_CHANGE_INST | INST_CHANGE_INAME)) == (INST_CHANGE_INST | INST_CHANGE_INAME))
302 fprintf(stderr, "Rewrite: instance %s (%d) -> %s (%d) for indom %s\n", ip->old_iname[i], ip->old_inst[i], ip->new_iname[i], ip->new_inst[i], pmInDomStr(ip->old_indom));
303 else if ((ip->flags[i] & (INST_CHANGE_INST | INST_CHANGE_INAME)) == INST_CHANGE_INST)
304 fprintf(stderr, "Rewrite: instance %s (%d) -> %s (%d) for indom %s\n", ip->old_iname[i], ip->old_inst[i], ip->old_iname[i], ip->new_inst[i], pmInDomStr(ip->old_indom));
305 else
306 fprintf(stderr, "Rewrite: instance %s (%d) -> %s (%d) for indom %s\n", ip->old_iname[i], ip->old_inst[i], ip->new_iname[i], ip->old_inst[i], pmInDomStr(ip->old_indom));
307 }
308 #endif
309 }
310 }
311 }
312
313 if (need_alloc) {
314 /*
315 * __pmLogPutInDom assumes the elements of inamelist[] point into
316 * of a contiguous allocation starting at inamelist[0] ... if we've
317 * changed an instance name or moved instance names about, then we
318 * need to reallocate the strings for inamelist[]
319 */
320 int need = 0;
321 char *new;
322 char *p;
323
324 for (j = 0; j < numinst; j++)
325 need += strlen(inamelist[j]) + 1;
326 new = (char *)malloc(need);
327 if (new == NULL) {
328 fprintf(stderr, "inamelist[] malloc(%d) failed: %s\n", need, strerror(errno));
329 abandon();
330 }
331 p = new;
332 for (j = 0; j < numinst; j++) {
333 strcpy(p, inamelist[j]);
334 inamelist[j] = p;
335 p += strlen(p) + 1;
336 }
337 }
338
339 if ((sts = __pmLogPutInDom(&outarch.logctl, indom, &stamp, numinst, instlist, inamelist)) < 0) {
340 fprintf(stderr, "%s: Error: __pmLogPutInDom: %s: %s\n",
341 pmProgname, pmInDomStr(indom), pmErrStr(sts));
342 abandon();
343 }
344 #if PCP_DEBUG
345 if (pmDebug & DBG_TRACE_APPL0) {
346 fprintf(stderr, "Metadata: write InDom %s @ offset=%ld\n", pmInDomStr(indom), out_offset);
347 }
348 #endif
349
350 free(instlist);
351 if (need_alloc)
352 free(inamelist[0]);
353 free(inamelist);
354 }