/** * @brief * do an initial check to see if a resresv can fit into a node partition * based on the meta data we keep. * * @param[in] policy - policy info * @param[in] np - node partition to check * @param[in] resresv - job/resv to see if it can fit * @param[in] flags - check_flags * COMPARE_TOTAL - compare with resources_available value * RETURN_ALL_ERR - return all the errors, not just the first failure * @param[in] err - schd_error structure to return why job/resv can't fit * * @return int * @retval 1 : can fit * @retval 0 : can't fit * @retval -1 : on error */ int resresv_can_fit_nodepart(status *policy, node_partition *np, resource_resv *resresv, int flags, schd_error *err) { int i; schd_error *prev_err = NULL; int can_fit = 1; int pass_flags; resource_req *req; selspec *spec = NULL; place *pl = NULL; if (policy == NULL || np == NULL || resresv == NULL || err == NULL) return -1; pass_flags = flags|UNSET_RES_ZERO; /* Check 1: Based on the flag check if there are any nodes available or if * they are free. */ if (flags & COMPARE_TOTAL) { /* Check that node partition must have one or more nodes inside it */ if (np->tot_nodes == 0) { set_schd_error_codes(err, NEVER_RUN, NO_TOTAL_NODES); if ((flags & RETURN_ALL_ERR)) { can_fit = 0; err->next = new_schd_error(); prev_err = err; err = err->next; } else return 0; } } else { /* Check is there at least 1 node in the free state */ if (np->free_nodes == 0) { set_schd_error_codes(err, NOT_RUN, NO_FREE_NODES); if ((flags & RETURN_ALL_ERR)) { can_fit = 0; err->next = new_schd_error(); prev_err = err; err = err->next; } else return 0; } } /* Check 2: v/scatter - If we're scattering or requesting exclusive nodes * we know we need at least as many nodes as requested chunks */ if (resresv->place_spec->scatter || resresv->place_spec->vscatter) { int nodect; enum sched_error error_code; enum schd_err_status status_code; if ( (flags & COMPARE_TOTAL) ) { nodect = np->tot_nodes; error_code = NO_TOTAL_NODES; status_code = NEVER_RUN; } else { nodect = np->free_nodes; error_code = NO_FREE_NODES; status_code = NOT_RUN; } if (nodect < resresv->select->total_chunks) { set_schd_error_codes(err, status_code, error_code); if ((flags & RETURN_ALL_ERR)) { can_fit = 0; err->next = new_schd_error(); prev_err = err; err = err->next; } else return 0; } } /* Check 3: Job Wide RASSN resources(e.g., ncpus, mem). We only check * resources that the server has summed over the select statement. We * know these came from the nodes so should be checked on the nodes. Other * resources are for server/queue and so we ignore them here */ if (resresv->is_job && resresv->job != NULL && resresv->job->resreq_rel != NULL) req = resresv->job->resreq_rel; else req = resresv->resreq; if (check_avail_resources(np->res, req, pass_flags, policy->resdef_to_check_rassn_select, INSUFFICIENT_RESOURCE, err) == 0) { if ((flags & RETURN_ALL_ERR)) { can_fit = 0; err->next = new_schd_error(); prev_err = err; err = err->next; } else return 0; } /* Check 4: Chunk level resources: Check each chunk compared to the meta data * This is mostly for non-consumables. Booleans are always honored * on nodes regardless if they are in the resources line. This is a * grandfathering in from the old nodespec properties. */ /* The call to get_resresv_spec is needed here because we are checking for resources on each * chunk. For jobs that already have execselect specification defined we only need to * traverse through those chunks. * get_resresv_spec sets the spec value to execselect/select depending on whether execselect * was set or not. */ get_resresv_spec(resresv, &spec, &pl); for (i = 0; spec->chunks[i] != NULL; i++) { if (check_avail_resources(np->res, spec->chunks[i]->req, pass_flags | CHECK_ALL_BOOLS, policy->resdef_to_check, INSUFFICIENT_RESOURCE, err) == 0) { if ((flags & RETURN_ALL_ERR)) { can_fit = 0; err->next = new_schd_error(); prev_err = err; err = err->next; } else return 0; } } if((flags&RETURN_ALL_ERR)) { if(prev_err != NULL) { prev_err->next = NULL; free(err); } return can_fit; } return 1; }
/** * @brief * do an initial check to see if a resresv can fit into a node partition * based on the meta data we keep. * * @param[in] policy - policy info * @param[in] np - node partition to check * @param[in] resresv - job/resv to see if it can fit * @param[in] flags - check_flags * COMPARE_TOTAL - compare with resources_available value * RETURN_ALL_ERR - return all the errors, not just the first failure * @param[in] err - schd_error structure to return why job/resv can't fit * * @return int * @retval 1 : can fit * @retval 0 : can't fit * @retval -1 : on error */ int resresv_can_fit_nodepart(status *policy, node_partition *np, resource_resv *resresv, int flags, schd_error *err) { int i; schd_error *prev_err = NULL; int can_fit = 1; int pass_flags; if (policy == NULL || np == NULL || resresv == NULL || err == NULL) return -1; pass_flags = flags|UNSET_RES_ZERO; /* Check 1: is there at least 1 node in the free state */ if (!(flags & COMPARE_TOTAL) && np->free_nodes == 0) { set_schd_error_codes(err, NOT_RUN, NO_FREE_NODES); if ((flags & RETURN_ALL_ERR)) { can_fit = 0; err->next = new_schd_error(); prev_err = err; err = err->next; } else return 0; } /* Check 2: v/scatter - If we're scattering or requesting exclusive nodes * we know we need at least as many nodes as requested chunks */ if (resresv->place_spec->scatter || resresv->place_spec->vscatter) { int nodect; enum sched_error error_code; enum schd_err_status status_code; if ( (flags & COMPARE_TOTAL) ) { nodect = np->tot_nodes; error_code = NO_TOTAL_NODES; status_code = NEVER_RUN; } else { nodect = np->free_nodes; error_code = NO_FREE_NODES; status_code = NOT_RUN; } if (nodect < resresv->select->total_chunks) { set_schd_error_codes(err, status_code, error_code); if ((flags & RETURN_ALL_ERR)) { can_fit = 0; err->next = new_schd_error(); prev_err = err; err = err->next; } else return 0; } } /* Check 3: Job Wide RASSN resources(e.g., ncpus, mem). We only check * resources that the server has summed over the select statement. We * know these came from the nodes so should be checked on the nodes. Other * resources are for server/queue and so we ignore them here */ if (check_avail_resources(np->res, resresv->resreq, pass_flags, policy->resdef_to_check_rassn, INSUFFICIENT_RESOURCE, err) == 0) { if ((flags & RETURN_ALL_ERR)) { can_fit = 0; err->next = new_schd_error(); prev_err = err; err = err->next; } else return 0; } /* Check 4: Chunk level resources: Check each chunk compared to the meta data * This is mostly for non-consumables. Booleans are always honored * on nodes regardless if they are in the resources line. This is a * grandfathering in from the old nodespec properties. */ for (i = 0; resresv->select->chunks[i] != NULL; i++) { if (check_avail_resources(np->res, resresv->select->chunks[i]->req, pass_flags | CHECK_ALL_BOOLS, policy->resdef_to_check, INSUFFICIENT_RESOURCE, err) == 0) { if ((flags & RETURN_ALL_ERR)) { can_fit = 0; err->next = new_schd_error(); prev_err = err; err = err->next; } else return 0; } } if((flags&RETURN_ALL_ERR)) { if(prev_err != NULL) { prev_err->next = NULL; free(err); } return can_fit; } return 1; }