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 }