1 /*
2 * Copyright (c) 1995-2006,2008 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 "pmapi.h"
16 #include "impl.h"
17
18 extern int __pmFetchLocal(int, pmID *, pmResult **);
19
20 static int
21 request_fetch (int ctxid, __pmContext *ctxp, int numpmid, pmID pmidlist[])
22 {
23 int n;
24
25 #ifdef ASYNC_API
26 if (ctxp->c_pmcd->pc_curpdu != 0) {
27 return (PM_ERR_CTXBUSY);
28 }
29 #endif /*ASYNC_API*/
30
31 if (ctxp->c_sent == 0) {
32 /*
33 * current profile is _not_ already cached at other end of
34 * IPC, so send get current profile
35 */
36 #ifdef PCP_DEBUG
37 if (pmDebug & DBG_TRACE_PROFILE) {
38 fprintf(stderr, "pmFetch: calling __pmSendProfile, context: %d\n",
39 ctxid);
40 __pmDumpProfile(stderr, PM_INDOM_NULL, ctxp->c_instprof);
41 }
42 #endif
43 if ((n = __pmSendProfile(ctxp->c_pmcd->pc_fd, __pmPtrToHandle(ctxp),
44 ctxid, ctxp->c_instprof)) < 0)
45 return (__pmMapErrno(n));
46 else
47 ctxp->c_sent = 1;
48 }
49
50 n = __pmSendFetch(ctxp->c_pmcd->pc_fd, __pmPtrToHandle(ctxp), ctxid,
51 &ctxp->c_origin, numpmid, pmidlist);
52 if (n < 0) {
53 n = __pmMapErrno(n);
54 }
55 return (n);
56 }
57
58 #ifdef ASYNC_API
59 int
60 pmRequestFetch(int ctxid, int numpmid, pmID pmidlist[])
61 {
62 int n = 0;
63 __pmContext *ctxp;
64
65 if ((n = __pmGetHostContextByID(ctxid, &ctxp)) >= 0) {
66 if ((n = request_fetch (ctxid, ctxp, numpmid, pmidlist)) >= 0) {
67 ctxp->c_pmcd->pc_curpdu = PDU_FETCH;
68 ctxp->c_pmcd->pc_tout_sec = TIMEOUT_DEFAULT;
69 }
70 }
71 return (n);
72 }
73 #endif /*ASYNC_API*/
74
75 static int
76 receive_fetch (__pmContext *ctxp, pmResult **result)
77 {
78 int n;
79 __pmPDU *pb;
80
81 n = __pmGetPDU(ctxp->c_pmcd->pc_fd, ANY_SIZE,
82 ctxp->c_pmcd->pc_tout_sec, &pb);
83 if (n == PDU_RESULT) {
84 n = __pmDecodeResult(pb, result);
85 }
86 else if (n == PDU_ERROR) {
87 __pmDecodeError(pb, &n);
88 }
89 else if (n != PM_ERR_TIMEOUT)
90 n = PM_ERR_IPC;
91
92 return (n);
93 }
94
95 #ifdef ASYNC_API
96 int
97 pmReceiveFetch (int ctxid, pmResult **result)
98 {
99 int n;
100 __pmContext *ctxp;
101
102 if ((n = __pmGetBusyHostContextByID (ctxid, &ctxp, PDU_FETCH)) >= 0) {
103 if ((n = receive_fetch (ctxp, result)) <= 0) {
104 /* pmcd may return state change in error PDU before
105 * returning results for fetch - if we get one of those,
106 * keep the state in the context for the second call to
107 * receive_fetch */
108 ctxp->c_pmcd->pc_curpdu = 0;
109 ctxp->c_pmcd->pc_tout_sec = 0;
110 }
111 }
112 return (n);
113 }
114 #endif /*ASYNC_API*/
115
116 int
117 pmFetch(int numpmid, pmID pmidlist[], pmResult **result)
118 {
119 int n;
120
121 if (numpmid < 1)
122 return PM_ERR_TOOSMALL;
123
124 if ((n = pmWhichContext()) >= 0) {
125 __pmContext *ctxp = __pmHandleToPtr(n);
126 int newcnt;
127 pmID *newlist;
128 int have_dm;
129
130 /* for derived metrics, may need to rewrite the pmidlist */
|
Event alloc_arg: |
Calling allocation function "__dmprefetch" on "newlist". [details] |
| Also see events: |
[overwrite_var] |
131 have_dm = newcnt = __dmprefetch(ctxp, numpmid, pmidlist, &newlist);
|
At conditional (1): "newcnt > numpmid": Taking false branch.
|
132 if (newcnt > numpmid) {
133 /* replace args passed into pmFetch */
134 numpmid = newcnt;
135 pmidlist = newlist;
136 }
137 else
|
Event overwrite_var: |
Overwriting "newlist" in call "newlist = NULL" leaks the storage that "newlist" points to. |
| Also see events: |
[alloc_arg] |
138 newlist = NULL;
139
140 if (ctxp->c_type == PM_CONTEXT_HOST) {
141 if ((n = request_fetch (n, ctxp, numpmid, pmidlist)) >= 0) {
142 int changed = 0;
143 do {
144 if ((n = receive_fetch (ctxp, result)) > 0) {
145 /* PMCD state change protocol */
146 changed = n;
147 }
148 } while (n > 0);
149
150 if (n == 0)
151 n |= changed;
152 }
153 }
154 else if (ctxp->c_type == PM_CONTEXT_LOCAL) {
155 n = __pmFetchLocal(numpmid, pmidlist, result);
156 }
157 else {
158 /* assume PM_CONTEXT_ARCHIVE */
159 n = __pmLogFetch(ctxp, numpmid, pmidlist, result);
160 if (n >= 0 && (ctxp->c_mode & __PM_MODE_MASK) != PM_MODE_INTERP) {
161 ctxp->c_origin.tv_sec = (__int32_t)(*result)->timestamp.tv_sec;
162 ctxp->c_origin.tv_usec = (__int32_t)(*result)->timestamp.tv_usec;
163 }
164 }
165
166 /* process derived metrics, if any */
167 if (have_dm) {
168 if (n >= 0)
169 __dmpostfetch(ctxp, result);
170 if (newlist != NULL)
171 free(newlist);
172 }
173 }
174
175 #ifdef PCP_DEBUG
176 if (pmDebug & DBG_TRACE_FETCH) {
177 fprintf(stderr, "pmFetch returns ...\n");
178 if (n > 0) {
179 fprintf(stderr, "PMCD state changes: agent(s)");
180 if (n & PMCD_ADD_AGENT) fprintf(stderr, " added");
181 if (n & PMCD_RESTART_AGENT) fprintf(stderr, " restarted");
182 if (n & PMCD_DROP_AGENT) fprintf(stderr, " dropped");
183 fputc('\n', stderr);
184 }
185 if (n >= 0)
186 __pmDumpResult(stderr, *result);
187 else
188 fprintf(stderr, "Error: %s\n", pmErrStr(n));
189 }
190 #endif
191
192 return n;
193 }
194
195 int
196 pmFetchArchive(pmResult **result)
197 {
198 int n;
199 __pmContext *ctxp;
200 int ctxp_mode;
201
202 if ((n = pmWhichContext()) >= 0) {
203 ctxp = __pmHandleToPtr(n);
204 ctxp_mode = (ctxp->c_mode & __PM_MODE_MASK);
205 if (ctxp->c_type != PM_CONTEXT_ARCHIVE)
206 n = PM_ERR_NOTARCHIVE;
207 else if (ctxp_mode == PM_MODE_INTERP)
208 /* makes no sense! */
209 n = PM_ERR_MODE;
210 else {
211 /* assume PM_CONTEXT_ARCHIVE and BACK or FORW */
212 n = __pmLogFetch(ctxp, 0, NULL, result);
213 if (n >= 0) {
214 ctxp->c_origin.tv_sec = (__int32_t)(*result)->timestamp.tv_sec;
215 ctxp->c_origin.tv_usec = (__int32_t)(*result)->timestamp.tv_usec;
216 }
217 }
218 }
219
220 return n;
221 }
222
223 int
224 pmSetMode(int mode, const struct timeval *when, int delta)
225 {
226 int n;
227 __pmContext *ctxp;
228 int l_mode = (mode & __PM_MODE_MASK);
229
230 if ((n = pmWhichContext()) >= 0) {
231 ctxp = __pmHandleToPtr(n);
232 if (ctxp->c_type == PM_CONTEXT_HOST) {
233 if (l_mode != PM_MODE_LIVE)
234 return PM_ERR_MODE;
235
236 ctxp->c_origin.tv_sec = ctxp->c_origin.tv_usec = 0;
237 ctxp->c_mode = mode;
238 ctxp->c_delta = delta;
239 return 0;
240 }
241 else if (ctxp->c_type == PM_CONTEXT_LOCAL) {
242 return PM_ERR_MODE;
243 }
244 else {
245 /* assume PM_CONTEXT_ARCHIVE */
246 if (l_mode == PM_MODE_INTERP ||
247 l_mode == PM_MODE_FORW || l_mode == PM_MODE_BACK) {
248 if (when != NULL) {
249 /*
250 * special case of NULL for timestamp
251 * => do not update notion of "current" time
252 */
253 ctxp->c_origin.tv_sec = (__int32_t)when->tv_sec;
254 ctxp->c_origin.tv_usec = (__int32_t)when->tv_usec;
255 }
256 ctxp->c_mode = mode;
257 ctxp->c_delta = delta;
258 __pmLogSetTime(ctxp);
259 __pmLogResetInterp(ctxp);
260 return 0;
261 }
262 else
263 return PM_ERR_MODE;
264 }
265 }
266 else
267 return n;
268 }