Beispiel #1
0
/*
 * find_resources() identifies the all of the resource candidates for
 * the job.  The set of resources returned could be more than the job
 * requires.  A later call to select_resources() will cull this list
 * down to the most appropriate set for the job.
 *
 * Inputs:  resrcs      - hash table of all resources
 *          resrc_reqst - the resources the job requests
 * Returns: nfound      - the number of resources found
 *          found_tree  - a resource tree containing resources that satisfy the
 *                        job's request or NULL if none are found
 */
int64_t find_resources (flux_t *h, resrc_t *resrc, resrc_reqst_t *resrc_reqst,
                        resrc_tree_t **found_tree)
{
    int64_t nfound = 0;

    if (!resrc || !resrc_reqst) {
        flux_log (h, LOG_ERR, "%s: invalid arguments", __FUNCTION__);
        goto ret;
    }
    /*
     * 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))
        goto ret;

    *found_tree = NULL;
    nfound = resrc_tree_search (resrc, resrc_reqst, found_tree, true);

    if (!nfound && *found_tree) {
        resrc_tree_destroy (*found_tree, false);
        *found_tree = NULL;
    }
ret:
    return nfound;
}
Beispiel #2
0
int resrc_reqst_set_endtime (resrc_reqst_t *resrc_reqst, int64_t time)
{
    if (resrc_reqst) {
        resrc_reqst->endtime = time;
        if (resrc_reqst_num_children (resrc_reqst)) {
            resrc_reqst_t *child = resrc_reqst_list_first
                (resrc_reqst->children);
            while (child) {
                resrc_reqst_set_endtime (child, time);
                child = resrc_reqst_list_next (resrc_reqst->children);
            }
        }
        return 0;
    }
    return -1;
}
Beispiel #3
0
/*
 * 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;
}
Beispiel #4
0
/*
 * reserve_resources() reserves resources for the specified job id.
 * Unlike the FCFS version where selected_tree provides the tree of
 * resources to reserve, this backfill version will search into the
 * future to find a time window when all of the required resources are
 * available, reserve those, and return the pointer to the selected
 * tree.
 */
int reserve_resources (flux_t h, resrc_tree_t **selected_tree, int64_t job_id,
                       int64_t starttime, int64_t walltime, resrc_t *resrc,
                       resrc_reqst_t *resrc_reqst)
{
    int rc = -1;
    int64_t *completion_time = NULL;
    int64_t nfound = 0;
    int64_t prev_completion_time = -1;
    resrc_tree_t *found_tree = NULL;

    if (reservation_depth > 0 && (curr_reservation_depth >= reservation_depth)) {
        goto ret;
    } else if (!resrc || !resrc_reqst) {
        flux_log (h, LOG_ERR, "%s: invalid arguments", __FUNCTION__);
        goto ret;
    }

    if (*selected_tree) {
        resrc_tree_destroy (*selected_tree, false);
        *selected_tree = NULL;
    }
    zlist_sort (completion_times, compare_int64_ascending);

    for (completion_time = zlist_first (completion_times);
         completion_time;
         completion_time = zlist_next (completion_times)) {
        /* Purge past times from consideration */
        if (*completion_time < starttime) {
            zlist_remove (completion_times, completion_time);
            continue;
        }
        /* Don't test the same time multiple times */
        if (prev_completion_time == *completion_time)
            continue;

        resrc_reqst_set_starttime (resrc_reqst, *completion_time + 1);
        resrc_reqst_set_endtime (resrc_reqst, *completion_time + 1 + walltime);
        flux_log (h, LOG_DEBUG, "Attempting to reserve %"PRId64" nodes for job "
                  "%"PRId64" at time %"PRId64"",
                  resrc_reqst_reqrd_qty (resrc_reqst), job_id,
                  *completion_time + 1);

        nfound = resrc_tree_search (resrc, resrc_reqst, &found_tree, true);
        if (nfound >= resrc_reqst_reqrd_qty (resrc_reqst)) {
            *selected_tree = select_resources (h, found_tree, resrc_reqst, NULL);
            resrc_tree_destroy (found_tree, false);
            if (*selected_tree) {
                rc = resrc_tree_reserve (*selected_tree, job_id,
                                         *completion_time + 1,
                                         *completion_time + 1 + walltime);
                if (rc) {
                    resrc_tree_destroy (*selected_tree, false);
                    *selected_tree = NULL;
                } else {
                    curr_reservation_depth++;
                    flux_log (h, LOG_DEBUG, "Reserved %"PRId64" nodes for job "
                              "%"PRId64" from %"PRId64" to %"PRId64"",
                              resrc_reqst_reqrd_qty (resrc_reqst), job_id,
                              *completion_time + 1,
                              *completion_time + 1 + walltime);
                }
                break;
            }
        }
        prev_completion_time = *completion_time;
    }
ret:
    return rc;
}