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 */
Event alloc_fn: Calling allocation function "malloc".
Event var_assign: Assigning: "res" = storage returned from "malloc(sizeof (pmResult) /*32*/ + (n_metric - 1) * sizeof (pmValueSet *) /*8*/)".
Also see events: [leaked_storage][leaked_storage][noescape][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage]
69   	    res = (pmResult *)malloc(sizeof(pmResult) + (n_metric - 1) * sizeof(pmValueSet *));
At conditional (1): "res == NULL": Taking false branch.
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   	
At conditional (2): "i < n_metric": Taking true branch.
78   	    for (i = 0; i < n_metric; i++) {
79   		res->vset[i] = (pmValueSet *)__pmPoolAlloc(sizeof(pmValueSet));
At conditional (3): "res->vset[i] == NULL": Taking true branch.
80   		if (res->vset[i] == NULL)
Event leaked_storage: Variable "res" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign][leaked_storage][noescape][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage]
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)
Event leaked_storage: Variable "res" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign][leaked_storage][noescape][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage]
120  		    return sts;
121  		res->vset[i]->vlist[0].inst = (int)mypid;
122  		res->vset[i]->valfmt = sts;
123  	    }
124  	
Event noescape: Variable "res" is not freed or pointed-to in function "__pmEncodeResult". [details]
Also see events: [alloc_fn][var_assign][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage]
125  	    if ((sts = __pmEncodeResult(fileno(logctl.l_mfp), res, &pb)) < 0)
Event leaked_storage: Variable "res" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign][leaked_storage][leaked_storage][noescape][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage]
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)
Event leaked_storage: Variable "res" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign][leaked_storage][leaked_storage][noescape][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage]
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)
Event leaked_storage: Variable "res" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign][leaked_storage][leaked_storage][noescape][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage]
136  			return sts;
137  	        }
138  	        else {
139  		    if ((sts = __pmLogPutDesc(&logctl, &desc[i], 0, NULL)) < 0)
Event leaked_storage: Variable "res" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign][leaked_storage][leaked_storage][noescape][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage]
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  	
153  		    if ((instid = (int *)malloc(sizeof(*instid))) == NULL)
Event leaked_storage: Variable "res" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign][leaked_storage][leaked_storage][noescape][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage]
154  			return -oserror();
155  		    *instid = (int)mypid;
156  		    sprintf(path, "%" FMT_PID, mypid);
157  		    if ((instname = (char **)malloc(sizeof(char *)+strlen(path)+1)) == NULL)
Event leaked_storage: Variable "res" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign][leaked_storage][leaked_storage][noescape][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage]
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)
Event leaked_storage: Variable "res" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign][leaked_storage][leaked_storage][noescape][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage][leaked_storage]
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  	}