blob: 6b862249df84073c59bdea490d9261c19b3646a0 [file] [log] [blame]
/*****************************************************************************\
* grid_functions.c - Functions related to curses display of smap.
*****************************************************************************
* Copyright (C) 2002-2007 The Regents of the University of California.
* Copyright (C) 2008-2011 Lawrence Livermore National Security.
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
* Written by Danny Auble <da@llnl.gov>
*
* CODE-OCEC-09-009. All rights reserved.
*
* This file is part of SLURM, a resource management program.
* For details, see <http://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/smap/smap.h"
static void _calc_coord_3d(int x, int y, int z, int default_y_offset,
int *coord_x, int *coord_y, int *dim_size)
{
int y_offset;
*coord_x = (x + (dim_size[2] - 1)) - z + 2;
y_offset = default_y_offset - (dim_size[2] * y);
*coord_y = (y_offset - y) + z;
}
static void _calc_coord_4d(int a, int x, int y, int z, int default_y_offset,
int *coord_x, int *coord_y, int* dim_size)
{
int x_offset, y_offset;
x_offset = (dim_size[1] + dim_size[3]) * a + 2;
*coord_x = x_offset + (x + (dim_size[3] - 1)) - z;
y_offset = default_y_offset - (dim_size[3] * y);
*coord_y = (y_offset - y) + z;
}
extern int *get_cluster_dims(node_info_msg_t *node_info_ptr)
{
int *dim_size = slurmdb_setup_cluster_dim_size();
if ((params.cluster_flags & CLUSTER_FLAG_CRAY) && dim_size) {
static int cray_dim_size[3] = {-1, -1, -1};
/* For now, assume one node per coordinate all
* May need to refine. */
cray_dim_size[0] = dim_size[0];
cray_dim_size[1] = dim_size[1];
cray_dim_size[2] = dim_size[2];
return cray_dim_size;
}
if (dim_size == NULL) {
static int default_dim_size[1];
default_dim_size[0] = node_info_ptr->record_count;
return default_dim_size;
}
return dim_size;
}
#ifdef HAVE_BG
static void _internal_setup_grid(int level, uint16_t *coords)
{
ba_mp_t *ba_mp;
smap_node_t *smap_node;
if (level > params.cluster_dims)
return;
if (level < params.cluster_dims) {
for (coords[level] = 0;
coords[level] < dim_size[level];
coords[level]++) {
/* handle the outer dims here */
_internal_setup_grid(level+1, coords);
}
return;
}
ba_mp = bg_configure_coord2ba_mp(coords);
if (!ba_mp || ba_mp->index > smap_system_ptr->node_cnt)
return;
smap_node = xmalloc(sizeof(smap_node_t));
smap_node->coord = xmalloc(sizeof(uint16_t) * params.cluster_dims);
memcpy(smap_node->coord, coords,
sizeof(uint16_t) * params.cluster_dims);
smap_node->index = ba_mp->index;
smap_system_ptr->grid[smap_node->index] = smap_node;
}
#endif
extern void set_grid_inx(int start, int end, int count)
{
int i;
if (!smap_system_ptr || !smap_system_ptr->grid)
return;
for (i = 0; i < smap_system_ptr->node_cnt; i++) {
if (!smap_system_ptr->grid[i]) /* Null node name */
continue;
if ((smap_system_ptr->grid[i]->index < start) ||
(smap_system_ptr->grid[i]->index > end))
continue;
if ((smap_system_ptr->grid[i]->state == NODE_STATE_DOWN) ||
(smap_system_ptr->grid[i]->state & NODE_STATE_DRAIN))
continue;
smap_system_ptr->grid[i]->letter = letters[count%62];
smap_system_ptr->grid[i]->color = colors[count%6];
}
}
/* This function is only called when HAVE_BG is set */
extern int set_grid_bg(int *start, int *end, int count, int set)
{
int node_cnt = 0, i, j;
if (!smap_system_ptr || !smap_system_ptr->grid)
return 0;
for (i = 0; i < smap_system_ptr->node_cnt; i++) {
if (!smap_system_ptr->grid[i]) /* Null node name */
continue;
for (j = 0; j < params.cluster_dims; j++) {
if ((smap_system_ptr->grid[i]->coord[j] < start[j]) ||
(smap_system_ptr->grid[i]->coord[j] > end[j]))
break;
}
if (j < params.cluster_dims)
continue; /* outside of boundary */
if (set ||
((smap_system_ptr->grid[i]->letter == '.') &&
(smap_system_ptr->grid[i]->letter != '#'))) {
smap_system_ptr->grid[i]->letter = letters[count%62];
smap_system_ptr->grid[i]->color = colors[count%6];
}
node_cnt++;
}
return node_cnt;
}
/* Build the smap_system_ptr structure from the node records */
extern void init_grid(node_info_msg_t *node_info_ptr, int cols)
{
int i, j, len;
int default_y_offset = 0;
smap_node_t *smap_node;
smap_system_ptr = xmalloc(sizeof(smap_system_t));
if (!node_info_ptr) {
if (params.display != COMMANDS)
return;
#ifdef HAVE_BG
uint16_t coords[params.cluster_dims];
smap_system_ptr->node_cnt = 1;
for (i=0; i<params.cluster_dims; i++)
smap_system_ptr->node_cnt *= dim_size[i];
smap_system_ptr->grid = xmalloc(sizeof(smap_node_t *) *
smap_system_ptr->node_cnt);
/* We need to make sure we set up the wires if we
don't have a node_info_ptr.
*/
bg_configure_ba_setup_wires();
_internal_setup_grid(0, coords);
#endif
} else {
smap_system_ptr->grid = xmalloc(sizeof(smap_node_t *) *
node_info_ptr->record_count);
for (i = 0; i < node_info_ptr->record_count; i++) {
node_info_t *node_ptr = &node_info_ptr->node_array[i];
if ((node_ptr->name == NULL) ||
(node_ptr->name[0] == '\0'))
continue;
smap_node = xmalloc(sizeof(smap_node_t));
len = strlen(node_ptr->name);
if (params.cluster_dims == 1) {
smap_node->coord = xmalloc(sizeof(uint16_t));
j = len - 1;
while ((node_ptr->name[j] >= '0') &&
(node_ptr->name[j] <= '9')) {
smap_node->coord[0] *= 10;
smap_node->coord[0] +=
node_ptr->name[j] - '0';
j++;
}
} else if (params.cluster_flags & CLUSTER_FLAG_CRAY) {
int len_a, len_h;
len_a = strlen(node_ptr->node_addr);
len_h = strlen(node_ptr->node_hostname);
if (len_a < params.cluster_dims) {
printf("Invalid node addr %s\n",
node_ptr->node_addr);
xfree(smap_node);
continue;
}
if (len_h < 1) {
printf("Invalid node hostname %s\n",
node_ptr->node_hostname);
xfree(smap_node);
continue;
}
smap_node->coord = xmalloc(sizeof(uint16_t) *
params.cluster_dims);
len_a -= params.cluster_dims;
for (j = 0; j < params.cluster_dims; j++) {
smap_node->coord[j] = select_char2coord(
node_ptr->node_addr[len_a+j]);
}
} else {
len -= params.cluster_dims;
if (len < 0) {
printf("Invalid node name: %s.\n",
node_ptr->name);
xfree(smap_node);
continue;
}
smap_node->coord = xmalloc(sizeof(uint16_t) *
params.cluster_dims);
for (j = 0; j < params.cluster_dims; j++) {
smap_node->coord[j] = select_char2coord(
node_ptr->name[len+j]);
}
}
smap_node->index = i;
smap_node->state = node_ptr->node_state;
smap_system_ptr->grid[i] = smap_node;
smap_system_ptr->node_cnt++;
}
}
if (params.cluster_dims == 3) {
default_y_offset = (dim_size[2] * dim_size[1]) +
(dim_size[1] - dim_size[2]);
} else if (params.cluster_dims == 4) {
default_y_offset = (dim_size[3] * dim_size[2]) +
(dim_size[2] - dim_size[3]);
}
if (cols == 0)
cols = 80;
for (i = 0; i < smap_system_ptr->node_cnt; i++) {
smap_node = smap_system_ptr->grid[i];
if (!smap_node) /* Null node name */
continue;
if (params.cluster_dims == 1) {
smap_node->grid_xcord = (i % cols) + 1;
smap_node->grid_ycord = (i / cols) + 1;
} else if (params.cluster_dims == 2) {
smap_node->grid_xcord = smap_node->coord[0] + 1;
smap_node->grid_ycord =
dim_size[1] - smap_node->coord[1];
} else if (params.cluster_dims == 3) {
_calc_coord_3d(smap_node->coord[0], smap_node->coord[1],
smap_node->coord[2],
default_y_offset,
&smap_node->grid_xcord,
&smap_node->grid_ycord, dim_size);
} else if (params.cluster_dims == 4) {
_calc_coord_4d(smap_node->coord[0], smap_node->coord[1],
smap_node->coord[2], smap_node->coord[3],
default_y_offset,
&smap_node->grid_xcord,
&smap_node->grid_ycord, dim_size);
}
}
}
extern void update_grid(node_info_msg_t *node_info_ptr)
{
int i;
if (!node_info_ptr)
return;
for (i = 0; i < node_info_ptr->record_count; i++) {
node_info_t *node_ptr = &node_info_ptr->node_array[i];
smap_node_t *smap_node;
if (!node_info_ptr->node_array[i].name
|| (node_info_ptr->node_array[i].name[0] == '\0'))
continue;
smap_node = smap_system_ptr->grid[i];
if (smap_node)
smap_node->state = node_ptr->node_state;
}
}
extern void clear_grid(void)
{
smap_node_t *smap_node;
int i;
if (!smap_system_ptr || !smap_system_ptr->grid)
return;
for (i = 0; i < smap_system_ptr->node_cnt; i++) {
smap_node = smap_system_ptr->grid[i];
if (!smap_node) /* Null node name */
continue;
if ((smap_node->state == NODE_STATE_DOWN)
|| (smap_node->state & NODE_STATE_DRAIN)) {
smap_node->color = COLOR_BLACK;
smap_node->letter = '#';
} else {
smap_node->color = COLOR_WHITE;
smap_node->letter = '.';
}
}
}
extern void free_grid(void)
{
int i;
if (!smap_system_ptr)
return;
if (smap_system_ptr->grid) {
for (i = 0; i < smap_system_ptr->node_cnt; i++) {
smap_node_t *smap_node = smap_system_ptr->grid[i];
if (!smap_node) /* Null node name */
continue;
xfree(smap_node->coord);
xfree(smap_node);
}
xfree(smap_system_ptr->grid);
}
xfree(smap_system_ptr);
}
/* print_grid - print values of every grid point */
extern void print_grid(void)
{
int i;
if (!smap_system_ptr || !smap_system_ptr->grid)
return;
for (i = 0; i < smap_system_ptr->node_cnt; i++) {
if (!smap_system_ptr->grid[i]) /* Null node name */
continue;
if (smap_system_ptr->grid[i]->color)
init_pair(smap_system_ptr->grid[i]->color,
smap_system_ptr->grid[i]->color, COLOR_BLACK);
else
init_pair(smap_system_ptr->grid[i]->color,
smap_system_ptr->grid[i]->color, 7);
wattron(grid_win, COLOR_PAIR(smap_system_ptr->grid[i]->color));
mvwprintw(grid_win,
smap_system_ptr->grid[i]->grid_ycord,
smap_system_ptr->grid[i]->grid_xcord, "%c",
smap_system_ptr->grid[i]->letter);
wattroff(grid_win, COLOR_PAIR(smap_system_ptr->grid[i]->color));
}
return;
}
bitstr_t *get_requested_node_bitmap(void)
{
static bitstr_t *bitmap = NULL;
static node_info_msg_t *old_node_ptr = NULL, *new_node_ptr;
int error_code;
int i = 0;
node_info_t *node_ptr = NULL;
if (!params.hl)
return NULL;
if (old_node_ptr) {
error_code = slurm_load_node(old_node_ptr->last_update,
&new_node_ptr, SHOW_ALL);
if (error_code == SLURM_SUCCESS)
slurm_free_node_info_msg(old_node_ptr);
else if (slurm_get_errno() == SLURM_NO_CHANGE_IN_DATA)
return bitmap;
} else {
error_code = slurm_load_node((time_t) NULL, &new_node_ptr,
SHOW_ALL);
}
if (bitmap)
FREE_NULL_BITMAP(bitmap);
if (error_code) {
slurm_perror("slurm_load_node");
return NULL;
}
old_node_ptr = new_node_ptr;
bitmap = bit_alloc(old_node_ptr->record_count);
for (i = 0; i < old_node_ptr->record_count; i++) {
node_ptr = &(old_node_ptr->node_array[i]);
if (hostlist_find(params.hl, node_ptr->name) != -1)
bit_set(bitmap, i);
}
return bitmap;
}