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;
70 return -oserror();
71 }
72 }
73
74 ans->numpmid = numpmid;
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)
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 }