/* * Comparator used for sorting blocks smallest to largest * * returns: -1: rec_a > rec_b 0: rec_a == rec_b 1: rec_a < rec_b * */ extern int bg_record_cmpf_inc(bg_record_t* rec_a, bg_record_t* rec_b) { int size_a = rec_a->cnode_cnt; int size_b = rec_b->cnode_cnt; /* We only look at this if we are ordering blocks larger than * a midplane, order of ionodes is how we order otherwise. */ if ((size_a >= bg_conf->mp_cnode_cnt) || (size_b >= bg_conf->mp_cnode_cnt)) { if (size_a < size_b) return -1; else if (size_a > size_b) return 1; } if (rec_a->mp_str && rec_b->mp_str) { size_a = strcmp(rec_a->mp_str, rec_b->mp_str); if (size_a < 0) return -1; else if (size_a > 0) return 1; } if (!rec_a->ionode_bitmap || !rec_b->ionode_bitmap) return 0; if (bit_ffs(rec_a->ionode_bitmap) < bit_ffs(rec_b->ionode_bitmap)) return -1; else return 1; return 0; }
unsigned bitmap_ffs(const uint32_t *bitmap, unsigned from, unsigned size) { unsigned index_last = BITMAP_WORD(size - 1); unsigned from_word = BITMAP_WORD(from); if (from_word == index_last) { uint32_t mask = SLICE(~0u, (size - 1) % BITS_PER_WORD, from % BITS_PER_WORD) << (from % BITS_PER_WORD); uint32_t word = bitmap[from_word] & mask; if (word != 0) return from_word * BITS_PER_WORD + bit_ffs(word) - 1; else return size; } if (bitmap[from_word] != 0) { uint32_t first_mask = SLICE(~0u, BITS_PER_WORD - 1, from % BITS_PER_WORD) << (from % BITS_PER_WORD); uint32_t first_word = bitmap[from_word] & first_mask; if (first_word != 0) return from_word * BITS_PER_WORD + bit_ffs(first_word) - 1; } for (unsigned w = from_word + 1; w < index_last; ++w) { if (bitmap[w] != 0) return w * BITS_PER_WORD + bit_ffs(bitmap[w]) - 1; } if (index_last != from_word) { uint32_t last = bitmap[index_last] & BITMAP_MASK_LAST(size); if (last != 0) return index_last * BITS_PER_WORD + bit_ffs(last) - 1; } return size; }
/* * Test if job can fit into the given full-length core_bitmap * IN job_resrcs_ptr - resources allocated to a job * IN full_bitmap - bitmap of available CPUs * IN bits_per_node - bits per node in the full_bitmap * RET 1 on success, 0 otherwise */ extern int job_fits_into_cores(job_resources_t *job_resrcs_ptr, bitstr_t *full_bitmap, const uint16_t *bits_per_node) { int full_node_inx = 0, full_bit_inx = 0, job_bit_inx = 0, i; int job_node_cnt; if (!full_bitmap) return 1; job_node_cnt = bit_set_count(job_resrcs_ptr->node_bitmap); for (full_node_inx = bit_ffs(job_resrcs_ptr->node_bitmap); job_node_cnt > 0; full_node_inx++) { if (bit_test(job_resrcs_ptr->node_bitmap, full_node_inx)) { full_bit_inx = cr_node_cores_offset[full_node_inx]; for (i = 0; i < bits_per_node[full_node_inx]; i++) { if (!bit_test(full_bitmap, full_bit_inx + i)) continue; if (job_resrcs_ptr->whole_node || bit_test(job_resrcs_ptr->core_bitmap, job_bit_inx + i)) { return 0; } } job_bit_inx += bits_per_node[full_node_inx]; job_node_cnt --; } } return 1; }
/* * Remove job from full-length core_bitmap * IN job_resrcs_ptr - resources allocated to a job * IN/OUT full_bitmap - bitmap of available CPUs, allocate as needed * IN bits_per_node - bits per node in the full_bitmap * RET 1 on success, 0 otherwise */ extern void remove_job_from_cores(job_resources_t *job_resrcs_ptr, bitstr_t **full_core_bitmap, const uint16_t *bits_per_node) { int full_node_inx = 0, job_node_cnt; int job_bit_inx = 0, full_bit_inx = 0, i; if (!job_resrcs_ptr->core_bitmap) return; /* add the job to the row_bitmap */ if (*full_core_bitmap == NULL) { uint32_t size = 0; for (i = 0; i < node_record_count; i++) size += bits_per_node[i]; *full_core_bitmap = bit_alloc(size); } job_node_cnt = bit_set_count(job_resrcs_ptr->node_bitmap); for (full_node_inx = bit_ffs(job_resrcs_ptr->node_bitmap); job_node_cnt > 0; full_node_inx++) { if (bit_test(job_resrcs_ptr->node_bitmap, full_node_inx)) { full_bit_inx = cr_node_cores_offset[full_node_inx]; for (i = 0; i < bits_per_node[full_node_inx]; i++) { if (!job_resrcs_ptr->whole_node && !bit_test(job_resrcs_ptr->core_bitmap, job_bit_inx + i)) continue; bit_clear(*full_core_bitmap, full_bit_inx + i); } job_bit_inx += bits_per_node[full_node_inx]; job_node_cnt --; } } }
/* given an "avail" node_bitmap, return a corresponding "avail" core_bitmap */ bitstr_t *_make_core_bitmap(bitstr_t *node_map) { uint32_t n, c, nodes, size; uint32_t coff; int i_first, i_last; nodes = bit_size(node_map); size = cr_get_coremap_offset(nodes); bitstr_t *core_map = bit_alloc(size); i_first = bit_ffs(node_map); if (i_first >= 0) i_last = bit_fls(node_map); else i_last = -2; for (n = i_first, c = 0; n <= i_last; n++) { if (bit_test(node_map, n)) { coff = cr_get_coremap_offset(n + 1); while (c < coff) { bit_set(core_map, c++); } } } return core_map; }
/* * bitmap2node_name_sortable - given a bitmap, build a list of comma * separated node names. names may include regular expressions * (e.g. "lx[01-10]") * IN bitmap - bitmap pointer * IN sort - returned sorted list or not * RET pointer to node list or NULL on error * globals: node_record_table_ptr - pointer to node table * NOTE: the caller must xfree the memory at node_list when no longer required */ char * bitmap2node_name_sortable (bitstr_t *bitmap, bool sort) { int i, first, last; hostlist_t hl; char *buf; if (bitmap == NULL) return xstrdup(""); first = bit_ffs(bitmap); if (first == -1) return xstrdup(""); last = bit_fls(bitmap); hl = hostlist_create(""); for (i = first; i <= last; i++) { if (bit_test(bitmap, i) == 0) continue; hostlist_push(hl, node_record_table_ptr[i].name); } if (sort) hostlist_sort(hl); buf = hostlist_ranged_string_xmalloc(hl); hostlist_destroy(hl); return buf; }
/* Compute resource usage for the given job on all available resources * * IN: job_ptr - pointer to the job requesting resources * IN: node_map - bitmap of available nodes * IN/OUT: core_map - bitmap of available cores * IN: cr_node_cnt - total number of nodes in the cluster * IN: cr_type - resource type * OUT: cpu_cnt - number of cpus that can be used by this job * IN: test_only - ignore allocated memory check * RET SLURM_SUCCESS index of selected node or -1 if none */ static int _get_res_usage(struct job_record *job_ptr, bitstr_t *node_map, bitstr_t *core_map, uint32_t cr_node_cnt, struct node_use_record *node_usage, uint16_t cr_type, uint16_t **cpu_cnt_ptr, bool test_only) { uint16_t *cpu_cnt, max_cpu_cnt = 0, part_lln_flag = 0; int i, i_first, i_last; int node_inx = -1; if (cr_node_cnt != node_record_count) { error("select/serial: node count inconsistent with slurmctld"); return SLURM_ERROR; } if (!job_ptr) { error("select/serial: NULL job pointer"); return SLURM_ERROR; } if (job_ptr->part_ptr && (job_ptr->part_ptr->flags & PART_FLAG_LLN)) part_lln_flag = 1; if (job_ptr->details && job_ptr->details->req_node_bitmap) bit_and(node_map, job_ptr->details->req_node_bitmap); cpu_cnt = xmalloc(cr_node_cnt * sizeof(uint16_t)); i_first = bit_ffs(node_map); if (i_first >= 0) i_last = bit_fls(node_map); else i_last = -2; for (i = i_first; i <= i_last; i++) { if (!bit_test(node_map, i)) continue; cpu_cnt[i] = _can_job_run_on_node(job_ptr, core_map, i, node_usage, cr_type, test_only); if (!(cr_type & CR_LLN) && !part_lln_flag && cpu_cnt[i]) { bit_nclear(node_map, 0, (node_record_count - 1)); bit_set(node_map, i); node_inx = i; break; /* select/serial: only need one node */ } } if ((cr_type & CR_LLN) || part_lln_flag) { for (i = i_first; i <= i_last; i++) { if (cpu_cnt[i] > max_cpu_cnt) { max_cpu_cnt = cpu_cnt[i]; node_inx = i; } } if (node_inx >= 0) { bit_nclear(node_map, 0, (node_record_count - 1)); bit_set(node_map, node_inx); } } *cpu_cnt_ptr = cpu_cnt; return node_inx; }
/* For a newly starting job, set "new_job_time" in each of it's nodes * NOTE: The job and node data structures must be locked on function entry */ extern void set_node_new_job(struct job_record *job_ptr, struct node_record *node_record_table_ptr) { int i, i_first, i_last; struct node_record *node_ptr; time_t now = time(NULL); if (!job_ptr || !job_ptr->node_bitmap) { error("%s: job_ptr node_bitmap is NULL", __func__); return; } i_first = bit_ffs(job_ptr->node_bitmap); if (i_first >= 0) i_last = bit_fls(job_ptr->node_bitmap); else i_last = i_first - 1; for (i = i_first; i <= i_last; i++) { if (!bit_test(job_ptr->node_bitmap, i)) continue; node_ptr = node_record_table_ptr + i; if (node_ptr->power) node_ptr->power->new_job_time = now; } }
static void __raspi__dispatch_bank(uint32_t pend_bank, int32_t add_to) { uint32_t bit; while(pend_bank) { bit = bit_ffs(pend_bank) - 1; pend_bank ^= (1 << bit); irq_dispatch(bit + add_to); } }
/* Return task list in Moab format 2: tux[0-1]*2:tux2 */ static char * _task_list_exp(struct job_record *job_ptr) { int i, node_inx = 0, reps = -1, task_cnt; char *buf = NULL, *host; hostlist_t hl_tmp = (hostlist_t) NULL; job_resources_t *job_resrcs_ptr = job_ptr->job_resrcs; xassert(job_resrcs_ptr); for (i=0; i<job_resrcs_ptr->nhosts; i++) { if (i == 0) { xassert(job_resrcs_ptr->cpus && job_resrcs_ptr->node_bitmap); node_inx = bit_ffs(job_resrcs_ptr->node_bitmap); } else { for (node_inx++; node_inx<node_record_count; node_inx++) { if (bit_test(job_resrcs_ptr->node_bitmap, node_inx)) break; } if (node_inx >= node_record_count) { error("Improperly formed job_resrcs for %u", job_ptr->job_id); break; } } host = node_record_table_ptr[node_inx].name; task_cnt = job_resrcs_ptr->cpus[i]; if (job_ptr->details && job_ptr->details->cpus_per_task) task_cnt /= job_ptr->details->cpus_per_task; if (task_cnt < 1) { error("Invalid task_cnt for job %u on node %s", job_ptr->job_id, host); task_cnt = 1; } if (reps == task_cnt) { /* append to existing hostlist record */ if (hostlist_push(hl_tmp, host) == 0) error("hostlist_push failure"); } else { if (hl_tmp) _append_hl_buf(&buf, &hl_tmp, &reps); /* start new hostlist record */ hl_tmp = hostlist_create(host); if (hl_tmp) reps = task_cnt; else error("hostlist_create failure"); } } if (hl_tmp) _append_hl_buf(&buf, &hl_tmp, &reps); return buf; }
/* For each running job, return power allocation/use information in a List * containing elements of type power_by_job_t. * NOTE: Job data structure must be locked on function entry * NOTE: Call list_delete() to free return value * NOTE: This function is currently unused. */ extern List get_job_power(List job_list, struct node_record *node_record_table_ptr) { struct node_record *node_ptr; struct job_record *job_ptr; ListIterator job_iterator; power_by_job_t *power_ptr; char jobid_buf[64] = ""; int i, i_first, i_last; uint64_t debug_flag = slurm_get_debug_flags(); List job_power_list = list_create(_job_power_del); time_t now = time(NULL); job_iterator = list_iterator_create(job_list); while ((job_ptr = (struct job_record *) list_next(job_iterator))) { if (!IS_JOB_RUNNING(job_ptr)) continue; power_ptr = xmalloc(sizeof(power_by_job_t)); power_ptr->job_id = job_ptr->job_id; power_ptr->start_time = job_ptr->start_time; list_append(job_power_list, power_ptr); if (!job_ptr->node_bitmap) { error("%s: %s node_bitmap is NULL", __func__, jobid2fmt(job_ptr, jobid_buf, sizeof(jobid_buf))); continue; } i_first = bit_ffs(job_ptr->node_bitmap); if (i_first < 0) continue; i_last = bit_fls(job_ptr->node_bitmap); for (i = i_first; i <= i_last; i++) { if (!bit_test(job_ptr->node_bitmap, i)) continue; node_ptr = node_record_table_ptr + i; if (node_ptr->power) { power_ptr->alloc_watts += node_ptr->power->cap_watts; } if (node_ptr->energy) { power_ptr->used_watts += node_ptr->energy->current_watts; } } if (debug_flag & DEBUG_FLAG_POWER) { info("%s: %s Age=%ld(sec) AllocWatts=%u UsedWatts=%u", __func__, jobid2fmt(job_ptr, jobid_buf, sizeof(jobid_buf)), (long int) difftime(now, power_ptr->start_time), power_ptr->alloc_watts, power_ptr->used_watts); } } list_iterator_destroy(job_iterator); return job_power_list; }
void test_fls64() { sput_fail_unless(bit_fls(0ull)==-1, "Edge case: arg=0"); sput_fail_unless(bit_fls(1ull)==0, "arg=1"); sput_fail_unless(bit_fls(0xFFFFFFFFFFFFFFFFull)==63, "arg=0xFFFFFFFF"); sput_fail_unless(bit_ffs(0x8000000000000000ull)==63, "arg=0x8000000000000000"); for (uint64_t i=0; i<64; ++i) { sput_fail_unless(bit_fls(1ull<<i)==i, "General Test"); sput_fail_unless(bit_fls(0xFFFFFFFFFFFFFFFFull>>i)==63-i, "General test1"); } }
/* Return task list in Moab format 1: tux0:tux0:tux1:tux1:tux2 */ static char * _task_list(struct job_record *job_ptr) { int i, j, node_inx = 0, task_cnt; char *buf = NULL, *host; job_resources_t *job_resrcs_ptr = job_ptr->job_resrcs; xassert(job_resrcs_ptr); #ifdef HAVE_BG if(job_ptr->node_cnt) { task_cnt = job_resrcs_ptr->cpu_array_value[0]; } else task_cnt = 1; #endif for (i=0; i<job_resrcs_ptr->nhosts; i++) { if (i == 0) { xassert(job_resrcs_ptr->cpus && job_resrcs_ptr->node_bitmap); node_inx = bit_ffs(job_resrcs_ptr->node_bitmap); } else { for (node_inx++; node_inx<node_record_count; node_inx++) { if (bit_test(job_resrcs_ptr->node_bitmap, node_inx)) break; } if (node_inx >= node_record_count) { error("Improperly formed job_resrcs for %u", job_ptr->job_id); break; } } host = node_record_table_ptr[node_inx].name; #ifndef HAVE_BG task_cnt = job_resrcs_ptr->cpus[i]; if (job_ptr->details && job_ptr->details->cpus_per_task) task_cnt /= job_ptr->details->cpus_per_task; if (task_cnt < 1) { error("Invalid task_cnt for job %u on node %s", job_ptr->job_id, host); task_cnt = 1; } #endif for (j=0; j<task_cnt; j++) { if (buf) xstrcat(buf, ":"); xstrcat(buf, host); } } return buf; }
/* power_job_reboot - Reboot compute nodes for a job from the head node */ extern int power_job_reboot(struct job_record *job_ptr) { int rc = SLURM_SUCCESS; int i, i_first, i_last; struct node_record *node_ptr; bitstr_t *wake_node_bitmap = NULL; time_t now = time(NULL); char *nodes, *features = NULL; wake_node_bitmap = bit_alloc(node_record_count); i_first = bit_ffs(job_ptr->node_bitmap); i_last = bit_fls(job_ptr->node_bitmap); for (i = i_first; i <= i_last; i++) { if (!bit_test(job_ptr->node_bitmap, i)) continue; node_ptr = node_record_table_ptr + i; resume_cnt++; resume_cnt_f++; node_ptr->node_state &= (~NODE_STATE_POWER_SAVE); node_ptr->node_state |= NODE_STATE_POWER_UP; node_ptr->node_state |= NODE_STATE_NO_RESPOND; bit_clear(power_node_bitmap, i); bit_clear(avail_node_bitmap, i); node_ptr->last_response = now + resume_timeout; bit_set(wake_node_bitmap, i); bit_set(resume_node_bitmap, i); } nodes = bitmap2node_name(wake_node_bitmap); if (nodes) { #if _DEBUG info("power_save: reboot nodes %s", nodes); #else verbose("power_save: reboot nodes %s", nodes); #endif if (job_ptr->details && job_ptr->details->features) features = xlate_features(job_ptr->details->features); _run_prog(resume_prog, nodes, features); xfree(features); } else { error("power_save: bitmap2nodename"); rc = SLURM_ERROR; } xfree(nodes); FREE_NULL_BITMAP(wake_node_bitmap); last_node_update = now; return rc; }
/* Remove any specialized cores from those allocated to the job */ static void _clear_spec_cores(struct job_record *job_ptr, bitstr_t *avail_core_bitmap) { int first_node, last_node, i_node; int first_core, last_core, i_core; int alloc_node = -1, alloc_core = -1, size; job_resources_t *job_res = job_ptr->job_resrcs; multi_core_data_t *mc_ptr = NULL; if (job_ptr->details && job_ptr->details->mc_ptr) mc_ptr = job_ptr->details->mc_ptr; size = bit_size(job_res->core_bitmap); bit_nset(job_res->core_bitmap, 0, size - 1); first_node = bit_ffs(job_res->node_bitmap); if (first_node >= 0) last_node = bit_fls(job_res->node_bitmap); else last_node = first_node - 1; for (i_node = first_node; i_node <= last_node; i_node++) { if (!bit_test(job_res->node_bitmap, i_node)) continue; job_res->cpus[++alloc_node] = 0; first_core = cr_get_coremap_offset(i_node); last_core = cr_get_coremap_offset(i_node + 1) - 1; for (i_core = first_core; i_core <= last_core; i_core++) { alloc_core++; if (bit_test(avail_core_bitmap, i_core)) { uint16_t tpc = select_node_record[i_node].vpus; if (mc_ptr && (mc_ptr->threads_per_core != NO_VAL16) && (mc_ptr->threads_per_core < tpc)) tpc = mc_ptr->threads_per_core; job_res->cpus[alloc_node] += tpc; } else { bit_clear(job_res->core_bitmap, alloc_core); } } } }
void test_ffs32() { sput_fail_unless(bit_ffs(0u)==-1, "Edge case: arg=0"); sput_fail_unless(bit_ffs(1u)==0, "arg=1"); sput_fail_unless(bit_ffs(0xFFFFFFFFu)==0, "arg=0xFFFFFFFF"); sput_fail_unless(bit_ffs(0x80000000u)==31, "arg=0x80000000"); for (uint32_t i=0; i<32; ++i) { sput_fail_unless(bit_ffs(0xFFFFFFFFu<<i)==i, "General test0"); sput_fail_unless(bit_ffs(1u<<i)==i, "General test1"); sput_fail_unless(bit_ffs(0xFFFFFFFFu>>i)==0, "General test2"); } }
/* Given a job pointer and a global node index, return the index of that * node in the job_resrcs_ptr->cpus. Return -1 if invalid */ extern int job_resources_node_inx_to_cpu_inx(job_resources_t *job_resrcs_ptr, int node_inx) { int first_inx, i, node_offset; /* Test for error cases */ if (!job_resrcs_ptr || !job_resrcs_ptr->node_bitmap) { error("job_resources_node_inx_to_cpu_inx: " "no job_resrcs or node_bitmap"); return -1; } if (!bit_test(job_resrcs_ptr->node_bitmap, node_inx)) { error("job_resources_node_inx_to_cpu_inx: " "Invalid node_inx"); return -1; } if (job_resrcs_ptr->cpu_array_cnt == 0) { error("job_resources_node_inx_to_cpu_inx: " "Invalid cpu_array_cnt"); return -1; } /* Only one record, no need to search */ if (job_resrcs_ptr->nhosts == 1) return 0; /* Scan bitmap, convert node_inx to node_cnt within job's allocation */ first_inx = bit_ffs(job_resrcs_ptr->node_bitmap); for (i=first_inx, node_offset=-1; i<=node_inx; i++) { if (bit_test(job_resrcs_ptr->node_bitmap, i)) node_offset++; } if (node_offset >= job_resrcs_ptr->nhosts) { error("job_resources_node_inx_to_cpu_inx: " "Found %d of %d nodes", job_resrcs_ptr->nhosts, node_offset); return -1; } return node_offset; }
static int _file_bcast(opt_t *opt_local, srun_job_t *job) { struct bcast_parameters *params; int rc; if ((opt_local->argc == 0) || (opt_local->argv[0] == NULL)) { error("No command name to broadcast"); return SLURM_ERROR; } params = xmalloc(sizeof(struct bcast_parameters)); params->block_size = 8 * 1024 * 1024; params->compress = opt_local->compress; if (opt_local->bcast_file) { params->dst_fname = xstrdup(opt_local->bcast_file); } else { xstrfmtcat(params->dst_fname, "%s/slurm_bcast_%u.%u", opt_local->cwd, job->jobid, job->stepid); } params->fanout = 0; params->job_id = job->jobid; params->force = true; if (opt_local->pack_grp_bits) params->pack_job_offset = bit_ffs(opt_local->pack_grp_bits); else params->pack_job_offset = NO_VAL; params->preserve = true; params->src_fname = opt_local->argv[0]; params->step_id = job->stepid; params->timeout = 0; params->verbose = 0; rc = bcast_file(params); if (rc == SLURM_SUCCESS) { xfree(opt_local->argv[0]); opt_local->argv[0] = params->dst_fname; } else { xfree(params->dst_fname); } xfree(params); return rc; }
/* Compute resource usage for the given job on all available resources * * IN: job_ptr - pointer to the job requesting resources * IN: node_map - bitmap of available nodes * IN/OUT: core_map - bitmap of available cores * IN: cr_node_cnt - total number of nodes in the cluster * IN: cr_type - resource type * OUT: cpu_cnt - number of cpus that can be used by this job * IN: test_only - ignore allocated memory check * RET SLURM_SUCCESS index of selected node or -1 if none */ static int _get_res_usage(struct job_record *job_ptr, bitstr_t *node_map, bitstr_t *core_map, uint32_t cr_node_cnt, struct node_use_record *node_usage, uint16_t cr_type, uint16_t **cpu_cnt_ptr, bool test_only) { uint16_t *cpu_cnt; uint32_t n; int i_first, i_last; int node_inx = -1; if (cr_node_cnt != node_record_count) { error("select/serial: node count inconsistent with slurmctld"); return SLURM_ERROR; } if (job_ptr->details && job_ptr->details->req_node_bitmap) bit_and(node_map, job_ptr->details->req_node_bitmap); cpu_cnt = xmalloc(cr_node_cnt * sizeof(uint16_t)); i_first = bit_ffs(node_map); if (i_first >= 0) i_last = bit_fls(node_map); else i_last = -2; for (n = i_first; n <= i_last; n++) { if (!bit_test(node_map, n)) continue; cpu_cnt[n] = _can_job_run_on_node(job_ptr, core_map, n, node_usage, cr_type, test_only); if (cpu_cnt[n]) { bit_nclear(node_map, 0, (node_record_count - 1)); bit_set(node_map, n); node_inx = n; break; /* select/serial: only need one node */ } } *cpu_cnt_ptr = cpu_cnt; return node_inx; }
static int cachedev_find_dirty_cache_blocks (struct cache_dev *cache, int *blknoPtr, int *bcountPtr) { int blkno; #ifdef DEBUG_CACHEDEV fprintf(outputfile, "*** %f: Entered cachedev::cachedev_find_dirty_cache_blocks\n", simtime ); fflush(outputfile); #endif bit_ffs (cache->dirtymap, cache->size, blknoPtr); if (*blknoPtr == -1) { return (0); } blkno = *blknoPtr; while (bit_test (cache->dirtymap, blkno) != 0) { blkno++; } *bcountPtr = blkno - *blknoPtr; return (1); }
/* * bitmap2hostlist - given a bitmap, build a hostlist * IN bitmap - bitmap pointer * RET pointer to hostlist or NULL on error * globals: node_record_table_ptr - pointer to node table * NOTE: the caller must xfree the memory at node_list when no longer required */ hostlist_t bitmap2hostlist (bitstr_t *bitmap) { int i, first, last; hostlist_t hl; if (bitmap == NULL) return NULL; first = bit_ffs(bitmap); if (first == -1) return NULL; last = bit_fls(bitmap); hl = hostlist_create(NULL); for (i = first; i <= last; i++) { if (bit_test(bitmap, i) == 0) continue; hostlist_push_host(hl, node_record_table_ptr[i].name); } return hl; }
/* a helper function for _add_job_to_active when GS_SOCKET * a job has just been added to p_ptr->active_resmap, so set all cores of * each used socket to avoid activating another job on the same socket */ static void _fill_sockets(bitstr_t *job_nodemap, struct gs_part *p_ptr) { uint32_t c, i; int n, first_bit, last_bit; if (!job_nodemap || !p_ptr || !p_ptr->active_resmap) return; first_bit = bit_ffs(job_nodemap); last_bit = bit_fls(job_nodemap); if ((first_bit < 0) || (last_bit < 0)) fatal("gang: _afill_sockets: nodeless job?"); for (c = 0, n = 0; n < first_bit; n++) { c += _get_phys_bit_cnt(n); } for (n = first_bit; n <= last_bit; n++) { uint16_t s, socks, cps, cores_per_node; cores_per_node = _get_phys_bit_cnt(n); if (bit_test(job_nodemap, n) == 0) { c += cores_per_node; continue; } socks = _get_socket_cnt(n); cps = cores_per_node / socks; for (s = 0; s < socks; s++) { for (i = c; i < c+cps; i++) { if (bit_test(p_ptr->active_resmap, i)) break; } if (i < c+cps) { /* set all bits on this used socket */ bit_nset(p_ptr->active_resmap, c, c+cps-1); } c += cps; } } }
/** * do_basil_reserve - create a BASIL reservation. * IN job_ptr - pointer to job which has just been allocated resources * RET 0 or error code, job will abort or be requeued on failure */ extern int do_basil_reserve(struct job_record *job_ptr) { struct nodespec *ns_head = NULL; uint16_t mppwidth = 0, mppdepth, mppnppn; uint32_t mppmem = 0, node_min_mem = 0; uint32_t resv_id; int i, first_bit, last_bit; hostlist_t hl; long rc; char *user, batch_id[16]; if (!job_ptr->job_resrcs || job_ptr->job_resrcs->nhosts == 0) return SLURM_SUCCESS; debug3("job #%u: %u nodes = %s, cpus=%u" , job_ptr->job_id, job_ptr->job_resrcs->nhosts, job_ptr->job_resrcs->nodes, job_ptr->job_resrcs->ncpus ); if (job_ptr->job_resrcs->node_bitmap == NULL) { error("job %u node_bitmap not set", job_ptr->job_id); return SLURM_SUCCESS; } first_bit = bit_ffs(job_ptr->job_resrcs->node_bitmap); last_bit = bit_fls(job_ptr->job_resrcs->node_bitmap); if (first_bit == -1 || last_bit == -1) return SLURM_SUCCESS; /* no nodes allocated */ mppdepth = MAX(1, job_ptr->details->cpus_per_task); mppnppn = job_ptr->details->ntasks_per_node; /* mppmem */ if (job_ptr->details->pn_min_memory & MEM_PER_CPU) { /* Only honour --mem-per-cpu if --ntasks has been given */ if (job_ptr->details->num_tasks) mppmem = job_ptr->details->pn_min_memory & ~MEM_PER_CPU; } else if (job_ptr->details->pn_min_memory) { node_min_mem = job_ptr->details->pn_min_memory; } hl = hostlist_create(""); if (hl == NULL) fatal("hostlist_create: malloc error"); for (i = first_bit; i <= last_bit; i++) { struct node_record *node_ptr = node_record_table_ptr + i; uint32_t basil_node_id; if (!bit_test(job_ptr->job_resrcs->node_bitmap, i)) continue; if (!node_ptr->name || node_ptr->name[0] == '\0') continue; /* bad node */ if (sscanf(node_ptr->name, "nid%05u", &basil_node_id) != 1) fatal("can not read basil_node_id from %s", node_ptr->name); if (ns_add_node(&ns_head, basil_node_id) != 0) { error("can not add node %s (nid%05u)", node_ptr->name, basil_node_id); free_nodespec(ns_head); return SLURM_ERROR; } if (node_min_mem) { uint32_t node_cpus, node_mem; if (slurmctld_conf.fast_schedule) { node_cpus = node_ptr->config_ptr->cpus; node_mem = node_ptr->config_ptr->real_memory; } else { node_cpus = node_ptr->cpus; node_mem = node_ptr->real_memory; } /* * ALPS 'Processing Elements per Node' value (aprun -N), * which in slurm is --ntasks-per-node and 'mppnppn' in * PBS: if --ntasks is specified, default to the number * of cores per node (also the default for 'aprun -N'). */ node_mem /= mppnppn ? mppnppn : node_cpus; mppmem = node_min_mem = MIN(node_mem, node_min_mem); } } /* mppwidth */ for (i = 0; i < job_ptr->job_resrcs->nhosts; i++) { uint16_t node_tasks = job_ptr->job_resrcs->cpus[i] / mppdepth; if (mppnppn && mppnppn < node_tasks) node_tasks = mppnppn; mppwidth += node_tasks; } snprintf(batch_id, sizeof(batch_id), "%u", job_ptr->job_id); user = uid_to_string(job_ptr->user_id); rc = basil_reserve(user, batch_id, mppwidth, mppdepth, mppnppn, mppmem, ns_head); xfree(user); if (rc <= 0) { /* errno value will be resolved by select_g_job_begin() */ errno = is_transient_error(rc) ? EAGAIN : ECONNABORTED; return SLURM_ERROR; } resv_id = rc; if (_set_select_jobinfo(job_ptr->select_jobinfo->data, SELECT_JOBDATA_RESV_ID, &resv_id) != SLURM_SUCCESS) { /* * This is a fatal error since it means we will not be able to * confirm the reservation; no step will be able to run in it. */ error("job %u: can not set resId %u", job_ptr->job_id, resv_id); basil_release(resv_id); return SLURM_ERROR; } info("ALPS RESERVATION #%u, JobId %u: BASIL -n %d -N %d -d %d -m %d", resv_id, job_ptr->job_id, mppwidth, mppnppn, mppdepth, mppmem); return SLURM_SUCCESS; }
static int _grid_table_by_switch(button_processor_t *button_processor, List node_list) { int rc = SLURM_SUCCESS; int inx = 0, ii = 0; switch_record_bitmaps_t *sw_nodes_bitmaps_ptr = g_switch_nodes_maps; #if TOPO_DEBUG /* engage if want original display below switched */ ListIterator itr = list_iterator_create(node_list); sview_node_info_t *sview_node_info_ptr = NULL; #endif button_processor->inx = &inx; for (ii=0; ii<g_topo_info_msg_ptr->record_count; ii++, sw_nodes_bitmaps_ptr++) { int j = 0, first, last; if (g_topo_info_msg_ptr->topo_array[ii].level) continue; first = bit_ffs(sw_nodes_bitmaps_ptr->node_bitmap); if (first == -1) continue; last = bit_fls(sw_nodes_bitmaps_ptr->node_bitmap); button_processor->inx = &j; button_processor->force_row_break = false; for (j = first; j <= last; j++) { if (TOPO_DEBUG) g_print("allocated node = %s button# %d\n", g_node_info_ptr->node_array[j].name, j); if (!bit_test(sw_nodes_bitmaps_ptr->node_bitmap, j)) continue; /* if (!working_sview_config.show_hidden) { */ /* if (!check_part_includes_node(j)) */ /* continue; */ /* } */ if (j == last) button_processor->force_row_break = true; if ((rc = _add_button_to_list( &g_node_info_ptr->node_array[j], button_processor)) != SLURM_SUCCESS) break; button_processor->force_row_break = false; } rc = _add_button_to_list(NULL, button_processor); } #if TOPO_DEBUG /* engage this if want original display below * switched grid */ button_processor->inx = &inx; while ((sview_node_info_ptr = list_next(itr))) { if ((rc = _add_button_to_list( sview_node_info_ptr->node_ptr, button_processor)) != SLURM_SUCCESS) break; inx++; } list_iterator_destroy(itr); #endif /* This is needed to get the correct width of the grid window. * If it is not given then we get a really narrow window. */ gtk_table_set_row_spacing(button_processor->table, (*button_processor->coord_y)? ((*button_processor->coord_y)-1):0, 1); return rc; }
int32_t kbd_process_keys(bthid_session_p s) { bitstr_t diff[bitstr_size(xsize)]; int32_t f1, f2, i; assert(s != NULL); assert(s->srv != NULL); /* Check if the new keys have been pressed */ bit_ffs(s->keys1, xsize, &f1); /* Check if old keys still pressed */ bit_ffs(s->keys2, xsize, &f2); if (f1 == -1) { /* no new key pressed */ if (f2 != -1) { /* release old keys */ kbd_write(s->keys2, f2, 0, s->vkbd); memset(s->keys2, 0, bitstr_size(xsize)); } return (0); } if (f2 == -1) { /* no old keys, but new keys pressed */ assert(f1 != -1); memcpy(s->keys2, s->keys1, bitstr_size(xsize)); kbd_write(s->keys1, f1, 1, s->vkbd); memset(s->keys1, 0, bitstr_size(xsize)); return (0); } /* new keys got pressed, old keys got released */ memset(diff, 0, bitstr_size(xsize)); for (i = f2; i < xsize; i ++) { if (bit_test(s->keys2, i)) { if (!bit_test(s->keys1, i)) { bit_clear(s->keys2, i); bit_set(diff, i); } } } for (i = f1; i < xsize; i++) { if (bit_test(s->keys1, i)) { if (!bit_test(s->keys2, i)) bit_set(s->keys2, i); else bit_clear(s->keys1, i); } } bit_ffs(diff, xsize, &f2); if (f2 > 0) kbd_write(diff, f2, 0, s->vkbd); bit_ffs(s->keys1, xsize, &f1); if (f1 > 0) { kbd_write(s->keys1, f1, 1, s->vkbd); memset(s->keys1, 0, bitstr_size(xsize)); } return (0); }
/* power_job_reboot - Reboot compute nodes for a job from the head node */ extern int power_job_reboot(struct job_record *job_ptr) { int rc = SLURM_SUCCESS; int i, i_first, i_last; struct node_record *node_ptr; bitstr_t *boot_node_bitmap = NULL; time_t now = time(NULL); char *nodes, *features = NULL; pid_t pid; boot_node_bitmap = node_features_reboot(job_ptr); if (boot_node_bitmap == NULL) return SLURM_SUCCESS; i_first = bit_ffs(boot_node_bitmap); if (i_first >= 0) i_last = bit_fls(boot_node_bitmap); else i_last = i_first - 1; for (i = i_first; i <= i_last; i++) { if (!bit_test(boot_node_bitmap, i)) continue; node_ptr = node_record_table_ptr + i; resume_cnt++; resume_cnt_f++; node_ptr->node_state &= (~NODE_STATE_POWER_SAVE); node_ptr->node_state |= NODE_STATE_POWER_UP; node_ptr->node_state |= NODE_STATE_NO_RESPOND; bit_clear(power_node_bitmap, i); bit_clear(avail_node_bitmap, i); node_ptr->last_response = now + resume_timeout; bit_set(resume_node_bitmap, i); } nodes = bitmap2node_name(boot_node_bitmap); if (nodes) { job_ptr->job_state |= JOB_CONFIGURING; job_ptr->wait_all_nodes = 1; if (job_ptr->details && job_ptr->details->features && node_features_g_user_update(job_ptr->user_id)) { features = node_features_g_job_xlate( job_ptr->details->features); } pid = _run_prog(resume_prog, nodes, features); #if _DEBUG info("power_save: pid %d reboot nodes %s features %s", (int) pid, nodes, features); #else verbose("power_save: pid %d reboot nodes %s features %s", (int) pid, nodes, features); #endif xfree(features); } else { error("power_save: bitmap2nodename"); rc = SLURM_ERROR; } xfree(nodes); FREE_NULL_BITMAP(boot_node_bitmap); last_node_update = now; return rc; }
static int _breakup_blocks(List block_list, List new_blocks, select_ba_request_t *request, List my_block_list, bool only_free, bool only_small) { int rc = SLURM_ERROR; bg_record_t *bg_record = NULL; ListIterator itr = NULL, bit_itr = NULL; int total_cnode_cnt=0; char start_char[SYSTEM_DIMENSIONS+1]; bitstr_t *ionodes = bit_alloc(bg_conf->ionodes_per_mp); int cnodes = request->procs / bg_conf->cpu_ratio; int curr_mp_bit = -1; int dim; if (bg_conf->slurm_debug_flags & DEBUG_FLAG_BG_PICK) info("cpu_count=%d cnodes=%d o_free=%d o_small=%d", request->procs, cnodes, only_free, only_small); switch(cnodes) { case 16: /* a 16 can go anywhere */ break; case 32: bit_itr = list_iterator_create(bg_lists->valid_small32); break; case 64: bit_itr = list_iterator_create(bg_lists->valid_small64); break; case 128: bit_itr = list_iterator_create(bg_lists->valid_small128); break; case 256: bit_itr = list_iterator_create(bg_lists->valid_small256); break; default: error("We shouldn't be here with this size %d", cnodes); goto finished; break; } /* First try with free blocks a midplane or less. Then try with the * smallest blocks. */ itr = list_iterator_create(block_list); while ((bg_record = list_next(itr))) { if (bg_record->free_cnt) { if (bg_conf->slurm_debug_flags & DEBUG_FLAG_BG_PICK) info("%s being freed by other job(s), skipping", bg_record->bg_block_id); continue; } /* never look at a block if a job is running */ if (bg_record->job_running != NO_JOB_RUNNING) continue; /* on the third time through look for just a block * that isn't used */ /* check for free blocks on the first and second time */ if (only_free && (bg_record->state != BG_BLOCK_FREE)) continue; /* check small blocks first */ if (only_small && (bg_record->cnode_cnt > bg_conf->mp_cnode_cnt)) continue; if (request->avail_mp_bitmap && !bit_super_set(bg_record->bitmap, request->avail_mp_bitmap)) { if (bg_conf->slurm_debug_flags & DEBUG_FLAG_BG_PICK) info("bg block %s has nodes not usable " "by this job", bg_record->bg_block_id); continue; } if (bg_record->cnode_cnt == cnodes) { ba_mp_t *ba_mp = NULL; if (bg_record->ba_mp_list) ba_mp = list_peek(bg_record->ba_mp_list); if (!ba_mp) { for (dim=0; dim<SYSTEM_DIMENSIONS; dim++) start_char[dim] = alpha_num[ bg_record->start[dim]]; start_char[dim] = '\0'; request->save_name = xstrdup(start_char); } else request->save_name = xstrdup(ba_mp->coord_str); rc = SLURM_SUCCESS; goto finished; } /* lets see if we can combine some small ones */ if (bg_record->cnode_cnt < cnodes) { char bitstring[BITSIZE]; bitstr_t *bitstr = NULL; int num_over = 0; int num_cnodes = bg_record->cnode_cnt; int rec_mp_bit = bit_ffs(bg_record->bitmap); if (curr_mp_bit != rec_mp_bit) { /* Got a different node than * previously, since the list should * be in order of nodes for small blocks * just clear here since the last node * doesn't have any more. */ curr_mp_bit = rec_mp_bit; bit_nclear(ionodes, 0, (bg_conf->ionodes_per_mp-1)); total_cnode_cnt = 0; } /* On really busy systems we can get overlapping blocks here. If that is the case only add that which doesn't overlap. */ if ((num_over = bit_overlap( ionodes, bg_record->ionode_bitmap))) { /* Since the smallest block size is the number of cnodes in an io node, just multiply the num_over by that to get the number of cnodes to remove. */ if ((num_cnodes -= num_over * bg_conf->smallest_block) <= 0) continue; } bit_or(ionodes, bg_record->ionode_bitmap); /* check and see if the bits set are a valid combo */ if (bit_itr) { while ((bitstr = list_next(bit_itr))) { if (bit_super_set(ionodes, bitstr)) break; } list_iterator_reset(bit_itr); } if (!bitstr) { bit_nclear(ionodes, 0, (bg_conf->ionodes_per_mp-1)); bit_or(ionodes, bg_record->ionode_bitmap); total_cnode_cnt = num_cnodes = bg_record->cnode_cnt; } else total_cnode_cnt += num_cnodes; bit_fmt(bitstring, BITSIZE, ionodes); if (bg_conf->slurm_debug_flags & DEBUG_FLAG_BG_PICK) info("combine adding %s %s %d got %d set " "ionodes %s total is %s", bg_record->bg_block_id, bg_record->mp_str, num_cnodes, total_cnode_cnt, bg_record->ionode_str, bitstring); if (total_cnode_cnt == cnodes) { ba_mp_t *ba_mp = NULL; if (bg_record->ba_mp_list) ba_mp = list_peek( bg_record->ba_mp_list); if (!ba_mp) { for (dim=0; dim<SYSTEM_DIMENSIONS; dim++) start_char[dim] = alpha_num[ bg_record->start[dim]]; start_char[dim] = '\0'; request->save_name = xstrdup(start_char); } else request->save_name = xstrdup(ba_mp->coord_str); if (!my_block_list) { rc = SLURM_SUCCESS; goto finished; } bg_record = create_small_record(bg_record, ionodes, cnodes); list_append(new_blocks, bg_record); rc = SLURM_SUCCESS; goto finished; } continue; } /* we found a block that is bigger than requested */ break; } if (bg_record) { ba_mp_t *ba_mp = NULL; if (bg_record->ba_mp_list) ba_mp = list_peek(bg_record->ba_mp_list); if (!ba_mp) { for (dim=0; dim<SYSTEM_DIMENSIONS; dim++) start_char[dim] = alpha_num[ bg_record->start[dim]]; start_char[dim] = '\0'; request->save_name = xstrdup(start_char); } else request->save_name = xstrdup(ba_mp->coord_str); /* It appears we don't need this original record * anymore, just work off the copy if indeed it is a copy. */ /* bg_record_t *found_record = NULL; */ /* if (bg_record->original) { */ /* if (bg_conf->slurm_debug_flags & DEBUG_FLAG_BG_PICK) */ /* info("1 This was a copy %s", */ /* bg_record->bg_block_id); */ /* found_record = bg_record->original; */ /* } else { */ /* if (bg_conf->slurm_debug_flags & DEBUG_FLAG_BG_PICK) */ /* info("looking for original"); */ /* found_record = find_org_in_bg_list( */ /* bg_lists->main, bg_record); */ /* } */ if ((bg_conf->slurm_debug_flags & DEBUG_FLAG_BG_PICK) && bg_record->original && (bg_record->original->magic != BLOCK_MAGIC)) { info("This record %s has bad magic, it must be " "getting freed. No worries it will all be " "figured out later.", bg_record->bg_block_id); } /* if (!found_record || found_record->magic != BLOCK_MAGIC) { */ /* error("this record wasn't found in the list!"); */ /* rc = SLURM_ERROR; */ /* goto finished; */ /* } */ if (bg_conf->slurm_debug_flags & DEBUG_FLAG_BG_PICK) { char tmp_char[256]; format_node_name(bg_record, tmp_char, sizeof(tmp_char)); info("going to split %s, %s", bg_record->bg_block_id, tmp_char); } if (!my_block_list) { rc = SLURM_SUCCESS; goto finished; } _split_block(block_list, new_blocks, bg_record, cnodes); rc = SLURM_SUCCESS; goto finished; } finished: if (bit_itr) list_iterator_destroy(bit_itr); FREE_NULL_BITMAP(ionodes); if (itr) list_iterator_destroy(itr); return rc; }
int main(int argc, char **argv) { int c; int count, waittime; int set_lun; int fd, retval; struct ctlstat_context ctx; /* default values */ retval = 0; waittime = 1; count = -1; memset(&ctx, 0, sizeof(ctx)); ctx.numdevs = 3; ctx.mode = CTLSTAT_MODE_STANDARD; ctx.flags |= CTLSTAT_FLAG_CPU; ctx.flags |= CTLSTAT_FLAG_FIRST_RUN; ctx.flags |= CTLSTAT_FLAG_HEADER; while ((c = getopt(argc, argv, ctlstat_opts)) != -1) { switch (c) { case 'C': ctx.flags &= ~CTLSTAT_FLAG_CPU; break; case 'c': count = atoi(optarg); break; case 'd': ctx.flags |= CTLSTAT_FLAG_DMA_TIME; break; case 'D': ctx.mode = CTLSTAT_MODE_DUMP; waittime = 30; break; case 'h': ctx.flags &= ~CTLSTAT_FLAG_HEADER; break; case 'j': ctx.mode = CTLSTAT_MODE_JSON; waittime = 30; break; case 'l': { int cur_lun; cur_lun = atoi(optarg); if (cur_lun > CTL_STAT_LUN_BITS) errx(1, "Invalid LUN number %d", cur_lun); bit_ffs(ctx.lun_mask, CTL_STAT_LUN_BITS, &set_lun); if (set_lun == -1) ctx.numdevs = 1; else ctx.numdevs++; bit_set(ctx.lun_mask, cur_lun); break; } case 'n': ctx.numdevs = atoi(optarg); break; case 't': ctx.flags |= CTLSTAT_FLAG_TOTALS; ctx.numdevs = 3; break; case 'w': waittime = atoi(optarg); break; default: retval = 1; usage(retval); exit(retval); break; } } bit_ffs(ctx.lun_mask, CTL_STAT_LUN_BITS, &set_lun); if ((F_TOTALS(&ctx)) && (set_lun != -1)) { errx(1, "Total Mode (-t) is incompatible with individual " "LUN mode (-l)"); } else if (set_lun == -1) { /* * Note that this just selects the first N LUNs to display, * but at this point we have no knoweledge of which LUN * numbers actually exist. So we may select LUNs that * aren't there. */ bit_nset(ctx.lun_mask, 0, min(ctx.numdevs - 1, CTL_STAT_LUN_BITS - 1)); } if ((fd = open(CTL_DEFAULT_DEV, O_RDWR)) == -1) err(1, "cannot open %s", CTL_DEFAULT_DEV); for (;count != 0;) { ctx.tmp_lun_stats = ctx.prev_lun_stats; ctx.prev_lun_stats = ctx.cur_lun_stats; ctx.cur_lun_stats = ctx.tmp_lun_stats; ctx.prev_time = ctx.cur_time; ctx.prev_cpu = ctx.cur_cpu; if (getstats(fd, &ctx.num_luns, &ctx.cur_lun_stats, &ctx.cur_time, &ctx.flags) != 0) errx(1, "error returned from getstats()"); switch(ctx.mode) { case CTLSTAT_MODE_STANDARD: ctlstat_standard(&ctx); break; case CTLSTAT_MODE_DUMP: ctlstat_dump(&ctx); break; case CTLSTAT_MODE_JSON: ctlstat_json(&ctx); break; default: break; } fprintf(stdout, "\n"); ctx.flags &= ~CTLSTAT_FLAG_FIRST_RUN; if (count != 1) sleep(waittime); if (count > 0) count--; } exit (retval); }
extern List setup_cluster_list_with_inx(mysql_conn_t *mysql_conn, slurmdb_job_cond_t *job_cond, void **curr_cluster) { List local_cluster_list = NULL; time_t now = time(NULL); MYSQL_RES *result = NULL; MYSQL_ROW row; hostlist_t temp_hl = NULL; hostlist_iterator_t h_itr = NULL; char *query = NULL; int dims = 0; if (!job_cond || !job_cond->used_nodes) return NULL; if (!job_cond->cluster_list || list_count(job_cond->cluster_list) != 1) { error("If you are doing a query against nodes " "you must only have 1 cluster " "you are asking for."); return NULL; } /* get the dimensions of this cluster so we know how to deal with the hostlists */ query = xstrdup_printf("select dimensions, flags from %s where " "name='%s'", cluster_table, (char *)list_peek(job_cond->cluster_list)); debug4("%d(%s:%d) query\n%s", mysql_conn->conn, THIS_FILE, __LINE__, query); if (!(result = mysql_db_query_ret(mysql_conn, query, 0))) { xfree(query); return NULL; } xfree(query); if (!(row = mysql_fetch_row(result))) { error("Couldn't get the dimensions of cluster '%s'.", (char *)list_peek(job_cond->cluster_list)); mysql_free_result(result); return NULL; } /* On a Cray System when dealing with hostlists as we are here this always needs to be 1. */ if (slurm_atoul(row[1]) & CLUSTER_FLAG_CRAY_A) dims = 1; else dims = atoi(row[0]); mysql_free_result(result); temp_hl = hostlist_create_dims(job_cond->used_nodes, dims); if (hostlist_count(temp_hl) <= 0) { error("we didn't get any real hosts to look for."); goto no_hosts; } h_itr = hostlist_iterator_create(temp_hl); query = xstrdup_printf("select cluster_nodes, time_start, " "time_end from \"%s_%s\" where node_name='' " "&& cluster_nodes !=''", (char *)list_peek(job_cond->cluster_list), event_table); if (job_cond->usage_start) { if (!job_cond->usage_end) job_cond->usage_end = now; xstrfmtcat(query, " && ((time_start < %ld) " "&& (time_end >= %ld || time_end = 0))", job_cond->usage_end, job_cond->usage_start); } if (debug_flags & DEBUG_FLAG_DB_JOB) DB_DEBUG(mysql_conn->conn, "query\n%s", query); if (!(result = mysql_db_query_ret(mysql_conn, query, 0))) { xfree(query); goto no_hosts; } xfree(query); local_cluster_list = list_create(_destroy_local_cluster); while ((row = mysql_fetch_row(result))) { char *host = NULL; int loc = 0; local_cluster_t *local_cluster = xmalloc(sizeof(local_cluster_t)); local_cluster->hl = hostlist_create_dims(row[0], dims); local_cluster->start = slurm_atoul(row[1]); local_cluster->end = slurm_atoul(row[2]); local_cluster->asked_bitmap = bit_alloc(hostlist_count(local_cluster->hl)); while ((host = hostlist_next_dims(h_itr, dims))) { if ((loc = hostlist_find( local_cluster->hl, host)) != -1) bit_set(local_cluster->asked_bitmap, loc); free(host); } hostlist_iterator_reset(h_itr); if (bit_ffs(local_cluster->asked_bitmap) != -1) { list_append(local_cluster_list, local_cluster); if (local_cluster->end == 0) { local_cluster->end = now; (*curr_cluster) = local_cluster; } else if (!(*curr_cluster) || (((local_cluster_t *)(*curr_cluster))->end < local_cluster->end)) { (*curr_cluster) = local_cluster; } } else _destroy_local_cluster(local_cluster); } mysql_free_result(result); if (!list_count(local_cluster_list)) { FREE_NULL_LIST(local_cluster_list); local_cluster_list = NULL; goto no_hosts; } no_hosts: hostlist_iterator_destroy(h_itr); hostlist_destroy(temp_hl); return local_cluster_list; }
/* * setup_cluster_nodes - get cluster record list within requested * time period with used nodes. Used for deciding whether a nodelist is * overlapping with the required nodes. */ extern cluster_nodes_t * setup_cluster_nodes(pgsql_conn_t *pg_conn, slurmdb_job_cond_t *job_cond) { DEF_VARS; cluster_nodes_t *cnodes = NULL; time_t now = time(NULL); hostlist_t temp_hl = NULL; hostlist_iterator_t h_itr = NULL; if (!job_cond || !job_cond->used_nodes) return NULL; if (!job_cond->cluster_list || list_count(job_cond->cluster_list) != 1) { error("If you are doing a query against nodes " "you must only have 1 cluster " "you are asking for."); return NULL; } temp_hl = hostlist_create(job_cond->used_nodes); if (!hostlist_count(temp_hl)) { error("we didn't get any real hosts to look for."); hostlist_destroy(temp_hl); return NULL; } query = xstrdup_printf("SELECT cluster_nodes, time_start, " "time_end FROM %s.%s WHERE node_name='' " "AND cluster_nodes !=''", (char *)list_peek(job_cond->cluster_list), event_table); if (job_cond->usage_start) { if (!job_cond->usage_end) job_cond->usage_end = now; xstrfmtcat(query, " AND ((time_start<%ld) " "AND (time_end>=%ld OR time_end=0))", job_cond->usage_end, job_cond->usage_start); } result = DEF_QUERY_RET; if (!result) { hostlist_destroy(temp_hl); return NULL; } h_itr = hostlist_iterator_create(temp_hl); cnodes = xmalloc(sizeof(cluster_nodes_t)); cnodes->cluster_list = list_create(_destroy_local_cluster); FOR_EACH_ROW { char *host = NULL; int loc = 0; local_cluster_t *local_cluster = xmalloc(sizeof(local_cluster_t)); local_cluster->hl = hostlist_create(ROW(0)); local_cluster->start = atoi(ROW(1)); local_cluster->end = atoi(ROW(2)); local_cluster->asked_bitmap = bit_alloc(hostlist_count(local_cluster->hl)); while((host = hostlist_next(h_itr))) { if ((loc = hostlist_find( local_cluster->hl, host)) != -1) bit_set(local_cluster->asked_bitmap, loc); free(host); } hostlist_iterator_reset(h_itr); if (bit_ffs(local_cluster->asked_bitmap) != -1) { list_append(cnodes->cluster_list, local_cluster); if (local_cluster->end == 0) { local_cluster->end = now; cnodes->curr_cluster = local_cluster; } } else _destroy_local_cluster(local_cluster); } END_EACH_ROW; PQclear(result); hostlist_iterator_destroy(h_itr); if (!list_count(cnodes->cluster_list)) { destroy_cluster_nodes(cnodes); cnodes = NULL; } hostlist_destroy(temp_hl); return cnodes; }