| /*****************************************************************************\ |
| * 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; |
| } |