/* * Select some resources from the found tree * frt is found resource tree * prt is selected resource tree parent */ static resrc_tree_t *test_select_resources (resrc_tree_t *frt, resrc_tree_t *prt, int select) { resrc_tree_t *selected_res = NULL; if (frt) { resrc_t *resrc = resrc_tree_resrc (frt); if (!strcmp (resrc_type(resrc), "core")) { if (resrc_id (resrc) == select) resrc_stage_resrc (resrc, 1, NULL); else goto ret; } else if (!strcmp (resrc_type(resrc), "memory")) resrc_stage_resrc (resrc, 100, NULL); selected_res = resrc_tree_new (prt, resrc); if (resrc_tree_num_children (frt)) { resrc_tree_t *child = resrc_tree_list_first ( resrc_tree_children (frt)); while (child) { (void) test_select_resources (child, selected_res, select); child = resrc_tree_list_next (resrc_tree_children (frt)); } } } ret: return selected_res; }
/* returns the number of resource or resource composites found */ int64_t resrc_tree_search (resrc_t *resrc_in, resrc_reqst_t *resrc_reqst, resrc_tree_t **found_tree, bool available) { int64_t nfound = 0; resrc_tree_list_t *children = NULL; resrc_tree_t *child_tree; resrc_tree_t *new_tree = NULL; if (!resrc_in || !found_tree || !resrc_reqst) { goto ret; } if (resrc_match_resource (resrc_in, resrc_reqst, available)) { if (resrc_reqst_num_children (resrc_reqst)) { if (resrc_tree_num_children (resrc_phys_tree (resrc_in))) { new_tree = resrc_tree_new (*found_tree, resrc_in); children = resrc_tree_children (resrc_phys_tree (resrc_in)); if (match_children (children, resrc_reqst->children, new_tree, available)) { nfound = 1; resrc_reqst->nfound++; } else { resrc_tree_destroy (new_tree, false); } } } else { (void) resrc_tree_new (*found_tree, resrc_in); nfound = 1; resrc_reqst->nfound++; } } else if (resrc_tree_num_children (resrc_phys_tree (resrc_in))) { /* * This clause visits the children of the current resource * searching for a match to the resource request. The found * tree must be extended to include this intermediate * resource. * * This also allows the resource request to be sparsely * defined. E.g., it might only stipulate a node with 4 cores * and omit the intervening socket. */ if (*found_tree) new_tree = resrc_tree_new (*found_tree, resrc_in); else { new_tree = resrc_tree_new (NULL, resrc_in); *found_tree = new_tree; } children = resrc_tree_children (resrc_phys_tree (resrc_in)); child_tree = resrc_tree_list_first (children); while (child_tree) { nfound += resrc_tree_search (resrc_tree_resrc (child_tree), resrc_reqst, &new_tree, available); child_tree = resrc_tree_list_next (children); } } ret: return nfound; }
static int rsreader_set_granular_digest (resrc_api_ctx_t *rsapi, machs_t *machs, resrc_tree_t *rt, char **err_str) { char *e_str = NULL; const char *digest = NULL; int nsocks = 0, ncs = 0; int rc = -1; resrc_t *r = NULL; if (rt) { r = resrc_tree_resrc (rt); if (strcmp (resrc_type (r), "node")) { if (resrc_tree_num_children (rt)) { resrc_tree_list_t *children = resrc_tree_children (rt); if (children) { resrc_tree_t *child = resrc_tree_list_first (children); while (child) { rc = rsreader_set_granular_digest (rsapi, machs, child, err_str); if (rc) break; child = resrc_tree_list_next (children); } } } } else if (!find_all_sockets_cores (rsapi, r, &nsocks, &ncs)) { /* matches based on the hostname, number of sockets and * cores. This linking isn't used by hwloc reader so * count-based matching is okay */ digest = rs2rank_tab_eq_by_count(machs, resrc_name (r), nsocks, ncs); if (digest) { (void) resrc_set_digest (r, xasprintf ("%s", digest)); rc = 0; } else e_str = xasprintf ("%s: Can't find a matching resrc for " "<%s,%d,%d>", __FUNCTION__, resrc_name (r), nsocks, ncs); } } if (err_str) *err_str = e_str; else free (e_str); return rc; }
/* * cycles through all of the resource children and returns the number of * requested resources found */ static int64_t match_child (resrc_tree_list_t *r_trees, resrc_reqst_t *resrc_reqst, resrc_tree_t *found_parent, bool available) { int64_t nfound = 0; resrc_t *resrc = NULL; resrc_tree_t *resrc_tree = NULL; resrc_tree = resrc_tree_list_first (r_trees); while (resrc_tree) { resrc = resrc_tree_resrc (resrc_tree); nfound += resrc_tree_search (resrc, resrc_reqst, &found_parent, available); resrc_tree = resrc_tree_list_next (r_trees); } return nfound; }
/* * cycles through all of the resource children and returns true when * the requested quantity of resources have been selected. */ static bool select_child (flux_t *h, resrc_tree_list_t *children, resrc_reqst_t *child_reqst, resrc_tree_t *selected_parent) { resrc_tree_t *child_tree = NULL; bool selected = false; child_tree = resrc_tree_list_first (children); while (child_tree) { if (select_resources (h, child_tree, child_reqst, selected_parent) && (resrc_reqst_nfound (child_reqst) >= resrc_reqst_reqrd_qty (child_reqst))) { selected = true; break; } child_tree = resrc_tree_list_next (children); } return selected; }
static int rsreader_set_node_digest (machs_t *machs, resrc_tree_t *rt) { const char *digest = NULL; int rc = -1; resrc_t *r = NULL; if (rt) { r = resrc_tree_resrc (rt); if (strcmp (resrc_type (r), "node")) { if (resrc_tree_num_children (rt)) { resrc_tree_list_t *children = resrc_tree_children (rt); if (children) { resrc_tree_t *child = resrc_tree_list_first (children); while (child) { rc = rsreader_set_node_digest (machs, child); if (rc) break; child = resrc_tree_list_next (children); } } } } else { /* Use the digest from the first resource partition of * the first node in the machine table */ digest = rs2rank_tab_eq_by_none (machs); if (digest) { (void) resrc_set_digest (r, xasprintf ("%s", digest)); rc = 0; } } } return rc; }
/* * select_resources() selects from the set of resource candidates the * best resources for the job. * * Inputs: found_tree - tree of resource tree candidates * resrc_reqst - the resources the job requests * selected_parent - parent of the selected resource tree * Returns: a resource tree of however many resources were selected */ resrc_tree_t *select_resources (flux_t *h, resrc_tree_t *found_tree, resrc_reqst_t *resrc_reqst, resrc_tree_t *selected_parent) { resrc_t *resrc; resrc_tree_list_t *children = NULL; resrc_tree_t *child_tree; resrc_tree_t *selected_tree = NULL; if (!resrc_reqst) { flux_log (h, LOG_ERR, "%s: called with empty request", __FUNCTION__); return NULL; } /* * A start time of zero is used to restrict the search to now * (appropriate for FCFS) and prevent any search into the future. */ if (resrc_reqst_set_starttime (resrc_reqst, 0) || resrc_reqst_set_endtime (resrc_reqst, 0)) return NULL; resrc = resrc_tree_resrc (found_tree); if (resrc_match_resource (resrc, resrc_reqst, true)) { if (resrc_reqst_num_children (resrc_reqst)) { if (resrc_tree_num_children (found_tree)) { selected_tree = resrc_tree_new (selected_parent, resrc); if (select_children (h, resrc_tree_children (found_tree), resrc_reqst_children (resrc_reqst), selected_tree)) { resrc_stage_resrc (resrc, resrc_reqst_reqrd_size (resrc_reqst), resrc_reqst_graph_reqs (resrc_reqst)); resrc_reqst_add_found (resrc_reqst, 1); flux_log (h, LOG_DEBUG, "selected %s", resrc_name (resrc)); } else { resrc_tree_destroy (selected_tree, false); } } } else { selected_tree = resrc_tree_new (selected_parent, resrc); resrc_stage_resrc (resrc, resrc_reqst_reqrd_size (resrc_reqst), resrc_reqst_graph_reqs (resrc_reqst)); resrc_reqst_add_found (resrc_reqst, 1); flux_log (h, LOG_DEBUG, "selected %s", resrc_name (resrc)); } } else if (resrc_tree_num_children (found_tree)) { /* * This clause visits the children of the current resource * searching for a match to the resource request. The selected * tree must be extended to include this intermediate * resource. * * This also allows the resource request to be sparsely * defined. E.g., it might only stipulate a node with 4 cores * and omit the intervening socket. */ selected_tree = resrc_tree_new (selected_parent, resrc); children = resrc_tree_children (found_tree); child_tree = resrc_tree_list_first (children); while (child_tree) { if (select_resources (h, child_tree, resrc_reqst, selected_tree) && resrc_reqst_nfound (resrc_reqst) >= resrc_reqst_reqrd_qty (resrc_reqst)) break; child_tree = resrc_tree_list_next (children); } } return selected_tree; }