1    	/*
2    	 * metriclist.c
3    	 *
4    	 * Copyright (c) 1997,2005 Silicon Graphics, Inc.  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   	 * You should have received a copy of the GNU General Public License along
17   	 * with this program; if not, write to the Free Software Foundation, Inc.,
18   	 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19   	 */
20   	
21   	#include "pmapi.h"
22   	#include "impl.h"
23   	#include "logger.h"
24   	
25   	extern int	ilog;
26   	
27   	/*
28   	 * extract the pmid in vsetp and all its instances, and put it in
29   	 * a pmResult of its own
30   	 */
31   	void
32   	extractpmid(pmValueSet *vsetp, struct timeval *timestamp, pmResult **resp)
33   	{
34   	    int			i;
35   	    int			size;
36   	    pmResult		*result;
37   	    pmValueBlock	*vbp;		/* value block pointer */
38   	
39   	
40   	    result = (pmResult *)malloc(sizeof(pmResult));
41   	    if (result == NULL) {
42   		fprintf(stderr, "%s: Error: cannot malloc space in \"extractpmid\".\n",
43   			pmProgname);
44   		exit(1);
45   	    }
46   	
47   	    size = sizeof(pmValueSet) + (vsetp->numval-1) * sizeof(pmValue);
48   	    result->vset[0] = (pmValueSet *)malloc(size);
49   	    if (result->vset[0] == NULL) {
50   		fprintf(stderr, "%s: Error: cannot malloc space in \"extractpmid\".\n",
51   			pmProgname);
52   		exit(1);
53   	    }
54   	
55   	
56   	    result->timestamp.tv_sec = timestamp->tv_sec;
57   	    result->timestamp.tv_usec = timestamp->tv_usec;
58   	    result->numpmid = 1;
59   	    result->vset[0]->pmid = vsetp->pmid;
60   	    result->vset[0]->numval = vsetp->numval;
61   	    result->vset[0]->valfmt = vsetp->valfmt;
62   	
63   	
64   	    for(i=0; i<vsetp->numval; i++) {
65   		result->vset[0]->vlist[i].inst = vsetp->vlist[i].inst;
66   		if (vsetp->valfmt == PM_VAL_INSITU)
67   		    result->vset[0]->vlist[i].value = vsetp->vlist[i].value;
68   		else {
69   		    vbp = vsetp->vlist[i].value.pval;
70   	
71   		    size = (int)vbp->vlen;
72   		    result->vset[0]->vlist[i].value.pval = (pmValueBlock *)malloc(size);
73   		    if (result->vset[0]->vlist[i].value.pval == NULL) {
74   			fprintf(stderr,
75   			    "%s: Error: cannot malloc space in \"extractpmid\".\n",
76   				pmProgname);
77   			exit(1);
78   	    	    }
79   	
80   		    result->vset[0]->vlist[i].value.pval->vtype = vbp->vtype;
81   		    result->vset[0]->vlist[i].value.pval->vlen = vbp->vlen;
82   	
83   		    /* in a pmValueBlock, the first byte is assigned to vtype,
84   		     * and the subsequent 3 bytes are assigned to vlen - that's
85   		     * a total of 4 bytes - the rest is used for vbuf
86   		     */
87   		    if (vbp->vlen < 4) {
88   			fprintf(stderr, "%s: Warning: pmValueBlock vlen (%u) is too small\n", pmProgname, vbp->vlen);
89   		    }
90   		    memcpy(result->vset[0]->vlist[i].value.pval->vbuf,
91   							vbp->vbuf, vbp->vlen-4);
92   		}
93   	    } /*for(i)*/
94   	
95   	    *resp = result;
96   	}
97   	
98   	rlist_t *
99   	mk_rlist_t(void)
100  	{
101  	    rlist_t	*rlist;
102  	    if ((rlist = (rlist_t *)malloc(sizeof(rlist_t))) == NULL) {
103  		fprintf(stderr, "%s: Error: cannot malloc space in \"mk_rlist_t\"\n",
104  			pmProgname);
105  		exit(1);
106  	    }
107  	    rlist->res = NULL;
108  	    rlist->next = NULL;
109  	    return(rlist);
110  	}
111  	
112  	
113  	/*
114  	 * insert rlist element in rlist list
115  	 */
116  	void
117  	insertrlist(rlist_t **rlist, rlist_t *elm)
118  	{
119  	    rlist_t	*curr;
120  	    rlist_t	*prev;
121  	
Event deref_ptr: Directly dereferencing pointer "elm".
Also see events: [check_after_deref]
122  	    elm->next = NULL;
123  	
Event check_after_deref: Dereferencing "elm" before a null check.
Also see events: [deref_ptr]
124  	    if (elm == NULL)
125  		return;
126  	
127  	    if (*rlist == NULL) {
128  		*rlist = elm;
129  		return;
130  	    }
131  	
132  	    if (elm->res->timestamp.tv_sec < (*rlist)->res->timestamp.tv_sec ||
133  		(elm->res->timestamp.tv_sec == (*rlist)->res->timestamp.tv_sec &&
134  		elm->res->timestamp.tv_usec <= (*rlist)->res->timestamp.tv_usec)) {
135  		    curr = *rlist;
136  		    *rlist = elm;
137  		    (*rlist)->next = curr;
138  		    return;
139  	    }
140  	
141  	    curr = (*rlist)->next;
142  	    prev = *rlist;
143  	
144  	    while (curr != NULL) {
145  		if (elm->res->timestamp.tv_sec < curr->res->timestamp.tv_sec ||
146  		    (elm->res->timestamp.tv_sec == curr->res->timestamp.tv_sec &&
147  		    elm->res->timestamp.tv_usec <= curr->res->timestamp.tv_usec)) {
148  			break;
149  		}
150  		prev = curr;
151  		curr = prev->next;
152  	    }
153  	
154  	    prev->next = elm;
155  	    elm->next = curr;
156  	}
157  	
158  	
159  	/*
160  	 * insert pmResult in rlist list
161  	 */
162  	void
163  	insertresult(rlist_t **rlist, pmResult *result)
164  	{
165  	    rlist_t	*elm;
166  	
167  	    elm = mk_rlist_t();
168  	    elm->res = result;
169  	    elm->next = NULL;
170  	
171  	    insertrlist (rlist, elm);
172  	}
173  	
174  	/*
175  	 * Find out whether the metrics in _result are in the metric list ml
176  	 */
177  	pmResult *
178  	searchmlist(pmResult *_Oresult)
179  	{
180  	    int		i;
181  	    int		j;
182  	    int		k;
183  	    int		q;
184  	    int		r;
185  	    int		found = 0;
186  	    int		maxinst = 0;		/* max number of instances */
187  	    int		numpmid = 0;
188  	    int		*ilist;
189  	    int		*jlist;
190  	    pmResult	*_Nresult;
191  	    pmValue	*vlistp = NULL;		/* temporary list of instances */
192  	    pmValueSet	*vsetp;			/* value set pointer */
193  	
194  	    ilist = (int *) malloc(_Oresult->numpmid * sizeof(int));
195  	    if (ilist == NULL)
196  		goto nomem;
197  	
198  	    jlist = (int *) malloc(_Oresult->numpmid * sizeof(int));
199  	    if (jlist == NULL)
200  		goto nomem;
201  	
202  	    /* find out how many of the pmid's in _Oresult need to be written out
203  	     * (also, find out the maximum number of instances to write out)
204  	     */
205  	    numpmid = 0;
206  	    maxinst = 0;
207  	    for (i=0; i<_Oresult->numpmid; i++) {
208  		vsetp = _Oresult->vset[i];
209  	
210  		for (j=0; j<ml_numpmid; j++) {
211  		    if (vsetp->pmid == ml[j].idesc->pmid) {
212  			/* pmid has been found in metric list
213  			 */
214  			if (ml[j].numinst > maxinst)
215  			    maxinst = ml[j].numinst;
216  	
217  			++numpmid;
218  			ilist[numpmid-1] = i;	/* _Oresult index */
219  			jlist[numpmid-1] = j;	/* ml list index */
220  			break;
221  		    }
222  		}
223  	    }
224  	
225  	
226  	    /*  if no matches (no pmid's are ready for writing), then return
227  	     */
228  	    if (numpmid == 0) {
229  		free(ilist);
230  		free(jlist);
231  		return(NULL);
232  	    }
233  	
234  	
235  	    /*  `numpmid' matches were found (some or all pmid's are ready for writing),
236  	     *	then allocate space for new result
237  	     */
238  	    _Nresult = (pmResult *) malloc(sizeof(pmResult) +
239  						(numpmid - 1) * sizeof(pmValueSet *));
240  	    if (_Nresult == NULL)
241  		goto nomem;
242  	
243  	    _Nresult->timestamp.tv_sec = _Oresult->timestamp.tv_sec;
244  	    _Nresult->timestamp.tv_usec = _Oresult->timestamp.tv_usec;
245  	    _Nresult->numpmid = numpmid;
246  	
247  	
248  	    /*  make array for indeces into vlist
249  	     */
250  	    if (maxinst > 0) {
251  		vlistp = (pmValue *) malloc(maxinst * sizeof(pmValue));
252  		if (vlistp == NULL)
253  		    goto nomem;
254  	    }
255  	
256  	
257  	    /*  point _Nresult at the right pmValueSet(s)
258  	     */
259  	    for (k=0; k<numpmid; k++) {
260  		i = ilist[k];
261  		j = jlist[k];
262  	
263  		/* point new result at the wanted pmid
264  		 */
265  		_Nresult->vset[k] = _Oresult->vset[i];
266  	
267  	
268  		/* allocate the right instances
269  		 */
270  		vsetp = _Nresult->vset[k];
271  	
272  		found = 0;
273  		for (q=0; q<ml[j].numinst; q++) {
274  		    for (r=0; r<vsetp->numval; r++) {
275  	
276  			/* if id in ml is -1, chances are that we haven't seen
277  			 * it before ... set the instance id
278  			 */
279  			if (ml[j].instlist[q].id < 0)
280  			    ml[j].instlist[q].id = vsetp->vlist[r].inst;
281  	
282  			if (ml[j].instlist[q].id == vsetp->vlist[r].inst) {
283  			    /* instance has been found
284  			     */
285  			    vlistp[found].inst = vsetp->vlist[r].inst;
286  			    vlistp[found].value = vsetp->vlist[r].value;
287  			    ++found;
288  			    break;
289  			} /*if*/
290  		    } /*for(r)*/
291  		} /*for(q)*/
292  	
293  	
294  		/* note: found may be <= ml[j].numinst
295  		 *	 further more, found may be zero ... deal with this later?
296  		 *		- NUMVAL
297  		 */
298  		vsetp->numval = found;
299  	
300  		for (q=0; q<vsetp->numval; q++) {
301  		    vsetp->vlist[q].inst = vlistp[q].inst;
302  		    vsetp->vlist[q].value = vlistp[q].value;
303  		    vlistp[q].inst = 0;
304  		    vlistp[q].value.lval = 0;
305  		} /*for(q)*/
306  	    } /*for(k)*/
307  	
308  	    free(ilist);
309  	    free(jlist);
310  	    if (maxinst > 0) free(vlistp);	/* free only if space was allocated */
311  	    return(_Nresult);
312  	
313  	nomem:
314  	    fprintf(stderr, "%s: Error: cannot malloc space in \"searchmlist\".\n",
315  		    pmProgname);
316  	    exit(1);
317  	}