1 /*
2 * Copyright (c) 1995-2003 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program 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 General Public License
12 * for more details.
13 */
14
15 #include "logger.h"
16 #include "pmda.h"
17
18 /*
19 * this routine creates the "fake" pmResult to be added to the
20 * start of the archive log to identify information about the
21 * archive beyond what is in the archive label.
22 */
23
24 /* encode the domain(x), cluster (y) and item (z) parts of the PMID */
25 #define PMID(x,y,z) ((x<<22)|(y<<10)|z)
26
27 /* encode the domain(x) and serial (y) parts of the pmInDom */
28 #define INDOM(x,y) ((x<<22)|y)
29
30 /*
31 * Note: these pmDesc entries MUST correspond to the corrsponding
32 * entries from the real PMDA ...
33 * We fake it out here to accommodate logging from PCP 1.1
34 * PMCD's and to avoid round-trip dependencies in setting up
35 * the preamble
36 */
37 static pmDesc desc[] = {
38 /* pmcd.pmlogger.host */
39 { PMID(2,3,3), PM_TYPE_STRING, INDOM(2,1), PM_SEM_DISCRETE, {0,0,0,0,0,0} },
40 /* pmcd.pmlogger.port */
41 { PMID(2,3,0), PM_TYPE_U32, INDOM(2,1), PM_SEM_DISCRETE, {0,0,0,0,0,0} },
42 /* pmcd.pmlogger.archive */
43 { PMID(2,3,2), PM_TYPE_STRING, INDOM(2,1), PM_SEM_DISCRETE, {0,0,0,0,0,0} },
44 };
45 /* names added for version 2 archives */
46 static char* names[] = {
47 "pmcd.pmlogger.host",
48 "pmcd.pmlogger.port",
49 "pmcd.pmlogger.archive"
50 };
51
52 static int n_metric = sizeof(desc) / sizeof(desc[0]);
53
54 int
55 do_preamble(void)
56 {
57 int sts;
58 int i;
59 int j;
60 pid_t mypid = getpid();
61 pmResult *res;
62 __pmPDU *pb;
63 pmAtomValue atom;
64 __pmTimeval tmp;
65 char path[MAXPATHLEN];
66 char host[MAXHOSTNAMELEN];
67
68 /* start to build the pmResult */
69 res = (pmResult *)malloc(sizeof(pmResult) + (n_metric - 1) * sizeof(pmValueSet *));
70 if (res == NULL)
71 return -oserror();
72
73 res->numpmid = n_metric;
74 last_stamp = res->timestamp = epoch; /* struct assignment */
75 tmp.tv_sec = (__int32_t)epoch.tv_sec;
76 tmp.tv_usec = (__int32_t)epoch.tv_usec;
77
78 for (i = 0; i < n_metric; i++) {
79 res->vset[i] = (pmValueSet *)__pmPoolAlloc(sizeof(pmValueSet));
80 if (res->vset[i] == NULL)
81 return -oserror();
82 res->vset[i]->pmid = desc[i].pmid;
83 res->vset[i]->numval = 1;
84 /* special case for each value 0 .. n_metric-1 */
85 if (desc[i].pmid == PMID(2,3,3)) {
86 /* my fully qualified hostname, cloned from the pmcd PMDA */
87 struct hostent *hep = NULL;
88 (void)gethostname(host, MAXHOSTNAMELEN);
89 host[MAXHOSTNAMELEN-1] = '\0';
90 hep = gethostbyname(host);
91 if (hep != NULL)
92 atom.cp = hep->h_name;
93 else
94 atom.cp = host;
95 }
96 else if (desc[i].pmid == PMID(2,3,0)) {
97 /* my control port number, from ports.c */
98 atom.l = ctlport;
99 }
100 else if (desc[i].pmid == PMID(2,3,2)) {
101 /*
102 * the full pathname to the base of the archive, cloned
103 * from GetPort() in ports.c
104 */
105 if (__pmAbsolutePath(archBase))
106 atom.cp = archBase;
107 else {
108 if (getcwd(path, MAXPATHLEN) == NULL)
109 atom.cp = archBase;
110 else {
111 strcat(path, "/");
112 strcat(path, archBase);
113 atom.cp = path;
114 }
115 }
116 }
117
118 sts = __pmStuffValue(&atom, &res->vset[i]->vlist[0], desc[i].type);
119 if (sts < 0)
120 return sts;
121 res->vset[i]->vlist[0].inst = (int)mypid;
122 res->vset[i]->valfmt = sts;
123 }
124
125 if ((sts = __pmEncodeResult(fileno(logctl.l_mfp), res, &pb)) < 0)
126 return sts;
127
128 __pmOverrideLastFd(fileno(logctl.l_mfp)); /* force use of log version */
129 /* and start some writing to the archive log files ... */
130 if ((sts = __pmLogPutResult(&logctl, pb)) < 0)
131 return sts;
132
133 for (i = 0; i < n_metric; i++) {
134 if (archive_version == PM_LOG_VERS02) {
135 if ((sts = __pmLogPutDesc(&logctl, &desc[i], 1, &names[i])) < 0)
136 return sts;
137 }
138 else {
139 if ((sts = __pmLogPutDesc(&logctl, &desc[i], 0, NULL)) < 0)
140 return sts;
141 }
142 if (desc[i].indom == PM_INDOM_NULL)
143 continue;
144 for (j = 0; j < i; j++) {
145 if (desc[i].indom == desc[j].indom)
146 break;
147 }
148 if (j == i) {
149 /* need indom ... force one with my PID as the only instance */
150 int *instid;
151 char **instname;
152
|
Event alloc_fn: |
Calling allocation function "malloc". |
|
Event var_assign: |
Assigning: "instid" = storage returned from "malloc(sizeof (*instid) /*4*/)". |
| Also see events: |
[leaked_storage] |
|
At conditional (1): "(instid = (int *)malloc(sizeof (*instid) /*4*/)) == NULL": Taking false branch.
|
153 if ((instid = (int *)malloc(sizeof(*instid))) == NULL)
154 return -oserror();
155 *instid = (int)mypid;
156 sprintf(path, "%" FMT_PID, mypid);
|
At conditional (2): "(instname = (char **)malloc(sizeof (char *) /*8*/ + strlen(path) + 1UL)) == NULL": Taking true branch.
|
157 if ((instname = (char **)malloc(sizeof(char *)+strlen(path)+1)) == NULL)
|
Event leaked_storage: |
Variable "instid" going out of scope leaks the storage it points to. |
| Also see events: |
[alloc_fn][var_assign] |
158 return -oserror();
159 /*
160 * this _is_ correct ... instname[] is a one element array
161 * with the string value immediately following
162 */
163 instname[0] = (char *)&instname[1];
164 strcpy(instname[0], path);
165 /*
166 * Note. DO NOT free instid and instname ... they get hidden
167 * away in addindom() below __pmLogPutInDom()
168 */
169 if ((sts = __pmLogPutInDom(&logctl, desc[i].indom, &tmp, 1, instid, instname)) < 0)
170 return sts;
171 }
172 }
173
174 /* fudge the temporal index */
175 fflush(logctl.l_mfp);
176 fseek(logctl.l_mfp, sizeof(__pmLogLabel)+2*sizeof(int), SEEK_SET);
177 fflush(logctl.l_mdfp);
178 fseek(logctl.l_mdfp, sizeof(__pmLogLabel)+2*sizeof(int), SEEK_SET);
179 __pmLogPutIndex(&logctl, &tmp);
180 fseek(logctl.l_mfp, 0L, SEEK_END);
181 fseek(logctl.l_mdfp, 0L, SEEK_END);
182
183 /*
184 * and now free stuff
185 * Note: error returns cause mem leaks, but this routine
186 * is only ever called once, so tough luck
187 */
188 for (i = 0; i < n_metric; i++)
189 __pmPoolFree(res->vset[i], sizeof(pmValueSet));
190 free(res);
191
192 return 0;
193 }