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