1    	/*
2    	 * Copyright (c) 1995 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 <stdio.h>
16   	#include <sys/time.h>
17   	#include "pmapi.h"
18   	#include "impl.h"
19   	#include "pmda.h"
20   	
21   	int
22   	__pmFetchLocal(int numpmid, pmID pmidlist[], pmResult **result)
23   	{
24   	    int		sts;
25   	    int		ctx;
26   	    int		j;
27   	    int		k;
28   	    int		n;
29   	    __pmContext	*ctxp;
30   	    pmResult	*ans;
31   	    pmResult	*tmp_ans;
32   	    __pmDSO	*dp;
33   	    int		need;
34   	
35   	    static pmID * splitlist=NULL;
36   	    static int	splitmax=0;
37   	
38   	    if (numpmid < 1)
39   		return PM_ERR_TOOSMALL;
40   	
41   	    if ((ctx = pmWhichContext()) < 0)
42   		return ctx;
43   	    ctxp = __pmHandleToPtr(ctx);
44   	
45   	    /*
46   	     * this is very ugly ... the DSOs have a high-water mark
47   	     * allocation algorithm for the result skeleton, but the
48   	     * code that calls us assumes it has freedom to retain
49   	     * this result structure for as long as it wishes, and
50   	     * then to call pmFreeResult
51   	     *
52   	     * we make another skeleton, selectively copy and return that
53   	     *
54   	     * (numpmid - 1) because there's room for one valueSet
55   	     * in a pmResult
56   	     */
57   	    need = (int)sizeof(pmResult) + (numpmid - 1) * (int)sizeof(pmValueSet *);
Event alloc_fn: Calling allocation function "malloc".
Event var_assign: Assigning: "ans" = storage returned from "malloc(need)".
Also see events: [leaked_storage][noescape][leaked_storage]
At conditional (1): "(ans = (pmResult *)malloc(need)) == NULL": Taking false branch.
58   	    if ((ans = (pmResult *)malloc(need)) == NULL)
59   		return -oserror();
60   	
61   	    /*
62   	     * Check if we have enough space to accomodate "best" case scenario -
63   	     * all pmids are from the same domain
64   	     */
At conditional (2): "splitmax < numpmid": Taking true branch.
65   	    if ( splitmax < numpmid ) {
66   		splitmax = numpmid;
At conditional (3): "(splitlist = (pmID *)realloc(splitlist, sizeof (pmID) /*4*/ * splitmax)) == NULL": Taking true branch.
67   		if ((splitlist = (pmID *)realloc (splitlist,
68   						  sizeof (pmID)*splitmax)) == NULL) {
69   		    splitmax = 0;
Event leaked_storage: Variable "ans" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign][noescape][leaked_storage]
70   		    return -oserror();
71   		}
72   	    }
73   	
74   	    ans->numpmid = numpmid;
Event noescape: Variable "ans" is not freed or pointed-to in function "__pmtimevalNow". [details]
Also see events: [alloc_fn][var_assign][leaked_storage][leaked_storage]
75   	    __pmtimevalNow(&ans->timestamp);
76   	    for (j = 0; j < numpmid; j++)
77   		ans->vset[j] = NULL;
78   	
79   	    for (j = 0; j < numpmid; j++) {
80   		int cnt;
81   	
82   		if (ans->vset[j] != NULL)
83   		    /* picked up in a previous fetch */
84   		    continue;
85   	
86   		sts = 0;
87   		if ((dp = __pmLookupDSO(((__pmID_int *)&pmidlist[j])->domain)) == NULL)
88   		    /* based on domain, unknown PMDA */
89   		    sts = PM_ERR_NOAGENT;
90   		else {
91   		    if (ctxp->c_sent != dp->domain) {
92   			/*
93   			 * current profile is _not_ already cached at other end of
94   			 * IPC, so send get current profile ...
95   			 * Note: trickier than the non-local case, as no per-PMDA
96   			 *	 caching at the PMCD end, so need to remember the
97   			 *	 last domain to receive a profile
98   			 */
99   	#ifdef PCP_DEBUG
100  			if (pmDebug & DBG_TRACE_FETCH)
101  			    fprintf(stderr, 
102  				    "__pmFetchLocal: calling ???_profile(domain: %d), "
103  				    "context: %d\n", dp->domain, ctx);
104  	#endif
105  			if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_5)
106  			    dp->dispatch.version.four.ext->e_context = ctx;
107  			if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_4)
108  			    sts = dp->dispatch.version.four.profile(ctxp->c_instprof,
109  								   dp->dispatch.version.four.ext);
110  			else if (dp->dispatch.comm.pmda_interface == PMDA_INTERFACE_3 ||
111  			         dp->dispatch.comm.pmda_interface == PMDA_INTERFACE_2)
112  			    sts = dp->dispatch.version.two.profile(ctxp->c_instprof,
113  								   dp->dispatch.version.two.ext);
114  			else
115  			    sts = dp->dispatch.version.one.profile(ctxp->c_instprof);
116  			if (sts >= 0)
117  			    ctxp->c_sent = dp->domain;
118  		    }
119  	
120  		}
121  	
122  		/* Copy all pmID for the current domain into the temp. list */
123  		for (cnt=0, k=j; k < numpmid; k++ ) {
124  		    if (((__pmID_int*)(pmidlist+k))->domain == ((__pmID_int*)(pmidlist+j))->domain) {
125  			splitlist[cnt++] = pmidlist[k];
126  		    }
127  		}
128  	
129  		if (sts >= 0) {
130  		    if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_5)
131  			dp->dispatch.version.four.ext->e_context = ctx;
132  		    if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_4)
133  			sts = dp->dispatch.version.four.fetch(cnt, splitlist, &tmp_ans,
134  							     dp->dispatch.version.four.ext);
135  		    else if (dp->dispatch.comm.pmda_interface == PMDA_INTERFACE_3 ||
136  			     dp->dispatch.comm.pmda_interface == PMDA_INTERFACE_2)
137  			sts = dp->dispatch.version.two.fetch(cnt, splitlist, &tmp_ans,
138  							     dp->dispatch.version.two.ext);
139  		    else
140  			sts = dp->dispatch.version.one.fetch(cnt, splitlist, &tmp_ans);
141  		}
142  	
143  		/* Copy results back
144  		 *
145  		 * Note: We DO NOT have to free tmp_ans since DSO PMDA would
146  		 *		ALWAYS return a pointer to the static area.
147  		 */
148  		for (n = 0, k = j; k < numpmid && n < cnt; k++) {
149  		    if ( pmidlist[k] == splitlist[n] ) {
150  			if (sts < 0) {
151  			    ans->vset[k] = (pmValueSet *)malloc(sizeof(pmValueSet));
152  			    if (ans->vset[k] == NULL)
Event leaked_storage: Variable "ans" going out of scope leaks the storage it points to.
Also see events: [alloc_fn][var_assign][leaked_storage][noescape]
153  				return -oserror();
154  			    ans->vset[k]->numval = sts;
155  			    ans->vset[k]->pmid = pmidlist[k];
156  			}
157  			else {
158  			    ans->vset[k] = tmp_ans->vset[n];
159  			}
160  	#ifdef PCP_DEBUG
161  			if (pmDebug & DBG_TRACE_FETCH) {
162  			    fprintf(stderr, "__pmFetchLocal: [%d] PMID=%s nval=",
163  				    k, pmIDStr(pmidlist[k]));
164  			    if (ans->vset[k]->numval < 0)
165  				fprintf(stderr, "%s\n",
166  					pmErrStr(ans->vset[k]->numval));
167  			    else
168  				fprintf(stderr, "%d\n", ans->vset[k]->numval);
169  			}
170  	#endif
171  			n++;
172  		    }
173  		}
174  	    }
175  	    *result = ans;
176  	
177  	    return 0;
178  	}