1    	/*
2    	 * Copyright (c) 1995 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   	 * You should have received a copy of the GNU General Public License along
15   	 * with this program; if not, write to the Free Software Foundation, Inc.,
16   	 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17   	 */
18   	
19   	#include "logger.h"
20   	
21   	int
22   	myFetch(int numpmid, pmID pmidlist[], __pmPDU **pdup)
23   	{
24   	    int			n = 0;
25   	    int			ctx;
26   	    __pmPDU		*pb;
27   	    __pmContext		*ctxp;
28   	
29   	    if (numpmid < 1)
30   		return PM_ERR_TOOSMALL;
31   	
32   	    if ((ctx = pmWhichContext()) >= 0) {
33   		ctxp = __pmHandleToPtr(ctx);
34   		if (ctxp->c_type != PM_CONTEXT_HOST)
35   		    return PM_ERR_NOTHOST;
36   	    }
37   	    else
38   		return PM_ERR_NOCONTEXT;
39   	
40   	#if CAN_RECONNECT
41   	    if (ctxp->c_pmcd->pc_fd == -1) {
42   		/* lost connection, try to get it back */
43   		n = reconnect();
44   		if (n < 0)
45   		    return n;
46   	    }
47   	#endif
48   	
49   	    if (ctxp->c_sent == 0) {
50   		/*
51   		 * current profile is _not_ already cached at other end of
52   		 * IPC, so send current profile
53   		 */
54   	#ifdef PCP_DEBUG
55   		if (pmDebug & DBG_TRACE_PROFILE)
56   		    fprintf(stderr, "myFetch: calling __pmSendProfile, context: %d\n", ctx);
57   	#endif
58   		if ((n = __pmSendProfile(ctxp->c_pmcd->pc_fd, FROM_ANON, ctx, ctxp->c_instprof)) >= 0)
59   		    ctxp->c_sent = 1;
60   	    }
61   	
62   	    if (n >= 0) {
63   		int		newcnt;
64   		pmID		*newlist;
65   		int		have_dm;
66   	
67   		/* for derived metrics, may need to rewrite the pmidlist */
Event alloc_arg: Calling allocation function "__dmprefetch" on "newlist". [details]
Also see events: [overwrite_var]
68   		have_dm = newcnt = __dmprefetch(ctxp, numpmid, pmidlist, &newlist);
At conditional (1): "newcnt > numpmid": Taking false branch.
69   		if (newcnt > numpmid) {
70   		    /* replace args passed into myFetch */
71   		    numpmid = newcnt;
72   		    pmidlist = newlist;
73   		}
74   		else
Event overwrite_var: Overwriting "newlist" in call "newlist = NULL" leaks the storage that "newlist" points to.
Also see events: [alloc_arg]
75   		    newlist = NULL;
76   	
77   		n = __pmSendFetch(ctxp->c_pmcd->pc_fd, FROM_ANON, ctx, &ctxp->c_origin, numpmid, pmidlist);
78   		if (n >= 0){
79   		    int		changed = 0;
80   		    do {
81   			n = __pmGetPDU(ctxp->c_pmcd->pc_fd, ANY_SIZE, TIMEOUT_DEFAULT, &pb);
82   			/*
83   			 * expect PDU_RESULT or
84   			 *        PDU_ERROR(changed > 0)+PDU_RESULT or
85   			 *        PDU_ERROR(real error < 0 from PMCD) or
86   			 *        0 (end of file)
87   			 *        < 0 (local error or IPC problem)
88   			 *        other (bogus PDU)
89   			 */
90   			if (n == PDU_RESULT) {
91   			    /*
92   			     * Success with a pmResult in a pdubuf.
93   			     *
94   			     * Need to process derived metrics, if any.
95   			     * This is ugly, we need to decode the pdubuf, rebuild
96   			     * the pmResult and encode back into a pdubuf ... the
97   			     * fastpath of not doing all of this needs to be
98   			     * preserved in the common case where derived metrics
99   			     * are not being logged.
100  			     */
101  			    if (have_dm) {
102  				pmResult	*result;
103  				__pmPDU		*npb;
104  				int		sts;
105  				if ((sts = __pmDecodeResult(pb, &result)) < 0) {
106  				    n = sts;
107  				}
108  				else {
109  				    __dmpostfetch(ctxp, &result);
110  				    __pmPinPDUBuf(pb);
111  				    if ((sts = __pmEncodeResult(ctxp->c_pmcd->pc_fd, result, &npb)) < 0)
112  					n = sts;
113  				    else
114  					*pdup = npb;
115  				    __pmUnpinPDUBuf(pb);
116  				}
117  			    }
118  			    else
119  				*pdup = pb;
120  			}
121  			else if (n == PDU_ERROR) {
122  			    __pmDecodeError(pb, &n);
123  			    if (n > 0) {
124  				/* PMCD state change protocol */
125  				changed = n;
126  				n = 0;
127  			    }
128  			    else {
129  				fprintf(stderr, "myFetch: ERROR PDU: %s\n", pmErrStr(n));
130  				disconnect(PM_ERR_IPC);
131  			    }
132  			}
133  			else if (n == 0) {
134  			    fprintf(stderr, "myFetch: End of File: PMCD exited?\n");
135  			    disconnect(PM_ERR_IPC);
136  			}
137  			else if (n < 0) {
138  			    fprintf(stderr, "myFetch: __pmGetPDU: Error: %s\n", pmErrStr(n));
139  			    disconnect(PM_ERR_IPC);
140  			}
141  			else {
142  			    fprintf(stderr, "myFetch: Unexpected %s PDU from PMCD\n", __pmPDUTypeStr(n));
143  			    disconnect(PM_ERR_IPC);
144  			}
145  		    } while (n == 0);
146  	
147  		    if (changed & PMCD_ADD_AGENT) {
148  			/*
149  			 * PMCD_DROP_AGENT does not matter, no values are returned.
150  			 * Trying to restart (PMCD_RESTART_AGENT) is less interesting
151  			 * than when we actually start (PMCD_ADD_AGENT) ... the latter
152  			 * is also set when a successful restart occurs, but more
153  			 * to the point the sequence Install-Remove-Install does
154  			 * not involve a restart ... it is the second Install that
155  			 * generates the second PMCD_ADD_AGENT that we need to be
156  			 * particularly sensitive to, as this may reset counter
157  			 * metrics ...
158  			 */
159  			int	sts;
160  			if ((sts = putmark()) < 0) {
161  			    fprintf(stderr, "putmark: %s\n", pmErrStr(sts));
162  			    exit(1);
163  			}
164  		    }
165  		}
166  		if (newlist != NULL)
167  		    free(newlist);
168  	    }
169  	
170  	    if (n < 0 && ctxp->c_pmcd->pc_fd != -1) {
171  		disconnect(n);
172  	    }
173  	
174  	    return n;
175  	}