1    	/*
2    	 * Copyright (c) 1995-2002 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   	static int *
19   	_subtract(int *list, int *list_len, int *arg, int arg_len)
20   	{
21   	    int		*new;
22   	    int		len = *list_len;
23   	    int		new_len = 0;
24   	    int		i, j;
25   	
26   	    if (list == NULL)
27   		/* noop */
28   		return NULL;
29   	
30   	    new = (int *)malloc(len * sizeof(int));
31   	    if (new == NULL)
32   		return NULL;
33   	
34   	    for (i=0; i < len; i++) {
35   		for (j=0; j < arg_len; j++)
36   		    if (list[i] == arg[j])
37   			break;
38   		if (j == arg_len)
39   		    /* this instance survived */
40   		    new[new_len++] = list[i];
41   	    }
42   	    free(list);
43   	    *list_len = new_len;
44   	    return new;
45   	}
46   	
47   	static int *
48   	_union(int *list, int *list_len, int *arg, int arg_len)
49   	{
50   	    int		*new;
51   	    int		len = *list_len;
52   	    int		new_len = *list_len;
53   	    int		i, j;
54   	
55   	    if (list == NULL) {
56   		list = (int *)malloc(arg_len * sizeof(int));
57   		memcpy((void *)list, (void *)arg, arg_len * sizeof(int));
58   		*list_len = arg_len;
59   		return list;
60   	    }
61   	
62   	    new = (int *)realloc((void *)list, (len + arg_len) * sizeof(int));
63   	    if (new == NULL)
64   		return NULL;
65   	
66   	    for (i=0; i < arg_len; i++) {
67   		for (j=0; j < new_len; j++) {
68   		    if (arg[i] == new[j])
69   			break;
70   		}
71   		if (j == new_len)
72   		    /* instance is not already in the list */
73   		    new[new_len++] = arg[i];
74   	    }
75   	    *list_len = new_len;
76   	    return new;
77   	}
78   	
79   	static void
80   	_setGlobalState(__pmContext *ctxp, int state)
81   	{
82   	    __pmInDomProfile	*p, *p_end;
83   	
84   	    /* free everything and set the global state */
85   	    if (ctxp->c_instprof->profile) {
86   		for (p=ctxp->c_instprof->profile, p_end = p + ctxp->c_instprof->profile_len;
87   		    p < p_end; p++) {
88   		    if (p->instances)
89   			free(p->instances);
90   		    p->instances_len = 0;
91   		}
92   	
93   		free(ctxp->c_instprof->profile);
94   		ctxp->c_instprof->profile = NULL;
95   		ctxp->c_instprof->profile_len = 0;
96   	    }
97   	
98   	    ctxp->c_instprof->state = state;
99   	    ctxp->c_sent = 0;
100  	}
101  	
102  	static __pmInDomProfile *
103  	_newprof(pmInDom indom, __pmContext *ctxp)
104  	{
105  	    __pmInDomProfile	*p;
106  	
107  	    if (ctxp->c_instprof->profile == NULL) {
108  		/* create a new profile for this inDom in the default state */
109  		p = ctxp->c_instprof->profile = (__pmInDomProfile *)malloc(
110  		    sizeof(__pmInDomProfile));
111  		if (p == NULL)
112  		    /* fail, no changes */
113  		    return NULL;
114  		ctxp->c_instprof->profile_len = 1;
115  	    }
116  	    else {
117  		/* append a new profile to the end of the list */
118  		ctxp->c_instprof->profile_len++;
119  		p = (__pmInDomProfile *)realloc((void *)ctxp->c_instprof->profile, 
120  		    ctxp->c_instprof->profile_len * sizeof(__pmInDomProfile));
121  		if (p == NULL)
122  		    /* fail, no changes */
123  		    return NULL;
124  		ctxp->c_instprof->profile = p;
125  		p = ctxp->c_instprof->profile + ctxp->c_instprof->profile_len - 1;
126  	    }
127  	
128  	    /* initialise a new profile entry : default = include all instances */
129  	    p->indom = indom;
130  	    p->instances = NULL;
131  	    p->instances_len = 0;
132  	    p->state = PM_PROFILE_INCLUDE;
133  	    return p;
134  	}
135  	
136  	__pmInDomProfile *
137  	__pmFindProfile(pmInDom indom, const __pmProfile *prof)
138  	{
139  	    __pmInDomProfile	*p, *p_end;
140  	
141  	    if (prof != NULL && prof->profile_len > 0)
142  		/* search for the profile entry for this instance domain */
143  		for (p=prof->profile, p_end=p+prof->profile_len; p < p_end; p++) {
144  		    if (p->indom == indom)
145  			/* found : an entry for this instance domain already exists */
146  			return p;
147  		}
148  	
149  	    /* not found */
150  	    return NULL;
151  	}
152  	
153  	int
154  	__pmInProfile(pmInDom indom, const __pmProfile *prof, int inst)
155  	{
156  	    __pmInDomProfile	*p;
157  	    int			*in, *in_end;
158  	
159  	    if (prof == NULL)
160  		/* default if no profile for any instance domains */
161  		return 1;
162  	
163  	    if ((p = __pmFindProfile(indom, prof)) == NULL)
164  		/* no profile for this indom => use global default */
165  		return (prof->state == PM_PROFILE_INCLUDE) ? 1 : 0;
166  	
167  	    for (in=p->instances, in_end=in+p->instances_len; in < in_end; in++)
168  		if (*in == inst)
169  		    /* present in the list => inverse of default for this indom */
170  		    return (p->state == PM_PROFILE_INCLUDE) ? 0 : 1;
171  	
172  	    /* not in the list => use default for this indom */
173  	    return (p->state == PM_PROFILE_INCLUDE) ? 1 : 0;
174  	}
175  	
176  	void
177  	__pmFreeProfile(__pmProfile *prof)
178  	{
179  	    __pmInDomProfile	*p, *p_end;
180  	
181  	    if (prof != NULL) {
182  		if (prof->profile != NULL) {
183  		    for (p=prof->profile, p_end = p+prof->profile_len; p < p_end; p++) {
184  			if (p->instances)
185  			    free(p->instances);
186  		    }
187  		    if (prof->profile_len)
188  			free(prof->profile);
189  		}
190  		free(prof);
191  	    }
192  	}
193  	
194  	int
195  	pmAddProfile(pmInDom indom, int instlist_len, int instlist[])
196  	{
197  	    int			sts;
198  	    __pmContext		*ctxp;
199  	    __pmInDomProfile	*prof;
200  	
201  	    if (indom == PM_INDOM_NULL && instlist != NULL)
202  		/* semantic disconnect! */
203  		return PM_ERR_PROFILESPEC;
204  	
205  	    if ((sts = pmWhichContext()) < 0)
206  		return sts;
207  	
208  	    ctxp = __pmHandleToPtr(sts);
209  	    if (indom == PM_INDOM_NULL && (instlist == NULL || instlist_len == 0)) {
210  		_setGlobalState(ctxp, PM_PROFILE_INCLUDE);
211  		goto SUCCESS;
212  	    }
213  	
214  	    if ((prof = __pmFindProfile(indom, ctxp->c_instprof)) == NULL) {
215  		if ((prof = _newprof(indom, ctxp)) == NULL) {
216  		    /* fail */
217  		    return -oserror();
218  		}
219  		else {
220  		    /* starting state: exclude all except the supplied list */
221  		    prof->state = PM_PROFILE_EXCLUDE;
222  		}
223  	    }
224  	
225  	    /* include all instances? */
226  	    if (instlist_len == 0 || instlist == NULL) {
227  		/* include all instances in this domain */
228  		if (prof->instances)
229  		    free(prof->instances);
230  		prof->instances = NULL;
231  		prof->instances_len = 0;
232  		prof->state = PM_PROFILE_INCLUDE;
233  		goto SUCCESS;
234  	    }
235  	
236  	    switch (prof->state) {
237  	    case PM_PROFILE_INCLUDE:
238  		/*
239  		 * prof->instances is an exclusion list (all else included)
240  		 * => traverse and remove the specified instances (if present)
241  		 */
242  		prof->instances = _subtract(
243  		    prof->instances, &prof->instances_len,
244  		    instlist, instlist_len);
245  		break;
246  	
247  	    case PM_PROFILE_EXCLUDE:
248  		/*
249  		 * prof->instances is an inclusion list (all else excluded)
250  		 * => traverse and add the specified instances (if not already present)
251  		 */
252  		prof->instances = _union(
253  		    prof->instances, &prof->instances_len,
254  		    instlist, instlist_len);
255  		break;
256  	    }
257  	
258  	SUCCESS:
259  	    ctxp->c_sent = 0;
260  	#ifdef PCP_DEBUG
261  	    if (pmDebug & DBG_TRACE_PROFILE) {
262  		fprintf(stderr, "pmAddProfile() indom: %s\n", pmInDomStr(indom));
263  		__pmDumpProfile(stderr, indom, ctxp->c_instprof);
264  	    }
265  	#endif
266  	    return 0;
267  	}
268  	
269  	int
270  	pmDelProfile(pmInDom indom, int instlist_len, int instlist[])
271  	{
272  	    int			sts;
273  	    __pmContext		*ctxp;
274  	    __pmInDomProfile	*prof;
275  	
Event const: After this line, the value of "instlist" is equal to 0.
Event new_values: Noticing condition "instlist != NULL".
Also see events: [dead_error_condition][dead_error_line]
276  	    if (indom == PM_INDOM_NULL && instlist != NULL)
277  		/* semantic disconnect! */
278  		return PM_ERR_PROFILESPEC;
279  	
280  	    if ((sts = pmWhichContext()) < 0)
281  		return sts;
282  	
283  	    ctxp = __pmHandleToPtr(sts);
Event dead_error_condition: On this path, the condition "instlist == NULL" cannot be false.
Event dead_error_line: Execution cannot reach this expression "instlist_len == 0" inside statement "if (indom == 4294967295U &&...".
Also see events: [const][new_values]
284  	    if (indom == PM_INDOM_NULL && (instlist == NULL || instlist_len == 0)) {
285  		_setGlobalState(ctxp, PM_PROFILE_EXCLUDE);
286  		goto SUCCESS;
287  	    }
288  	
289  	    if ((prof = __pmFindProfile(indom, ctxp->c_instprof)) == NULL) {
290  		if ((prof = _newprof(indom, ctxp)) == NULL) {
291  		    /* fail */
292  		    return -oserror();
293  		}
294  		else {
295  		    /* starting state: include all except the supplied list */
296  		    prof->state = PM_PROFILE_EXCLUDE;
297  		}
298  	    }
299  	
300  	    /* include all instances? */
301  	    if (instlist_len == 0 || instlist == NULL) {
302  		/* include all instances in this domain */
303  		if (prof->instances)
304  		    free(prof->instances);
305  		prof->instances = NULL;
306  		prof->instances_len = 0;
307  		prof->state = PM_PROFILE_EXCLUDE;
308  		goto SUCCESS;
309  	    }
310  	
311  	    switch (prof->state) {
312  	    case PM_PROFILE_INCLUDE:
313  		/*
314  		 * prof->instances is an exclusion list (all else included)
315  		 * => traverse and add the specified instances (if not already present)
316  		 */
317  		prof->instances = _union(
318  		    prof->instances, &prof->instances_len,
319  		    instlist, instlist_len);
320  		break;
321  	
322  	    case PM_PROFILE_EXCLUDE:
323  		/*
324  		 * prof->instances is an inclusion list (all else excluded)
325  		 * => traverse and remove the specified instances (if present)
326  		 */
327  		prof->instances = _subtract(
328  		    prof->instances, &prof->instances_len,
329  		    instlist, instlist_len);
330  		break;
331  	    }
332  	
333  	SUCCESS:
334  	    ctxp->c_sent = 0;
335  	#ifdef PCP_DEBUG
336  	    if (pmDebug & DBG_TRACE_PROFILE) {
337  		fprintf(stderr, "pmDelProfile() indom: %s\n", pmInDomStr(indom));
338  		__pmDumpProfile(stderr, indom, ctxp->c_instprof);
339  	    }
340  	#endif
341  	    return 0;
342  	}
343  	
344  	void
345  	__pmDumpProfile(FILE *f, int indom, const __pmProfile *pp)
346  	{
347  	    int			j;
348  	    int			k;
349  	    __pmInDomProfile	*prof;
350  	
351  	    fprintf(f, "Dump Instance Profile state=%s, %d profiles",
352  		pp->state == PM_PROFILE_INCLUDE ? "INCLUDE" : "EXCLUDE",
353  		pp->profile_len);
354  	    if (indom != PM_INDOM_NULL)
355  		fprintf(f, ", dump restricted to indom=%d [%s]", 
356  		        indom, pmInDomStr(indom));
357  	    fprintf(f, "\n");
358  	
359  	    for (prof=pp->profile, j=0; j < pp->profile_len; j++, prof++) {
360  		if (indom != PM_INDOM_NULL && indom != prof->indom)
361  		    continue;
362  		fprintf(f, "\tProfile [%d] indom=%d [%s] state=%s %d instances\n",
363  		    j, prof->indom, pmInDomStr(prof->indom),
364  		    (prof->state == PM_PROFILE_INCLUDE) ? "INCLUDE" : "EXCLUDE",
365  		    prof->instances_len);
366  	
367  		if (prof->instances_len) {
368  		    fprintf(f, "\t\tInstances:");
369  		    for (k=0; k < prof->instances_len; k++)
370  			fprintf(f, " [%d]", prof->instances[k]);
371  		    fprintf(f, "\n");
372  		}
373  	    }
374  	}