1 /*
2 * Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; either version 2.1 of the License, or
7 * (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12 * License for more details.
13 */
14
15 #include "pmapi.h"
16 #include "impl.h"
17 #include <stddef.h>
18
19 /* bytes for a length field in a header/trailer, or a string length field */
20 #define LENSIZE 4
21
22 #ifdef PCP_DEBUG
23 static char *
24 StrTimeval(__pmTimeval *tp)
25 {
26 if (tp == NULL) {
27 static char *null_timeval = "<null timeval>";
28 return null_timeval;
29 }
30 else {
31 static char sbuf[13];
32 struct tm tmp;
33 time_t t = tp->tv_sec;
34 pmLocaltime(&t, &tmp);
35 sprintf(sbuf, "%02d:%02d:%02d.%03d", /* safe */
36 tmp.tm_hour, tmp.tm_min, tmp.tm_sec, tp->tv_usec/1000);
37 return sbuf;
38 }
39 }
40 #endif
41
42 __pmHashNode *
43 __pmHashSearch(unsigned int key, __pmHashCtl *hcp)
44 {
45 __pmHashNode *hp;
46
47 if (hcp->hsize == 0)
48 return NULL;
49
50 for (hp = hcp->hash[key % hcp->hsize]; hp != NULL; hp = hp->next) {
51 if (hp->key == key)
52 return hp;
53 }
54 return NULL;
55 }
56
57 int
58 __pmHashAdd(unsigned int key, void *data, __pmHashCtl *hcp)
59 {
60 __pmHashNode *hp;
61 int k;
62
63 hcp->nodes++;
64
65 if (hcp->hsize == 0) {
66 hcp->hsize = 1; /* arbitrary number */
67 if ((hcp->hash = (__pmHashNode **)calloc(hcp->hsize, sizeof(__pmHashNode *))) == NULL) {
68 hcp->hsize = 0;
69 return -oserror();
70 }
71 }
72 else if (hcp->nodes / 4 > hcp->hsize) {
73 __pmHashNode *tp;
74 __pmHashNode **old = hcp->hash;
75 int oldsize = hcp->hsize;
76
77 hcp->hsize *= 2;
78 if (hcp->hsize % 2) hcp->hsize++;
79 if (hcp->hsize % 3) hcp->hsize += 2;
80 if (hcp->hsize % 5) hcp->hsize += 2;
81 if ((hcp->hash = (__pmHashNode **)calloc(hcp->hsize, sizeof(__pmHashNode *))) == NULL) {
82 hcp->hsize = oldsize;
83 hcp->hash = old;
84 return -oserror();
85 }
86 /*
87 * re-link chains
88 */
89 while (oldsize) {
90 for (hp = old[--oldsize]; hp != NULL; ) {
91 tp = hp;
92 hp = hp->next;
93 k = tp->key % hcp->hsize;
94 tp->next = hcp->hash[k];
95 hcp->hash[k] = tp;
96 }
97 }
98 free(old);
99 }
100
101 if ((hp = (__pmHashNode *)malloc(sizeof(__pmHashNode))) == NULL)
102 return -oserror();
103
104 k = key % hcp->hsize;
105 hp->key = key;
106 hp->data = data;
107 hp->next = hcp->hash[k];
108 hcp->hash[k] = hp;
109
110 return 1;
111 }
112
113 int
114 __pmHashDel(unsigned int key, void *data, __pmHashCtl *hcp)
115 {
116 __pmHashNode *hp;
117 __pmHashNode *lhp = NULL;
118
119 if (hcp->hsize == 0)
120 return 0;
121
122 for (hp = hcp->hash[key % hcp->hsize]; hp != NULL; hp = hp->next) {
123 if (hp->key == key && hp->data == data) {
124 if (lhp == NULL)
125 hcp->hash[key % hcp->hsize] = hp->next;
126 else
127 lhp->next = hp->next;
128 free(hp);
129 return 1;
130 }
131 lhp = hp;
132 }
133
134 return 0;
135 }
136
137 static int
138 addindom(__pmLogCtl *lcp, pmInDom indom, const __pmTimeval *tp, int numinst,
139 int *instlist, char **namelist, int *indom_buf, int allinbuf)
140 {
141 __pmLogInDom *idp;
142 __pmHashNode *hp;
143 int sts;
144
145 if ((idp = (__pmLogInDom *)malloc(sizeof(__pmLogInDom))) == NULL)
146 return -oserror();
147 idp->stamp = *tp; /* struct assignment */
148 idp->numinst = numinst;
149 idp->instlist = instlist;
150 idp->namelist = namelist;
151 idp->buf = indom_buf;
152 idp->allinbuf = allinbuf;
153
154 #ifdef PCP_DEBUG
155 if (pmDebug & DBG_TRACE_LOGMETA)
156 fprintf(stderr, "addindom( ..., %s, %s, numinst=%d)\n",
157 pmInDomStr(indom), StrTimeval((__pmTimeval *)tp), numinst);
158 #endif
159
160
161 if ((hp = __pmHashSearch((unsigned int)indom, &lcp->l_hashindom)) == NULL) {
162 idp->next = NULL;
163 sts = __pmHashAdd((unsigned int)indom, (void *)idp, &lcp->l_hashindom);
164 }
165 else {
166 idp->next = (__pmLogInDom *)hp->data;
167 hp->data = (void *)idp;
168 sts = 0;
169 }
170 return sts;
171 }
172
173 /*
174 * load _all_ of the hashed pmDesc and __pmLogInDom structures from the metadata
175 * log file -- used at the initialization (NewContext) of an archive
176 * If version 2 then
177 * load all the names from the meta data and create l_pmns.
178 */
179 int
180 __pmLogLoadMeta(__pmLogCtl *lcp)
181 {
182 int rlen;
183 int check;
184 pmDesc *dp;
185 int sts = 0;
186 __pmLogHdr h;
187 FILE *f = lcp->l_mdfp;
188 int version2 = ((lcp->l_label.ill_magic & 0xff) == PM_LOG_VERS02);
189 int numpmid = 0;
190 int n;
191
192 if (version2) {
193 if ((sts = __pmNewPMNS(&(lcp->l_pmns))) < 0) {
194 goto end;
195 }
196 }
197
198 fseek(f, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET);
199 for ( ; ; ) {
200 n = (int)fread(&h, 1, sizeof(__pmLogHdr), f);
201
202 /* swab hdr */
203 h.len = ntohl(h.len);
204 h.type = ntohl(h.type);
205
206 if (n != sizeof(__pmLogHdr) || h.len <= 0) {
207 if (feof(f)) {
208 clearerr(f);
209 sts = 0;
210 goto end;
211 }
212 #ifdef PCP_DEBUG
213 if (pmDebug & DBG_TRACE_LOGMETA) {
214 fprintf(stderr, "__pmLogLoadMeta: header read -> %d: expected: %d\n",
215 n, (int)sizeof(__pmLogHdr));
216 }
217 #endif
218 if (ferror(f)) {
219 clearerr(f);
220 sts = -oserror();
221 }
222 else
223 sts = PM_ERR_LOGREC;
224 goto end;
225 }
226 #ifdef PCP_DEBUG
227 if (pmDebug & DBG_TRACE_LOGMETA) {
228 fprintf(stderr, "__pmLogLoadMeta: record len=%d, type=%d @ offset=%d\n",
229 h.len, h.type, (int)(ftell(f) - sizeof(__pmLogHdr)));
230 }
231 #endif
232 rlen = h.len - (int)sizeof(__pmLogHdr) - (int)sizeof(int);
233 if (h.type == TYPE_DESC) {
234 numpmid++;
|
Event alloc_fn: |
Calling allocation function "malloc". |
|
Event var_assign: |
Assigning: "dp" = storage returned from "malloc(sizeof (pmDesc) /*20*/)". |
| Also see events: |
[noescape][leaked_storage] |
|
At conditional (1): "(dp = (pmDesc *)malloc(sizeof (pmDesc) /*20*/)) == NULL": Taking false branch.
|
235 if ((dp = (pmDesc *)malloc(sizeof(pmDesc))) == NULL) {
236 sts = -oserror();
237 goto end;
238 }
|
At conditional (2): "(n = (int)fread(dp, 1UL, sizeof (pmDesc) /*20*/, f)) != sizeof (pmDesc) /*20*/": Taking true branch.
|
239 if ((n = (int)fread(dp, 1, sizeof(pmDesc), f)) != sizeof(pmDesc)) {
240 #ifdef PCP_DEBUG
|
At conditional (3): "pmDebug & 0x100": Taking true branch.
|
241 if (pmDebug & DBG_TRACE_LOGMETA) {
242 fprintf(stderr, "__pmLogLoadMeta: pmDesc read -> %d: expected: %d\n",
243 n, (int)sizeof(pmDesc));
244 }
245 #endif
|
At conditional (4): "ferror(f)": Taking true branch.
|
246 if (ferror(f)) {
247 clearerr(f);
248 sts = -oserror();
249 }
250 else
251 sts = PM_ERR_LOGREC;
252 goto end;
253 }
254 else {
255 /* swab desc */
256 dp->type = ntohl(dp->type);
257 dp->sem = ntohl(dp->sem);
258 dp->indom = __ntohpmInDom(dp->indom);
259 dp->units = __ntohpmUnits(dp->units);
260 dp->pmid = __ntohpmID(dp->pmid);
261 }
262
263 if ((sts = __pmHashAdd((int)dp->pmid, (void *)dp, &lcp->l_hashpmid)) < 0)
264 goto end;
265
266 if (version2) {
267 char name[MAXPATHLEN];
268 int numnames;
269 int i;
270 int len;
271
272 /* read in the names & store in PMNS tree ... */
273 if ((n = (int)fread(&numnames, 1, sizeof(numnames), f)) !=
274 sizeof(numnames)) {
275 #ifdef PCP_DEBUG
276 if (pmDebug & DBG_TRACE_LOGMETA) {
277 fprintf(stderr, "__pmLogLoadMeta: numnames read -> %d: expected: %d\n",
278 n, (int)sizeof(numnames));
279 }
280 #endif
281 if (ferror(f)) {
282 clearerr(f);
283 sts = -oserror();
284 }
285 else
286 sts = PM_ERR_LOGREC;
287 goto end;
288 }
289 else {
290 /* swab numnames */
291 numnames = ntohl(numnames);
292 }
293
294 for (i = 0; i < numnames; i++) {
295 if ((n = (int)fread(&len, 1, sizeof(len), f)) !=
296 sizeof(len)) {
297 #ifdef PCP_DEBUG
298 if (pmDebug & DBG_TRACE_LOGMETA) {
299 fprintf(stderr, "__pmLogLoadMeta: len name[%d] read -> %d: expected: %d\n",
300 i, n, (int)sizeof(len));
301 }
302 #endif
303 if (ferror(f)) {
304 clearerr(f);
305 sts = -oserror();
306 }
307 else
308 sts = PM_ERR_LOGREC;
309 goto end;
310 }
311 else {
312 /* swab len */
313 len = ntohl(len);
314 }
315
316 if ((n = (int)fread(name, 1, len, f)) != len) {
317 #ifdef PCP_DEBUG
318 if (pmDebug & DBG_TRACE_LOGMETA) {
319 fprintf(stderr, "__pmLogLoadMeta: name[%d] read -> %d: expected: %d\n",
320 i, n, len);
321 }
322 #endif
323 if (ferror(f)) {
324 clearerr(f);
325 sts = -oserror();
326 }
327 else
328 sts = PM_ERR_LOGREC;
329 goto end;
330 }
331 name[len] = '\0';
332 #ifdef PCP_DEBUG
333 if (pmDebug & DBG_TRACE_LOGMETA) {
334 fprintf(stderr, "__pmLogLoadMeta: PMID: %s name: %s\n",
335 pmIDStr(dp->pmid), name);
336 }
337 #endif
338
339 if ((sts = __pmAddPMNSNode(lcp->l_pmns, dp->pmid, name)) < 0) {
340 /*
341 * If we see a duplicate PMID, its a recoverable error.
342 * We wont be able to see all of the data in the log, but
343 * its better to provide access to some rather than none,
344 * esp. when only one or two metric IDs may be corrupted
345 * in this way (which we may not be interested in anyway).
346 */
347 if (sts != PM_ERR_PMID)
348 goto end;
349 sts = 0;
350 }
351 }/*for*/
352 }/*version2*/
353 }
354 else if (h.type == TYPE_INDOM) {
355 int *tbuf;
356 pmInDom indom;
357 __pmTimeval *when;
358 int numinst;
359 int *instlist;
360 char **namelist;
361 char *namebase;
362 int *stridx;
363 int i;
364 int k;
365 int allinbuf;
366
367 if ((tbuf = (int *)malloc(rlen)) == NULL) {
368 sts = -oserror();
369 goto end;
370 }
371 if ((n = (int)fread(tbuf, 1, rlen, f)) != rlen) {
372 #ifdef PCP_DEBUG
373 if (pmDebug & DBG_TRACE_LOGMETA) {
374 fprintf(stderr, "__pmLogLoadMeta: indom read -> %d: expected: %d\n",
375 n, rlen);
376 }
377 #endif
378 if (ferror(f)) {
379 clearerr(f);
380 sts = -oserror();
381 }
382 else
383 sts = PM_ERR_LOGREC;
384 goto end;
385 }
386
387 k = 0;
388 when = (__pmTimeval *)&tbuf[k];
389 when->tv_sec = ntohl(when->tv_sec);
390 when->tv_usec = ntohl(when->tv_usec);
391 k += sizeof(*when)/sizeof(int);
392 indom = __ntohpmInDom((unsigned int)tbuf[k++]);
393 numinst = ntohl(tbuf[k++]);
394 if (numinst > 0) {
395 instlist = &tbuf[k];
396 k += numinst;
397 stridx = &tbuf[k];
398 #if defined(HAVE_32BIT_PTR)
399 namelist = (char **)stridx;
400 allinbuf = 1; /* allocation is all in tbuf */
401 #else
402 allinbuf = 0; /* allocation for namelist + tbuf */
403 /* need to allocate to hold the pointers */
404 namelist = (char **)malloc(numinst*sizeof(char*));
405 if (namelist == NULL) {
406 sts = -oserror();
407 goto end;
408 }
409 #endif
410 k += numinst;
411 namebase = (char *)&tbuf[k];
412 for (i = 0; i < numinst; i++) {
413 instlist[i] = ntohl(instlist[i]);
414 namelist[i] = &namebase[ntohl(stridx[i])];
415 }
416 }
417 else {
418 /* no instances, or an error */
419 instlist = NULL;
420 namelist = NULL;
421 }
422 if ((sts = addindom(lcp, indom, when, numinst, instlist, namelist, tbuf, allinbuf)) < 0)
423 goto end;
424 }
425 else
426 fseek(f, (long)rlen, SEEK_CUR);
427 n = (int)fread(&check, 1, sizeof(check), f);
428 check = ntohl(check);
429 if (n != sizeof(check) || h.len != check) {
430 #ifdef PCP_DEBUG
431 if (pmDebug & DBG_TRACE_LOGMETA) {
432 fprintf(stderr, "__pmLogLoadMeta: trailer read -> %d or len=%d: expected %d @ offset=%d\n",
433 n, check, h.len, (int)(ftell(f) - sizeof(check)));
434 }
435 #endif
436 if (ferror(f)) {
437 clearerr(f);
438 sts = -oserror();
439 }
440 else
441 sts = PM_ERR_LOGREC;
442 goto end;
443 }
444 }/*for*/
445 end:
446
447 fseek(f, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET);
448
|
At conditional (5): "version2": Taking true branch.
|
|
At conditional (6): "sts == 0": Taking true branch.
|
449 if (version2 && sts == 0) {
450 __pmFixPMNSHashTab(lcp->l_pmns, numpmid, 1);
451 }
|
Event leaked_storage: |
Variable "dp" going out of scope leaks the storage it points to. |
| Also see events: |
[alloc_fn][var_assign][noescape] |
452 return sts;
453 }
454
455 /*
456 * scan the hashed data structures to find a pmDesc, given a pmid
457 */
458 int
459 __pmLogLookupDesc(__pmLogCtl *lcp, pmID pmid, pmDesc *dp)
460 {
461 __pmHashNode *hp;
462 pmDesc *tp;
463
464 if ((hp = __pmHashSearch((unsigned int)pmid, &lcp->l_hashpmid)) == NULL)
465 return PM_ERR_PMID_LOG;
466
467 tp = (pmDesc *)hp->data;
468 *dp = *tp; /* struct assignment */
469 return 0;
470 }
471
472 /*
473 * Add a new pmDesc into the metadata log, and to the hashed data structures
474 * If numnames is positive, then write out any associated PMNS names.
475 */
476 int
477 __pmLogPutDesc(__pmLogCtl *lcp, const pmDesc *dp, int numnames, char **names)
478 {
479 __pmLogHdr h;
480 FILE *f = lcp->l_mdfp;
481 pmDesc *tdp;
482 pmDesc *odp; /* pmDesc to write out */
483 int onumnames; /* numnames to write out */
484 int olen; /* length to write out */
485 int i;
486 int len;
487 pmDesc tmp;
488
489 h.type = htonl(TYPE_DESC);
490 len = sizeof(__pmLogHdr) + sizeof(pmDesc) + LENSIZE;
491
492 tmp.type = htonl(dp->type);
493 tmp.sem = htonl(dp->sem);
494 tmp.indom = __htonpmInDom(dp->indom);
495 tmp.units = __htonpmUnits(dp->units);
496 tmp.pmid = __htonpmID(dp->pmid);
497 odp = &tmp;
498
499 if (numnames > 0) {
500 len += sizeof(numnames);
501 for (i = 0; i < numnames; i++)
502 len += LENSIZE + (int)strlen(names[i]);
503
504 h.len = htonl(len);
505 onumnames = htonl(numnames);
506 if (fwrite(&h, 1, sizeof(__pmLogHdr), f) != sizeof(__pmLogHdr) ||
507 fwrite(odp, 1, sizeof(pmDesc), f) != sizeof(pmDesc) ||
508 fwrite(&onumnames, 1, sizeof(numnames), f) != sizeof(numnames))
509 return -oserror();
510
511 /* write out the names */
512 for (i = 0; i < numnames; i++) {
513 int slen = (int)strlen(names[i]);
514 olen = htonl(slen);
515 if (fwrite(&olen, 1, LENSIZE, f) != LENSIZE)
516 return -oserror();
517 if (fwrite(names[i], 1, slen, f) != slen)
518 return -oserror();
519 }
520
521 olen = htonl(len);
522 if (fwrite(&olen, 1, LENSIZE, f) != LENSIZE)
523 return -oserror();
524 }
525 else {
526 h.len = htonl(len);
527 olen = htonl(len);
528 if (fwrite(&h, 1, sizeof(__pmLogHdr), f) != sizeof(__pmLogHdr) ||
529 fwrite(odp, 1, sizeof(pmDesc), f) != sizeof(pmDesc) ||
530 fwrite(&olen, 1, LENSIZE, f) != LENSIZE)
531 return -oserror();
532 }
533
534 /*
535 * need to make a copy of the pmDesc, and add this, since caller
536 * may re-use *dp
537 */
538 if ((tdp = (pmDesc *)malloc(sizeof(pmDesc))) == NULL)
539 return -oserror();
540 *tdp = *dp; /* struct assignment */
541 return __pmHashAdd((int)dp->pmid, (void *)tdp, &lcp->l_hashpmid);
542 }
543
544 static __pmLogInDom *
545 searchindom(__pmLogCtl *lcp, pmInDom indom, __pmTimeval *tp)
546 {
547 __pmHashNode *hp;
548 __pmLogInDom *idp;
549
550 #ifdef PCP_DEBUG
551 if (pmDebug & DBG_TRACE_LOGMETA)
552 fprintf(stderr, "searchindom( ..., %s, %s)\n",
553 pmInDomStr(indom), StrTimeval(tp));
554 #endif
555
556 if ((hp = __pmHashSearch((unsigned int)indom, &lcp->l_hashindom)) == NULL)
557 return NULL;
558
559 idp = (__pmLogInDom *)hp->data;
560 if (tp != NULL) {
561 for ( ; idp != NULL; idp = idp->next) {
562 /*
563 * need first one at or earlier than the requested time
564 */
565 if (__pmTimevalSub(&idp->stamp, tp) <= 0)
566 break;
567 #ifdef PCP_DEBUG
568 if (pmDebug & DBG_TRACE_LOGMETA) {
569 fprintf(stderr, "request @ %s is ", StrTimeval(tp));
570 fprintf(stderr, "too early for indom @ %s\n",
571 StrTimeval(&idp->stamp));
572 }
573 #endif
574 }
575 if (idp == NULL)
576 return NULL;
577 }
578
579 #ifdef PCP_DEBUG
580 if (pmDebug & DBG_TRACE_LOGMETA)
581 fprintf(stderr, "success for indom @ %s\n",
582 StrTimeval(&idp->stamp));
583 #endif
584 return idp;
585 }
586
587 /*
588 * for the given indom retrieve the instance domain that is correct
589 * as of the latest time (tp == NULL) or at a designated
590 * time
591 */
592 int
593 __pmLogGetInDom(__pmLogCtl *lcp, pmInDom indom, __pmTimeval *tp, int **instlist, char ***namelist)
594 {
595 __pmLogInDom *idp = searchindom(lcp, indom, tp);
596
597 if (idp == NULL)
598 return PM_ERR_INDOM_LOG;
599
600 *instlist = idp->instlist;
601 *namelist = idp->namelist;
602
603 return idp->numinst;
604 }
605
606 int
607 __pmLogLookupInDom(__pmLogCtl *lcp, pmInDom indom, __pmTimeval *tp,
608 const char *name)
609 {
610 __pmLogInDom *idp = searchindom(lcp, indom, tp);
611 int i;
612
613 if (idp == NULL)
614 return PM_ERR_INDOM_LOG;
615
616 if (idp->numinst < 0)
617 return idp->numinst;
618
619 /* full match */
620 for (i = 0; i < idp->numinst; i++) {
621 if (strcmp(name, idp->namelist[i]) == 0)
622 return idp->instlist[i];
623 }
624
625 /* half-baked match to first space */
626 for (i = 0; i < idp->numinst; i++) {
627 char *p = idp->namelist[i];
628 while (*p && *p != ' ')
629 p++;
630 if (*p == ' ') {
631 if (strncmp(name, idp->namelist[i], p - idp->namelist[i]) == 0)
632 return idp->instlist[i];
633 }
634 }
635
636 return PM_ERR_INST_LOG;
637 }
638
639 int
640 __pmLogNameInDom(__pmLogCtl *lcp, pmInDom indom, __pmTimeval *tp, int inst, char **name)
641 {
642 __pmLogInDom *idp = searchindom(lcp, indom, tp);
643 int i;
644
645 if (idp == NULL)
646 return PM_ERR_INDOM_LOG;
647
648 if (idp->numinst < 0)
649 return idp->numinst;
650
651 for (i = 0; i < idp->numinst; i++) {
652 if (inst == idp->instlist[i]) {
653 *name = idp->namelist[i];
654 return 0;
655 }
656 }
657
658 return PM_ERR_INST_LOG;
659 }
660
661 int
662 __pmLogPutInDom(__pmLogCtl *lcp, pmInDom indom, const __pmTimeval *tp,
663 int numinst, int *instlist, char **namelist)
664 {
665 int sts = 0;
666 __pmLogHdr h;
667 int i;
668 int wlen;
669 int strsize;
670 int *stridx;
671 int real_numinst;
672 int onuminst;
673 pmInDom oindom;
674 __pmTimeval otp;
675
676 /*
677 * Note: this routine depends upon the names pointed to by namelist[]
678 * being packed, and starting at namelist[0] ... this is exactly
679 * the format returned by pmGetInDom and __pmLogLoadMeta, so it
680 * should be OK
681 */
682
683 real_numinst = numinst > 0 ? numinst : 0;
684 if ((stridx = (int *)malloc(real_numinst * sizeof(stridx[0]))) == NULL)
685 return -oserror();
686
687 h.len = (int)sizeof(__pmLogHdr) + (int)sizeof(*tp) + (int)sizeof(indom) +
688 (int)sizeof(numinst) +
689 real_numinst * ((int)sizeof(instlist[0]) + (int)sizeof(stridx[0])) +
690 (int)sizeof(h.len);
691 strsize = 0;
692 for (i = 0; i < numinst; i++) {
693 strsize += (int)strlen(namelist[i]) + 1;
694 /* see Note */
695 stridx[i] = (int)((ptrdiff_t)namelist[i] - (ptrdiff_t)namelist[0]);
696 stridx[i] = htonl(stridx[i]); /* swab */
697 instlist[i] = htonl(instlist[i]); /* swab: this is changed back after writing */
698 }
699 h.len += strsize;
700
701 /* swab all output buffers */
702 h.len = htonl(h.len);
703 h.type = htonl(TYPE_INDOM);
704 otp.tv_sec = htonl(tp->tv_sec);
705 otp.tv_usec = htonl(tp->tv_usec);
706 oindom = __htonpmInDom(indom);
707 onuminst = htonl(numinst);
708
709 wlen = (int)fwrite(&h, 1, sizeof(__pmLogHdr), lcp->l_mdfp);
710 wlen += fwrite(&otp, 1, sizeof(otp), lcp->l_mdfp);
711 wlen += fwrite(&oindom, 1, sizeof(oindom), lcp->l_mdfp);
712 wlen += fwrite(&onuminst, 1, sizeof(onuminst), lcp->l_mdfp);
713 if (numinst > 0) {
714 wlen += fwrite(instlist, 1, real_numinst * sizeof(instlist[0]), lcp->l_mdfp);
715 wlen += fwrite(stridx, 1, real_numinst * sizeof(stridx[0]), lcp->l_mdfp);
716 /* see Note */
717 wlen += fwrite(namelist[0], 1, strsize, lcp->l_mdfp);
718 }
719 wlen += fwrite(&h.len, 1, sizeof(h.len), lcp->l_mdfp);
720 free(stridx);
721
722 if (wlen != (int)ntohl(h.len)) {
723 pmprintf("__pmLogPutInDom: wrote %d, expected %d: %s\n",
724 wlen, (int)ntohl(h.len), osstrerror());
725 pmflush();
726 return -oserror();
727 }
728
729 sts = addindom(lcp, indom, tp, numinst, instlist, namelist, NULL, 0);
730
731 /* swab instance list back again so as to not upset the caller */
732 for (i = 0; i < numinst; i++) {
733 instlist[i] = ntohl(instlist[i]);
734 }
735
736 return sts;
737 }
738
739 int
740 pmLookupInDomArchive(pmInDom indom, const char *name)
741 {
742 int n;
743 int j;
744 __pmHashNode *hp;
745 __pmLogInDom *idp;
746 __pmContext *ctxp;
747
748 if (indom == PM_INDOM_NULL)
749 return PM_ERR_INDOM;
750
751 if ((n = pmWhichContext()) >= 0) {
752 ctxp = __pmHandleToPtr(n);
753 if (ctxp->c_type != PM_CONTEXT_ARCHIVE)
754 return PM_ERR_NOTARCHIVE;
755
756 if ((hp = __pmHashSearch((unsigned int)indom, &ctxp->c_archctl->ac_log->l_hashindom)) == NULL)
757 return PM_ERR_INDOM_LOG;
758
759 for (idp = (__pmLogInDom *)hp->data; idp != NULL; idp = idp->next) {
760 /* full match */
761 for (j = 0; j < idp->numinst; j++) {
762 if (strcmp(name, idp->namelist[j]) == 0) {
763 return idp->instlist[j];
764 }
765 }
766 /* half-baked match to first space */
767 for (j = 0; j < idp->numinst; j++) {
768 char *p = idp->namelist[j];
769 while (*p && *p != ' ')
770 p++;
771 if (*p == ' ') {
772 if (strncmp(name, idp->namelist[j], p - idp->namelist[j]) == 0)
773 return idp->instlist[j];
774 }
775 }
776 }
777 n = PM_ERR_INST_LOG;
778 }
779
780 return n;
781 }
782
783 int
784 pmNameInDomArchive(pmInDom indom, int inst, char **name)
785 {
786 int n;
787 int j;
788 __pmHashNode *hp;
789 __pmLogInDom *idp;
790 __pmContext *ctxp;
791
792 if (indom == PM_INDOM_NULL)
793 return PM_ERR_INDOM;
794
795 if ((n = pmWhichContext()) >= 0) {
796 ctxp = __pmHandleToPtr(n);
797 if (ctxp->c_type != PM_CONTEXT_ARCHIVE)
798 return PM_ERR_NOTARCHIVE;
799
800 if ((hp = __pmHashSearch((unsigned int)indom, &ctxp->c_archctl->ac_log->l_hashindom)) == NULL)
801 return PM_ERR_INDOM_LOG;
802
803 for (idp = (__pmLogInDom *)hp->data; idp != NULL; idp = idp->next) {
804 for (j = 0; j < idp->numinst; j++) {
805 if (idp->instlist[j] == inst) {
806 if ((*name = strdup(idp->namelist[j])) == NULL)
807 n = -oserror();
808 else
809 n = 0;
810 return n;
811 }
812 }
813 }
814 n = PM_ERR_INST_LOG;
815 }
816
817 return n;
818 }
819
820 int
821 pmGetInDomArchive(pmInDom indom, int **instlist, char ***namelist)
822 {
823 int n;
824 int i;
825 int j;
826 char *p;
827 __pmContext *ctxp;
828 __pmHashNode *hp;
829 __pmLogInDom *idp;
830 int numinst = 0;
831 int strsize = 0;
832 int *ilist = NULL;
833 char **nlist = NULL;
834 char **olist;
835
836 /* avoid ambiguity when no instances or errors */
837 *instlist = NULL;
838 *namelist = NULL;
839 if (indom == PM_INDOM_NULL)
840 return PM_ERR_INDOM;
841
842 if ((n = pmWhichContext()) >= 0) {
843 ctxp = __pmHandleToPtr(n);
844 if (ctxp->c_type != PM_CONTEXT_ARCHIVE)
845 return PM_ERR_NOTARCHIVE;
846
847 if ((hp = __pmHashSearch((unsigned int)indom, &ctxp->c_archctl->ac_log->l_hashindom)) == NULL)
848 return PM_ERR_INDOM_LOG;
849
850 for (idp = (__pmLogInDom *)hp->data; idp != NULL; idp = idp->next) {
851 for (j = 0; j < idp->numinst; j++) {
852 for (i = 0; i < numinst; i++) {
853 if (idp->instlist[j] == ilist[i])
854 break;
855 }
856 if (i == numinst) {
857 numinst++;
858 if ((ilist = (int *)realloc(ilist, numinst*sizeof(ilist[0]))) == NULL) {
859 __pmNoMem("pmGetInDomArchive: ilist", numinst*sizeof(ilist[0]), PM_FATAL_ERR);
860 }
861 if ((nlist = (char **)realloc(nlist, numinst*sizeof(nlist[0]))) == NULL) {
862 __pmNoMem("pmGetInDomArchive: nlist", numinst*sizeof(nlist[0]), PM_FATAL_ERR);
863 }
864 ilist[numinst-1] = idp->instlist[j];
865 nlist[numinst-1] = idp->namelist[j];
866 strsize += strlen(idp->namelist[j])+1;
867 }
868 }
869 }
870 if ((olist = (char **)malloc(numinst*sizeof(olist[0]) + strsize)) == NULL) {
871 __pmNoMem("pmGetInDomArchive: olist", numinst*sizeof(olist[0]) + strsize, PM_FATAL_ERR);
872 }
873 p = (char *)olist;
874 p += numinst * sizeof(olist[0]);
875 for (i = 0; i < numinst; i++) {
876 olist[i] = p;
877 strcpy(p, nlist[i]);
878 p += strlen(nlist[i]) + 1;
879 }
880 free(nlist);
881 *instlist = ilist;
882 *namelist = olist;
883 n = numinst;
884 }
885
886 return n;
887 }