blob: e02d2cf6f07d561c9abeccb695df925b9ae2e5d0 [file] [log] [blame]
/*****************************************************************************\
* core_array.c - Handle functions dealing with core_arrays.
*****************************************************************************
* Copyright (C) SchedMD LLC.
*
* This file is part of Slurm, a resource management program.
* For details, see <https://slurm.schedmd.com/>.
* Please also read the included file: DISCLAIMER.
*
* Slurm is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* In addition, as a special exception, the copyright holders give permission
* to link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two. You must obey the GNU
* General Public License in all respects for all of the code used other than
* OpenSSL. If you modify file(s) with this exception, you may extend this
* exception to your version of the file(s), but you are not obligated to do
* so. If you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files in
* the program, then also delete it here.
*
* Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with Slurm; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\*****************************************************************************/
#include "src/common/core_array.h"
#include "src/common/node_conf.h"
#include "src/common/xmalloc.h"
#include "src/common/xstring.h"
/*
* Build an empty array of bitmaps, one per node
* Use free_core_array() to release returned memory
*/
extern bitstr_t **build_core_array(void)
{
xassert(node_record_count);
return xcalloc(node_record_count, sizeof(bitstr_t *));
}
/* Clear all elements of an array of bitmaps, one per node */
extern void clear_core_array(bitstr_t **core_array)
{
int n;
if (!core_array)
return;
for (n = 0; n < node_record_count; n++) {
if (core_array[n])
bit_clear_all(core_array[n]);
}
}
/*
* Copy an array of bitmaps, one per node
* Use free_core_array() to release returned memory
*/
extern bitstr_t **copy_core_array(bitstr_t **core_array)
{
bitstr_t **core_array2 = NULL;
int n;
if (core_array) {
core_array2 = xmalloc(sizeof(bitstr_t *) * node_record_count);
for (n = 0; n < node_record_count; n++) {
if (core_array[n])
core_array2[n] = bit_copy(core_array[n]);
}
}
return core_array2;
}
/*
* Return count of set bits in array of bitmaps, one per node
*/
extern int count_core_array_set(bitstr_t **core_array)
{
int count = 0, n;
if (!core_array)
return count;
for (n = 0; n < node_record_count; n++) {
if (core_array[n])
count += bit_set_count(core_array[n]);
}
return count;
}
/*
* Set core_array to ~core_array
*/
extern void core_array_not(bitstr_t **core_array)
{
if (!core_array)
return;
for (int n = 0; n < node_record_count; n++) {
if (core_array[n])
bit_not(core_array[n]);
}
return;
}
/*
* Set row_bitmap1 to core_array1 & core_array2
*/
extern void core_array_and(bitstr_t **core_array1, bitstr_t **core_array2)
{
int n, s1, s2;
for (n = 0; n < node_record_count; n++) {
if (core_array1[n] && core_array2[n]) {
s1 = bit_size(core_array1[n]);
s2 = bit_size(core_array2[n]);
if (s1 > s2)
bit_realloc(core_array2[n], s1);
else if (s1 < s2)
bit_realloc(core_array1[n], s2);
bit_and(core_array1[n], core_array2[n]);
} else
FREE_NULL_BITMAP(core_array1[n]);
}
}
/*
* Set row_bitmap1 to row_bitmap1 & !row_bitmap2
* In other words, any bit set in row_bitmap2 is cleared from row_bitmap1
*/
extern void core_array_and_not(bitstr_t **core_array1, bitstr_t **core_array2)
{
int n, s1, s2;
for (n = 0; n < node_record_count; n++) {
if (core_array1[n] && core_array2[n]) {
s1 = bit_size(core_array1[n]);
s2 = bit_size(core_array2[n]);
if (s1 > s2)
bit_realloc(core_array2[n], s1);
else if (s1 < s2)
bit_realloc(core_array1[n], s2);
bit_and_not(core_array1[n], core_array2[n]);
}
}
}
/*
* Set row_bitmap1 to core_array1 | core_array2
*/
extern void core_array_or(bitstr_t **core_array1, bitstr_t **core_array2)
{
int n, s1, s2;
for (n = 0; n < node_record_count; n++) {
if (core_array1[n] && core_array2[n]) {
s1 = bit_size(core_array1[n]);
s2 = bit_size(core_array2[n]);
if (s1 > s2)
bit_realloc(core_array2[n], s1);
else if (s1 < s2)
bit_realloc(core_array1[n], s2);
bit_or(core_array1[n], core_array2[n]);
} else if (core_array2[n])
core_array1[n] = bit_copy(core_array2[n]);
}
}
/* Free an array of bitmaps, one per node */
extern void free_core_array(bitstr_t ***core_array)
{
bitstr_t **core_array2 = *core_array;
int n;
if (core_array2) {
for (n = 0; n < node_record_count; n++)
FREE_NULL_BITMAP(core_array2[n]);
xfree(core_array2);
*core_array = NULL;
}
}
/* Enable detailed logging of cr_dist() node and per-node core bitmaps */
extern void core_array_log(char *loc, bitstr_t *node_map, bitstr_t **core_map)
{
char tmp[100];
if (!(slurm_conf.debug_flags & DEBUG_FLAG_SELECT_TYPE))
return;
verbose("%s", loc);
if (node_map) {
char *node_list = bitmap2node_name(node_map);
verbose("node_list:%s", node_list);
xfree(node_list);
}
if (core_map) {
char *core_list = NULL;
char *sep = "";
for (int i = 0; i < node_record_count; i++) {
if (!core_map[i] || (bit_ffs(core_map[i]) == -1))
continue;
bit_fmt(tmp, sizeof(tmp), core_map[i]);
xstrfmtcat(core_list, "%snode[%d]:%s", sep, i, tmp);
sep = ",";
}
verbose("core_list:%s", core_list);
xfree(core_list);
}
}
/* Translate per-node core bitmap array to system-wide core bitmap */
extern bitstr_t *core_array_to_bitmap(bitstr_t **core_array)
{
bitstr_t *core_bitmap = NULL;
int i;
int c, core_offset;
#if _DEBUG
char tmp[128];
#endif
if (!core_array)
return core_bitmap;
#if _DEBUG
for (i = 0; i < node_record_count; i++) {
if (!core_array[i])
continue;
bit_fmt(tmp, sizeof(tmp), core_array[i]);
error("OUT core bitmap[%d] %s",
i, tmp);
}
#endif
core_bitmap = bit_alloc(cr_get_coremap_offset(node_record_count));
for (i = 0; i < node_record_count; i++) {
if (!core_array[i])
continue;
core_offset = cr_get_coremap_offset(i);
for (c = 0; c < node_record_table_ptr[i]->tot_cores; c++) {
if (bit_test(core_array[i], c))
bit_set(core_bitmap, core_offset + c);
}
}
#if _DEBUG
bit_fmt(tmp, sizeof(tmp), core_bitmap);
error("IN core bitmap %s", tmp);
#endif
return core_bitmap;
}
/* Translate system-wide core bitmap to per-node core bitmap array */
extern bitstr_t **core_bitmap_to_array(bitstr_t *core_bitmap)
{
bitstr_t **core_array = NULL;
int i, i_first, i_last, j, c;
int node_inx = 0, core_offset;
char tmp[128];
if (!core_bitmap)
return core_array;
#if _DEBUG
bit_fmt(tmp, sizeof(tmp), core_bitmap);
error("IN core bitmap %s", tmp);
#endif
i_first = bit_ffs(core_bitmap);
if (i_first == -1)
return core_array;
core_array = build_core_array();
i_last = bit_fls(core_bitmap);
for (i = i_first; i <= i_last; i++) {
if (!bit_test(core_bitmap, i))
continue;
/*
* next_node will jump over any hole in the node list created by
* dynamic node removal
*/
for (j = node_inx; next_node(&j); j++) {
if (i < cr_get_coremap_offset(j+1)) {
node_inx = j;
i = cr_get_coremap_offset(j+1) - 1;
break;
}
}
if (j >= node_record_count) {
bit_fmt(tmp, sizeof(tmp), core_bitmap);
error("error translating core bitmap %s",
tmp);
break;
}
/*
* If node_inx is pointing to a hole this means that
* node_inx == last_node_index + 1, and the rest of
* the list up to node_record_count (MaxNodeCount) is empty.
*
* next_node() would have returned NULL when
* node_inx > last_node_index and we will end up here.
*/
if (!node_record_table_ptr[node_inx])
break;
/* Copy all core bitmaps for this node here */
core_array[node_inx] =
bit_alloc(node_record_table_ptr[node_inx]->tot_cores);
core_offset = cr_get_coremap_offset(node_inx);
for (c = 0; c < node_record_table_ptr[node_inx]->tot_cores;
c++) {
if (bit_test(core_bitmap, core_offset + c))
bit_set(core_array[node_inx], c);
}
node_inx++;
}
#if _DEBUG
for (i = 0; i < node_record_count; i++) {
if (!core_array[i])
continue;
bit_fmt(tmp, sizeof(tmp), core_array[i]);
error("OUT core bitmap[%d] %s",
i, tmp);
}
#endif
return core_array;
}