1 /*****************************************************************************\
2  *  core_array.c - Handle functions dealing with core_arrays.
3  *****************************************************************************
4  *  Copyright (C) 2019 SchedMD LLC
5  *
6  *  This file is part of Slurm, a resource management program.
7  *  For details, see <https://slurm.schedmd.com/>.
8  *  Please also read the included file: DISCLAIMER.
9  *
10  *  Slurm is free software; you can redistribute it and/or modify it under
11  *  the terms of the GNU General Public License as published by the Free
12  *  Software Foundation; either version 2 of the License, or (at your option)
13  *  any later version.
14  *
15  *  In addition, as a special exception, the copyright holders give permission
16  *  to link the code of portions of this program with the OpenSSL library under
17  *  certain conditions as described in each individual source file, and
18  *  distribute linked combinations including the two. You must obey the GNU
19  *  General Public License in all respects for all of the code used other than
20  *  OpenSSL. If you modify file(s) with this exception, you may extend this
21  *  exception to your version of the file(s), but you are not obligated to do
22  *  so. If you do not wish to do so, delete this exception statement from your
23  *  version.  If you delete this exception statement from all source files in
24  *  the program, then also delete it here.
25  *
26  *  Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
27  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
28  *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
29  *  details.
30  *
31  *  You should have received a copy of the GNU General Public License along
32  *  with Slurm; if not, write to the Free Software Foundation, Inc.,
33  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
34 \*****************************************************************************/
35 
36 #include "cons_common.h"
37 #include "src/common/xstring.h"
38 
39 /*
40  * Build an empty array of bitmaps, one per node
41  * Use free_core_array() to release returned memory
42  */
build_core_array(void)43 extern bitstr_t **build_core_array(void)
44 {
45 	xassert(core_array_size);
46 
47 	return xcalloc(core_array_size, sizeof(bitstr_t *));
48 }
49 
50 /* Clear all elements of an array of bitmaps, one per node */
clear_core_array(bitstr_t ** core_array)51 extern void clear_core_array(bitstr_t **core_array)
52 {
53 	int n;
54 
55 	if (!core_array)
56 		return;
57 	for (n = 0; n < core_array_size; n++) {
58 		if (core_array[n])
59 			bit_clear_all(core_array[n]);
60 	}
61 }
62 
63 /*
64  * Copy an array of bitmaps, one per node
65  * Use free_core_array() to release returned memory
66  */
copy_core_array(bitstr_t ** core_array)67 extern bitstr_t **copy_core_array(bitstr_t **core_array)
68 {
69 	bitstr_t **core_array2 = NULL;
70 	int n;
71 
72 	if (core_array) {
73 		core_array2 = xmalloc(sizeof(bitstr_t *) * core_array_size);
74 		for (n = 0; n < core_array_size; n++) {
75 			if (core_array[n])
76 				core_array2[n] = bit_copy(core_array[n]);
77 		}
78 	}
79 	return core_array2;
80 }
81 
82 /*
83  * Return count of set bits in array of bitmaps, one per node
84  */
count_core_array_set(bitstr_t ** core_array)85 extern int count_core_array_set(bitstr_t **core_array)
86 {
87 	int count = 0, n;
88 
89 	if (!core_array)
90 		return count;
91 	for (n = 0; n < core_array_size; n++) {
92 		if (core_array[n])
93 			count += bit_set_count(core_array[n]);
94 	}
95 	return count;
96 }
97 
98 /*
99  * Set row_bitmap1 to core_array1 & core_array2
100  */
core_array_and(bitstr_t ** core_array1,bitstr_t ** core_array2)101 extern void core_array_and(bitstr_t **core_array1, bitstr_t **core_array2)
102 {
103 	int n, s1, s2;
104 	for (n = 0; n < core_array_size; n++) {
105 		if (core_array1[n] && core_array2[n]) {
106 			s1 = bit_size(core_array1[n]);
107 			s2 = bit_size(core_array2[n]);
108 			if (s1 > s2)
109 				core_array2[n] = bit_realloc(core_array1[n],s1);
110 			else if (s1 < s2)
111 				core_array1[n] = bit_realloc(core_array1[n],s2);
112 			bit_and(core_array1[n], core_array2[n]);
113 		} else if (core_array1[n])
114 			bit_free(core_array1[n]);
115 	}
116 }
117 
118 /*
119  * Set row_bitmap1 to row_bitmap1 & !row_bitmap2
120  * In other words, any bit set in row_bitmap2 is cleared from row_bitmap1
121  */
core_array_and_not(bitstr_t ** core_array1,bitstr_t ** core_array2)122 extern void core_array_and_not(bitstr_t **core_array1, bitstr_t **core_array2)
123 {
124 	int n, s1, s2;
125 	for (n = 0; n < core_array_size; n++) {
126 		if (core_array1[n] && core_array2[n]) {
127 			s1 = bit_size(core_array1[n]);
128 			s2 = bit_size(core_array2[n]);
129 			if (s1 > s2)
130 				core_array2[n] = bit_realloc(core_array1[n],s1);
131 			else if (s1 < s2)
132 				core_array1[n] = bit_realloc(core_array1[n],s2);
133 			bit_and_not(core_array1[n], core_array2[n]);
134 		}
135 	}
136 }
137 
138 /*
139  * Set row_bitmap1 to core_array1 | core_array2
140  */
core_array_or(bitstr_t ** core_array1,bitstr_t ** core_array2)141 extern void core_array_or(bitstr_t **core_array1, bitstr_t **core_array2)
142 {
143 	int n, s1, s2;
144 	for (n = 0; n < core_array_size; n++) {
145 		if (core_array1[n] && core_array2[n]) {
146 			s1 = bit_size(core_array1[n]);
147 			s2 = bit_size(core_array2[n]);
148 			if (s1 > s2)
149 				core_array2[n] = bit_realloc(core_array1[n],s1);
150 			else if (s1 < s2)
151 				core_array1[n] = bit_realloc(core_array1[n],s2);
152 			bit_or(core_array1[n], core_array2[n]);
153 		} else if (core_array2[n])
154 			core_array1[n] = bit_copy(core_array2[n]);
155 	}
156 }
157 
158 /* Free an array of bitmaps, one per node */
free_core_array(bitstr_t *** core_array)159 extern void free_core_array(bitstr_t ***core_array)
160 {
161 	bitstr_t **core_array2 = *core_array;
162 	int n;
163 
164 	if (core_array2) {
165 		for (n = 0; n < core_array_size; n++)
166 			FREE_NULL_BITMAP(core_array2[n]);
167 		xfree(core_array2);
168 		*core_array = NULL;
169 	}
170 }
171 
172 /* Enable detailed logging of cr_dist() node and per-node core bitmaps */
core_array_log(char * loc,bitstr_t * node_map,bitstr_t ** core_map)173 extern void core_array_log(char *loc, bitstr_t *node_map, bitstr_t **core_map)
174 {
175 	char tmp[100];
176 
177 	if (!(select_debug_flags & DEBUG_FLAG_SELECT_TYPE))
178 		return;
179 
180 	info("%s", loc);
181 
182 	if (node_map) {
183 		char *node_list = bitmap2node_name(node_map);
184 		info("node_list:%s", node_list);
185 		xfree(node_list);
186 	}
187 
188 	if (core_map) {
189 		char *core_list = NULL;
190 		char *sep = "";
191 
192 		for (int i = 0; i < core_array_size; i++) {
193 			if (!core_map[i] || (bit_ffs(core_map[i]) == -1))
194 				continue;
195 			bit_fmt(tmp, sizeof(tmp), core_map[i]);
196 			xstrfmtcat(core_list, "%snode[%d]:%s", sep, i, tmp);
197 			sep = ",";
198 		}
199 		info("core_list:%s", core_list);
200 		xfree(core_list);
201 	}
202 }
203 
204 /* Translate per-node core bitmap array to system-wide core bitmap */
core_array_to_bitmap(bitstr_t ** core_array)205 extern bitstr_t *core_array_to_bitmap(bitstr_t **core_array)
206 {
207 	bitstr_t *core_bitmap = NULL;
208 	int i;
209 	int c, core_offset;
210 #if _DEBUG
211 	char tmp[128];
212 #endif
213 
214 	if (!core_array)
215 		return core_bitmap;
216 
217 #if _DEBUG
218 	for (i = 0; i < core_array_size; i++) {
219 		if (!core_array[i])
220 			continue;
221 		bit_fmt(tmp, sizeof(tmp), core_array[i]);
222 		error("%s: %s: OUT core bitmap[%d] %s", plugin_type, __func__,
223 		      i, tmp);
224 	}
225 #endif
226 
227 	if (!is_cons_tres) {
228 		core_bitmap = *core_array;
229 		*core_array = NULL;
230 		return core_bitmap;
231 	}
232 
233 	core_bitmap =
234 		bit_alloc(select_node_record[select_node_cnt-1].cume_cores);
235 	for (i = 0; i < core_array_size; i++) {
236 		if (!core_array[i])
237 			continue;
238 		core_offset = select_node_record[i].cume_cores -
239 			      select_node_record[i].tot_cores;
240 		for (c = 0; c < select_node_record[i].tot_cores; c++) {
241 			if (bit_test(core_array[i], c))
242 				bit_set(core_bitmap, core_offset + c);
243 		}
244 	}
245 
246 #if _DEBUG
247 	bit_fmt(tmp, sizeof(tmp), core_bitmap);
248 	error("%s: %s: IN core bitmap %s", plugin_type, __func__, tmp);
249 #endif
250 
251 	return core_bitmap;
252 }
253 
254 /* Translate system-wide core bitmap to per-node core bitmap array */
core_bitmap_to_array(bitstr_t * core_bitmap)255 extern bitstr_t **core_bitmap_to_array(bitstr_t *core_bitmap)
256 {
257 	bitstr_t **core_array = NULL;
258 	int i, i_first, i_last, j, c;
259 	int node_inx = 0, core_offset;
260 	char tmp[128];
261 
262 	if (!core_bitmap)
263 		return core_array;
264 
265 #if _DEBUG
266 	bit_fmt(tmp, sizeof(tmp), core_bitmap);
267 	error("%s: %s: IN core bitmap %s", plugin_type, __func__, tmp);
268 #endif
269 
270 	i_first = bit_ffs(core_bitmap);
271 	if (i_first == -1)
272 		return core_array;
273 
274 	core_array = build_core_array();
275 
276 	if (!is_cons_tres) {
277 		*core_array = bit_copy(core_bitmap);
278 		return core_array;
279 	}
280 
281 	i_last = bit_fls(core_bitmap);
282 
283 	for (i = i_first; i <= i_last; i++) {
284 		if (!bit_test(core_bitmap, i))
285 			continue;
286 		for (j = node_inx; j < select_node_cnt; j++) {
287 			if (i < select_node_record[j].cume_cores) {
288 				node_inx = j;
289 				i = select_node_record[j].cume_cores - 1;
290 				break;
291 			}
292 		}
293 		if (j >= select_node_cnt) {
294 			bit_fmt(tmp, sizeof(tmp), core_bitmap);
295 			error("%s: %s: error translating core bitmap %s",
296 			      plugin_type, __func__, tmp);
297 			break;
298 		}
299 		/* Copy all core bitmaps for this node here */
300 		core_array[node_inx] =
301 			bit_alloc(select_node_record[node_inx].tot_cores);
302 		core_offset = select_node_record[node_inx].cume_cores -
303 			      select_node_record[node_inx].tot_cores;
304 		for (c = 0; c < select_node_record[node_inx].tot_cores; c++) {
305 			if (bit_test(core_bitmap, core_offset + c))
306 				bit_set(core_array[node_inx], c);
307 		}
308 		node_inx++;
309 	}
310 
311 #if _DEBUG
312 	for (i = 0; i < core_array_size; i++) {
313 		if (!core_array[i])
314 			continue;
315 		bit_fmt(tmp, sizeof(tmp), core_array[i]);
316 		error("%s: %s: OUT core bitmap[%d] %s", plugin_type, __func__,
317 		      i, tmp);
318 	}
319 #endif
320 
321 	return core_array;
322 }
323