Blame src/hwloc/netloc/architecture.c

Packit Service c5cf8c
/*
Packit Service c5cf8c
 * Copyright © 2016-2017 Inria.  All rights reserved.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * $COPYRIGHT$
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Additional copyrights may follow
Packit Service c5cf8c
 * See COPYING in top-level directory.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * $HEADER$
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
#define _GNU_SOURCE         /* See feature_test_macros(7) */
Packit Service c5cf8c
#include <private/netloc.h>
Packit Service c5cf8c
#include <netloc.h>
Packit Service c5cf8c
Packit Service c5cf8c
typedef struct netloc_analysis_data_t {
Packit Service c5cf8c
    int level;
Packit Service c5cf8c
    void *userdata;
Packit Service c5cf8c
} netloc_analysis_data;
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
static int partition_topology_to_tleaf(netloc_topology_t *topology,
Packit Service c5cf8c
        int partition, int num_cores, netloc_arch_t *arch);
Packit Service c5cf8c
static netloc_arch_tree_t *tree_merge(netloc_arch_tree_t *main,
Packit Service c5cf8c
        netloc_arch_tree_t *sub);
Packit Service c5cf8c
static int netloc_arch_tree_destruct(netloc_arch_tree_t *tree);
Packit Service c5cf8c
static int netloc_arch_node_destruct(netloc_arch_node_t *arch_node);
Packit Service c5cf8c
static netloc_arch_node_t *netloc_arch_node_construct(void);
Packit Service c5cf8c
Packit Service c5cf8c
#define checked_fscanf(f, w, str, failed) \
Packit Service c5cf8c
    if (fscanf(f, " %1023s", w) != 1) { \
Packit Service c5cf8c
        fprintf(stderr, "Cannot read %s\n", str); \
Packit Service c5cf8c
        perror("fscanf"); \
Packit Service c5cf8c
        goto ERROR; \
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
/* Complete the topology to have a complete balanced tree  */
Packit Service c5cf8c
void netloc_arch_tree_complete(netloc_arch_tree_t *tree, UT_array **down_degrees_by_level,
Packit Service c5cf8c
        int num_hosts, int **parch_idx)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int num_levels = tree->num_levels;
Packit Service c5cf8c
    NETLOC_int *max_degrees = tree->degrees;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Complete the tree by inserting nodes */
Packit Service c5cf8c
    for (int l = 0; l < num_levels-1; l++) { // from the root to the leaves
Packit Service c5cf8c
        int num_degrees = utarray_len(down_degrees_by_level[l]);
Packit Service c5cf8c
        int *degrees = (int *)down_degrees_by_level[l]->d;
Packit Service c5cf8c
        NETLOC_int max_degree = max_degrees[l];
Packit Service c5cf8c
Packit Service c5cf8c
        unsigned int down_level_idx = 0;
Packit Service c5cf8c
        UT_array *down_level_degrees = down_degrees_by_level[l+1];
Packit Service c5cf8c
        NETLOC_int down_level_max_degree = max_degrees[l+1];
Packit Service c5cf8c
        for (int d = 0; d < num_degrees; d++) {
Packit Service c5cf8c
            int degree = degrees[d];
Packit Service c5cf8c
            if (degree > 0) {
Packit Service c5cf8c
                down_level_idx += degree;
Packit Service c5cf8c
                if (degree < max_degree) {
Packit Service c5cf8c
                    int missing_degree = (degree-max_degree)*down_level_max_degree;
Packit Service c5cf8c
                    utarray_insert(down_level_degrees, &missing_degree, down_level_idx);
Packit Service c5cf8c
                    down_level_idx++;
Packit Service c5cf8c
                }
Packit Service c5cf8c
            } else {
Packit Service c5cf8c
                int missing_degree = degree*down_level_max_degree;
Packit Service c5cf8c
                utarray_insert(down_level_degrees, &missing_degree, down_level_idx);
Packit Service c5cf8c
                down_level_idx++;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* Indices for the list of hosts, in the complete architecture */
Packit Service c5cf8c
    int num_degrees = utarray_len(down_degrees_by_level[num_levels-1]);
Packit Service c5cf8c
    int *degrees = (int *)down_degrees_by_level[num_levels-1]->d;
Packit Service c5cf8c
    NETLOC_int max_degree = max_degrees[num_levels-1];
Packit Service c5cf8c
    int ghost_idx = 0;
Packit Service c5cf8c
    int idx = 0;
Packit Service c5cf8c
    int *arch_idx = (int *)malloc(sizeof(int[num_hosts]));
Packit Service c5cf8c
    for (int d = 0; d < num_degrees; d++) {
Packit Service c5cf8c
        int degree = degrees[d];
Packit Service c5cf8c
        int diff;
Packit Service c5cf8c
Packit Service c5cf8c
        if (degree > 0) {
Packit Service c5cf8c
            diff = max_degree-degree;
Packit Service c5cf8c
        } else {
Packit Service c5cf8c
            diff = -degree;
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        for (int i = 0; i < degree; i++) {
Packit Service c5cf8c
            arch_idx[idx++] = ghost_idx++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        ghost_idx += diff;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    *parch_idx = arch_idx;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
NETLOC_int netloc_arch_tree_num_leaves(netloc_arch_tree_t *tree)
Packit Service c5cf8c
{
Packit Service c5cf8c
    NETLOC_int num_leaves = 1;
Packit Service c5cf8c
    for (int l = 0; l < tree->num_levels; l++) {
Packit Service c5cf8c
        num_leaves *= tree->degrees[l];
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return num_leaves;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static int get_current_resources(int *pnum_nodes, char ***pnodes, int **pslot_idx,
Packit Service c5cf8c
        int **pslot_list, int **prank_list)
Packit Service c5cf8c
{
Packit Service c5cf8c
    char *filename = getenv("NETLOC_CURRENTSLOTS");
Packit Service c5cf8c
    char word[1024];
Packit Service c5cf8c
    char *end_word;
Packit Service c5cf8c
    int *slot_list = NULL;
Packit Service c5cf8c
    int *rank_list = NULL;
Packit Service c5cf8c
    int *slot_idx = NULL;
Packit Service c5cf8c
    char **nodes = NULL;
Packit Service c5cf8c
Packit Service c5cf8c
    if (!filename) {
Packit Service c5cf8c
        fprintf(stderr, "You need to set NETLOC_CURRENTSLOTS\n");
Packit Service c5cf8c
        return NETLOC_ERROR;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    FILE *file = fopen(filename, "r");
Packit Service c5cf8c
    if (!file) {
Packit Service c5cf8c
        perror("fopen");
Packit Service c5cf8c
        return NETLOC_ERROR;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    checked_fscanf(file, word, "num_nodes", failed);
Packit Service c5cf8c
Packit Service c5cf8c
    int num_nodes;
Packit Service c5cf8c
    num_nodes = strtol(word, &end_word, 10);
Packit Service c5cf8c
    if (*word == '\0' || *end_word != '\0' || num_nodes <= 0) {
Packit Service c5cf8c
        fprintf(stderr, "Oups: incorrect number of nodes (%d) in \"%s\"\n",
Packit Service c5cf8c
                num_nodes, word);
Packit Service c5cf8c
        goto ERROR;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    nodes = (char **)malloc(sizeof(char *[num_nodes]));
Packit Service c5cf8c
    for (int n = 0; n < num_nodes; n++) {
Packit Service c5cf8c
        checked_fscanf(file, word, "node", failed);
Packit Service c5cf8c
        nodes[n] = strdup(word);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    slot_idx = (int *)malloc(sizeof(int[num_nodes+1]));
Packit Service c5cf8c
    slot_idx[0] = 0;
Packit Service c5cf8c
    for (int n = 0; n < num_nodes; n++) {
Packit Service c5cf8c
        checked_fscanf(file, word, "slot index", failed);
Packit Service c5cf8c
Packit Service c5cf8c
        int slot_index = strtol(word, &end_word, 10);
Packit Service c5cf8c
        if (*word == '\0' || *end_word != '\0' || num_nodes <= 0) {
Packit Service c5cf8c
            fprintf(stderr, "Oups: incorrect slot index (%d) in \"%s\"\n",
Packit Service c5cf8c
                    slot_index, word);
Packit Service c5cf8c
            goto ERROR;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        slot_idx[n+1] = slot_idx[n]+slot_index;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    slot_list = (int *)malloc(sizeof(int[slot_idx[num_nodes]]));
Packit Service c5cf8c
    rank_list = (int *)malloc(sizeof(int[slot_idx[num_nodes]]));
Packit Service c5cf8c
    for (int s = 0; s < slot_idx[num_nodes]; s++) {
Packit Service c5cf8c
        checked_fscanf(file, word, "slot number", failed);
Packit Service c5cf8c
        slot_list[s] = strtol(word, &end_word, 10);
Packit Service c5cf8c
        if (*word == '\0' || *end_word != '\0' || num_nodes <= 0) {
Packit Service c5cf8c
            fprintf(stderr, "Oups: incorrect slot number (%d) in \"%s\"\n",
Packit Service c5cf8c
                    slot_list[s], word);
Packit Service c5cf8c
            goto ERROR;
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        checked_fscanf(file, word, "rank number", failed);
Packit Service c5cf8c
        rank_list[s] = strtol(word, &end_word, 10);
Packit Service c5cf8c
        if (*word == '\0' || *end_word != '\0' || num_nodes <= 0) {
Packit Service c5cf8c
            fprintf(stderr, "Oups: incorrect rank number (%d) in \"%s\"\n",
Packit Service c5cf8c
                    rank_list[s], word);
Packit Service c5cf8c
            goto ERROR;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    *pnum_nodes = num_nodes;
Packit Service c5cf8c
    *pnodes = nodes;
Packit Service c5cf8c
    *pslot_idx = slot_idx;
Packit Service c5cf8c
    *pslot_list = slot_list;
Packit Service c5cf8c
    *prank_list = rank_list;
Packit Service c5cf8c
Packit Service c5cf8c
    fclose(file);
Packit Service c5cf8c
Packit Service c5cf8c
    return NETLOC_SUCCESS;
Packit Service c5cf8c
Packit Service c5cf8c
ERROR:
Packit Service c5cf8c
    fclose(file);
Packit Service c5cf8c
    free(nodes);
Packit Service c5cf8c
    free(slot_idx);
Packit Service c5cf8c
    free(slot_list);
Packit Service c5cf8c
    free(rank_list);
Packit Service c5cf8c
    return NETLOC_ERROR;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int netloc_arch_set_current_resources(netloc_arch_t *arch)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
    int num_nodes;
Packit Service c5cf8c
    char **nodenames;
Packit Service c5cf8c
    int *slot_idx;
Packit Service c5cf8c
    int *slot_list;
Packit Service c5cf8c
    int *rank_list;
Packit Service c5cf8c
Packit Service c5cf8c
    ret = get_current_resources(&num_nodes, &nodenames, &slot_idx, &slot_list,
Packit Service c5cf8c
            &rank_list);
Packit Service c5cf8c
Packit Service c5cf8c
    if (ret != NETLOC_SUCCESS || num_nodes <= 0)
Packit Service c5cf8c
        assert(0); // XXX
Packit Service c5cf8c
Packit Service c5cf8c
    NETLOC_int *current_nodes = NULL;
Packit Service c5cf8c
Packit Service c5cf8c
    if (!arch->has_slots) {
Packit Service c5cf8c
        current_nodes = (NETLOC_int *) malloc(sizeof(NETLOC_int[num_nodes]));
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    netloc_arch_node_t **arch_node_list = (netloc_arch_node_t **)
Packit Service c5cf8c
        malloc(sizeof(netloc_arch_node_t *[num_nodes]));
Packit Service c5cf8c
    netloc_node_t **node_list = (netloc_node_t **)
Packit Service c5cf8c
        malloc(sizeof(netloc_node_t *[num_nodes]));
Packit Service c5cf8c
    for (int n = 0; n < num_nodes; n++) {
Packit Service c5cf8c
        netloc_arch_node_t *arch_node;
Packit Service c5cf8c
        HASH_FIND_STR(arch->nodes_by_name, nodenames[n], arch_node);
Packit Service c5cf8c
        if (!arch_node) {
Packit Service c5cf8c
            ret = NETLOC_ERROR;
Packit Service c5cf8c
            goto ERROR;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        arch_node_list[n] = arch_node;
Packit Service c5cf8c
        node_list[n] = arch_node->node;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    ret = netloc_topology_read_hwloc(arch->topology, num_nodes, node_list);
Packit Service c5cf8c
    if( NETLOC_SUCCESS != ret ) {
Packit Service c5cf8c
        goto ERROR;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    int constant_num_slots = 0;
Packit Service c5cf8c
    for (int n = 0; n < num_nodes; n++) {
Packit Service c5cf8c
        netloc_arch_node_t *node = arch_node_list[n];
Packit Service c5cf8c
Packit Service c5cf8c
        ret = netloc_arch_node_get_hwloc_info(node);
Packit Service c5cf8c
        if (ret != NETLOC_SUCCESS)
Packit Service c5cf8c
            goto ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
        if (!arch->has_slots) {
Packit Service c5cf8c
            current_nodes[n] = node->idx_in_topo;
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        int num_slots = slot_idx[n+1]-slot_idx[n];
Packit Service c5cf8c
        node->num_current_slots = num_slots;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Nodes with different number of slots are not handled yet, because we
Packit Service c5cf8c
         * build the scotch architecture without taking account of the
Packit Service c5cf8c
         * available cores inside nodes, and Scotch is not able to weight the
Packit Service c5cf8c
         * nodes */
Packit Service c5cf8c
        if (!arch->has_slots) {
Packit Service c5cf8c
            if (constant_num_slots) {
Packit Service c5cf8c
                if (constant_num_slots != num_slots) {
Packit Service c5cf8c
                    fprintf(stderr, "Oups: the same number of cores by node is needed!\n");
Packit Service c5cf8c
                    assert(constant_num_slots == num_slots);
Packit Service c5cf8c
                }
Packit Service c5cf8c
            } else {
Packit Service c5cf8c
                constant_num_slots = num_slots;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        node->current_slots = (NETLOC_int *)
Packit Service c5cf8c
            malloc(sizeof(NETLOC_int[num_slots]));
Packit Service c5cf8c
        NETLOC_int num_leaves = netloc_arch_tree_num_leaves(node->slot_tree);
Packit Service c5cf8c
        node->slot_ranks = (int *)
Packit Service c5cf8c
            malloc(sizeof(int[num_leaves]));
Packit Service c5cf8c
Packit Service c5cf8c
        for (int s = slot_idx[n]; s < slot_idx[n+1]; s++) {
Packit Service c5cf8c
            int slot = slot_list[s];
Packit Service c5cf8c
            node->current_slots[s-slot_idx[n]] = node->slot_idx[slot];
Packit Service c5cf8c
            node->slot_ranks[node->slot_idx[slot]] = rank_list[s];
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (!arch->has_slots) {
Packit Service c5cf8c
        arch->num_current_hosts = num_nodes;
Packit Service c5cf8c
        arch->current_hosts = current_nodes;
Packit Service c5cf8c
        arch->arch.global_tree = arch->arch.node_tree;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Build nodes_by_idx */
Packit Service c5cf8c
        NETLOC_int tree_size = netloc_arch_tree_num_leaves(arch->arch.node_tree);
Packit Service c5cf8c
        netloc_arch_node_slot_t *nodes_by_idx = (netloc_arch_node_slot_t *)
Packit Service c5cf8c
            malloc(sizeof(netloc_arch_node_slot_t[tree_size]));
Packit Service c5cf8c
        for (int n = 0; n < num_nodes; n++) {
Packit Service c5cf8c
            netloc_arch_node_t *node = arch_node_list[n];
Packit Service c5cf8c
            nodes_by_idx[node->idx_in_topo].node = node;
Packit Service c5cf8c
            nodes_by_idx[node->idx_in_topo].slot = -1;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        arch->node_slot_by_idx = nodes_by_idx;
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        int num_hosts = slot_idx[num_nodes];
Packit Service c5cf8c
        NETLOC_int *current_hosts = (NETLOC_int *)
Packit Service c5cf8c
            malloc(sizeof(NETLOC_int[num_hosts]));
Packit Service c5cf8c
        /* Add the slot trees to the node tree */
Packit Service c5cf8c
Packit Service c5cf8c
        /* Check that each slot tree has the same size */
Packit Service c5cf8c
        int slot_tree_size = 0;
Packit Service c5cf8c
        for (int n = 0; n < num_nodes; n++) {
Packit Service c5cf8c
            netloc_arch_node_t *node = arch_node_list[n];
Packit Service c5cf8c
            int current_size = netloc_arch_tree_num_leaves(node->slot_tree);
Packit Service c5cf8c
            if (!slot_tree_size) {
Packit Service c5cf8c
                slot_tree_size = current_size;
Packit Service c5cf8c
            } else {
Packit Service c5cf8c
                if (slot_tree_size != current_size) {
Packit Service c5cf8c
                    assert(0);
Packit Service c5cf8c
                }
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        int current_host_idx = 0;
Packit Service c5cf8c
        int node_tree_size = netloc_arch_tree_num_leaves(arch->arch.node_tree);
Packit Service c5cf8c
        int global_tree_size = node_tree_size*slot_tree_size;
Packit Service c5cf8c
        netloc_arch_node_slot_t *nodes_by_idx = (netloc_arch_node_slot_t *)
Packit Service c5cf8c
            malloc(sizeof(netloc_arch_node_slot_t[global_tree_size]));
Packit Service c5cf8c
        for (int n = 0; n < num_nodes; n++) {
Packit Service c5cf8c
            netloc_arch_node_t *node = arch_node_list[n];
Packit Service c5cf8c
            for (int s = slot_idx[n]; s < slot_idx[n+1]; s++) {
Packit Service c5cf8c
                int slot_rank = s-slot_idx[n];
Packit Service c5cf8c
                int topo_idx = node->idx_in_topo*slot_tree_size +
Packit Service c5cf8c
                    node->slot_idx[slot_rank];
Packit Service c5cf8c
                nodes_by_idx[topo_idx].node = node;
Packit Service c5cf8c
                nodes_by_idx[topo_idx].slot = slot_rank;
Packit Service c5cf8c
                current_hosts[current_host_idx++] = topo_idx;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        arch->num_current_hosts = current_host_idx;
Packit Service c5cf8c
        arch->current_hosts = current_hosts;
Packit Service c5cf8c
        arch->node_slot_by_idx = nodes_by_idx;
Packit Service c5cf8c
Packit Service c5cf8c
        netloc_arch_tree_t *new_tree =
Packit Service c5cf8c
            tree_merge(arch->arch.node_tree, arch_node_list[0]->slot_tree);
Packit Service c5cf8c
        netloc_arch_tree_destruct(arch->arch.node_tree);
Packit Service c5cf8c
        arch->arch.global_tree = new_tree;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
ERROR:
Packit Service c5cf8c
    for (int n = 0; n < num_nodes; n++) {
Packit Service c5cf8c
        free(nodenames[n]);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    free(nodenames);
Packit Service c5cf8c
    free(slot_idx);
Packit Service c5cf8c
    free(slot_list);
Packit Service c5cf8c
    free(rank_list);
Packit Service c5cf8c
    free(arch_node_list);
Packit Service c5cf8c
    free(node_list);
Packit Service c5cf8c
Packit Service c5cf8c
    if (ret == NETLOC_SUCCESS)
Packit Service c5cf8c
        return ret;
Packit Service c5cf8c
Packit Service c5cf8c
    free(current_nodes);
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int netloc_arch_set_global_resources(netloc_arch_t *arch)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret;
Packit Service c5cf8c
    NETLOC_int *current_nodes = NULL;
Packit Service c5cf8c
    int *slot_idx = NULL;
Packit Service c5cf8c
Packit Service c5cf8c
    int num_nodes =  HASH_COUNT(arch->nodes_by_name);
Packit Service c5cf8c
    if (!arch->has_slots) {
Packit Service c5cf8c
        current_nodes = (NETLOC_int *) malloc(sizeof(NETLOC_int[num_nodes]));
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    ret = netloc_topology_read_hwloc(arch->topology, 0, NULL);
Packit Service c5cf8c
    if( NETLOC_SUCCESS != ret ) {
Packit Service c5cf8c
        goto ERROR;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    int constant_num_slots = 0;
Packit Service c5cf8c
    slot_idx = (int *)malloc(sizeof(int[num_nodes+1]));
Packit Service c5cf8c
    slot_idx[0] = 0;
Packit Service c5cf8c
    int current_idx = 0;
Packit Service c5cf8c
    netloc_arch_node_t *node, *node_tmp;
Packit Service c5cf8c
    HASH_ITER(hh, arch->nodes_by_name, node, node_tmp) {
Packit Service c5cf8c
        ret = netloc_arch_node_get_hwloc_info(node);
Packit Service c5cf8c
        if (ret != NETLOC_SUCCESS)
Packit Service c5cf8c
            goto ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
        if (!arch->has_slots) {
Packit Service c5cf8c
            current_nodes[current_idx] = node->idx_in_topo;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        current_idx++;
Packit Service c5cf8c
Packit Service c5cf8c
        int num_slots = node->num_slots;
Packit Service c5cf8c
        node->num_current_slots = num_slots;
Packit Service c5cf8c
Packit Service c5cf8c
        slot_idx[current_idx] = slot_idx[current_idx-1]+num_slots;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Nodes with different number of slots are not handled yet, because we
Packit Service c5cf8c
         * build the scotch architecture without taking account of the
Packit Service c5cf8c
         * available cores inside nodes, and Scotch is not able to weight the
Packit Service c5cf8c
         * nodes */
Packit Service c5cf8c
        if (!arch->has_slots) {
Packit Service c5cf8c
            if (constant_num_slots) {
Packit Service c5cf8c
                if (constant_num_slots != num_slots) {
Packit Service c5cf8c
                    fprintf(stderr, "Oups: the same number of cores by node is needed!\n");
Packit Service c5cf8c
                    assert(constant_num_slots == num_slots);
Packit Service c5cf8c
                }
Packit Service c5cf8c
            } else {
Packit Service c5cf8c
                constant_num_slots = num_slots;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (!arch->has_slots) {
Packit Service c5cf8c
        arch->num_current_hosts = num_nodes;
Packit Service c5cf8c
        arch->current_hosts = current_nodes;
Packit Service c5cf8c
        arch->arch.global_tree = arch->arch.node_tree;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Build nodes_by_idx */
Packit Service c5cf8c
        int tree_size = netloc_arch_tree_num_leaves(arch->arch.node_tree);
Packit Service c5cf8c
        netloc_arch_node_slot_t *nodes_by_idx = (netloc_arch_node_slot_t *)
Packit Service c5cf8c
            malloc(sizeof(netloc_arch_node_slot_t[tree_size]));
Packit Service c5cf8c
        netloc_arch_node_t *node, *node_tmp;
Packit Service c5cf8c
        HASH_ITER(hh, arch->nodes_by_name, node, node_tmp) {
Packit Service c5cf8c
            nodes_by_idx[node->idx_in_topo].node = node;
Packit Service c5cf8c
            nodes_by_idx[node->idx_in_topo].slot = -1;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        arch->node_slot_by_idx = nodes_by_idx;
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        int num_hosts = slot_idx[num_nodes];
Packit Service c5cf8c
        NETLOC_int *current_hosts = (NETLOC_int *)
Packit Service c5cf8c
            malloc(sizeof(NETLOC_int[num_hosts]));
Packit Service c5cf8c
        netloc_arch_node_t *node, *node_tmp;
Packit Service c5cf8c
        /* Add the slot trees to the node tree */
Packit Service c5cf8c
Packit Service c5cf8c
        /* Check that each slot tree has the same size */
Packit Service c5cf8c
        int slot_tree_size = 0;
Packit Service c5cf8c
        HASH_ITER(hh, arch->nodes_by_name, node, node_tmp) {
Packit Service c5cf8c
            int current_size = netloc_arch_tree_num_leaves(node->slot_tree);
Packit Service c5cf8c
            if (!slot_tree_size) {
Packit Service c5cf8c
                slot_tree_size = current_size;
Packit Service c5cf8c
            } else {
Packit Service c5cf8c
                if (slot_tree_size != current_size) {
Packit Service c5cf8c
                    assert(0);
Packit Service c5cf8c
                }
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        int current_host_idx = 0;
Packit Service c5cf8c
        int node_tree_size = netloc_arch_tree_num_leaves(arch->arch.node_tree);
Packit Service c5cf8c
        int global_tree_size = node_tree_size*slot_tree_size;
Packit Service c5cf8c
        netloc_arch_node_slot_t *nodes_by_idx = (netloc_arch_node_slot_t *)
Packit Service c5cf8c
            malloc(sizeof(netloc_arch_node_slot_t[global_tree_size]));
Packit Service c5cf8c
        int n = 0;
Packit Service c5cf8c
        HASH_ITER(hh, arch->nodes_by_name, node, node_tmp) {
Packit Service c5cf8c
            for (int s = slot_idx[n]; s < slot_idx[n+1]; s++) {
Packit Service c5cf8c
                int slot_rank = s-slot_idx[n];
Packit Service c5cf8c
                int topo_idx = node->idx_in_topo*slot_tree_size +
Packit Service c5cf8c
                    node->slot_idx[slot_rank];
Packit Service c5cf8c
                nodes_by_idx[topo_idx].node = node;
Packit Service c5cf8c
                nodes_by_idx[topo_idx].slot = slot_rank;
Packit Service c5cf8c
                current_hosts[current_host_idx++] = topo_idx;
Packit Service c5cf8c
            }
Packit Service c5cf8c
            n++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        arch->num_current_hosts = current_host_idx;
Packit Service c5cf8c
        arch->current_hosts = current_hosts;
Packit Service c5cf8c
        arch->node_slot_by_idx = nodes_by_idx;
Packit Service c5cf8c
Packit Service c5cf8c
        netloc_arch_tree_t *new_tree =
Packit Service c5cf8c
            tree_merge(arch->arch.node_tree, arch->nodes_by_name->slot_tree);
Packit Service c5cf8c
        netloc_arch_tree_destruct(arch->arch.node_tree);
Packit Service c5cf8c
        arch->arch.global_tree = new_tree;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
ERROR:
Packit Service c5cf8c
    free(slot_idx);
Packit Service c5cf8c
Packit Service c5cf8c
    if (ret == NETLOC_SUCCESS)
Packit Service c5cf8c
        return ret;
Packit Service c5cf8c
Packit Service c5cf8c
    free(current_nodes);
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
netloc_arch_tree_t *tree_merge(netloc_arch_tree_t *main, netloc_arch_tree_t *sub)
Packit Service c5cf8c
{
Packit Service c5cf8c
    netloc_arch_tree_t *new_tree = (netloc_arch_tree_t *)
Packit Service c5cf8c
        malloc(sizeof(netloc_arch_tree_t));
Packit Service c5cf8c
Packit Service c5cf8c
    int num_levels = main->num_levels+sub->num_levels;
Packit Service c5cf8c
    new_tree->num_levels = num_levels;
Packit Service c5cf8c
    new_tree->degrees = (NETLOC_int *)malloc(sizeof(NETLOC_int[num_levels]));
Packit Service c5cf8c
    new_tree->cost = (NETLOC_int *)malloc(sizeof(NETLOC_int[num_levels]));
Packit Service c5cf8c
Packit Service c5cf8c
    memcpy(new_tree->degrees, main->degrees,
Packit Service c5cf8c
            main->num_levels*sizeof(*new_tree->degrees));
Packit Service c5cf8c
    memcpy(new_tree->degrees+main->num_levels, sub->degrees,
Packit Service c5cf8c
            sub->num_levels*sizeof(*new_tree->degrees));
Packit Service c5cf8c
Packit Service c5cf8c
    int out_coeff = 10;
Packit Service c5cf8c
    for (int l = 0; l < main->num_levels; l++) {
Packit Service c5cf8c
        new_tree->cost[l] = main->cost[l]*sub->cost[0]*out_coeff;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    memcpy(new_tree->cost+main->num_levels, sub->cost,
Packit Service c5cf8c
            sub->num_levels*sizeof(*new_tree->cost));
Packit Service c5cf8c
Packit Service c5cf8c
    return new_tree;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static int netloc_arch_tree_destruct(netloc_arch_tree_t *tree)
Packit Service c5cf8c
{
Packit Service c5cf8c
    free(tree->cost);
Packit Service c5cf8c
    free(tree->degrees);
Packit Service c5cf8c
    free(tree);
Packit Service c5cf8c
Packit Service c5cf8c
    return NETLOC_SUCCESS;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
int partition_topology_to_tleaf(netloc_topology_t *topology,
Packit Service c5cf8c
        int partition, int num_cores, netloc_arch_t *arch)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int ret = 0;
Packit Service c5cf8c
    UT_array *nodes;
Packit Service c5cf8c
    utarray_new(nodes, &ut_ptr_icd);
Packit Service c5cf8c
Packit Service c5cf8c
    netloc_arch_tree_t *tree = (netloc_arch_tree_t *)
Packit Service c5cf8c
        malloc(sizeof(netloc_arch_tree_t));
Packit Service c5cf8c
    arch->arch.node_tree = tree;
Packit Service c5cf8c
    arch->type = NETLOC_ARCH_TREE;
Packit Service c5cf8c
Packit Service c5cf8c
    /* we build nodes from host list in the given partition
Packit Service c5cf8c
     * and we init all the analysis data */
Packit Service c5cf8c
    netloc_node_t *node, *node_tmp;
Packit Service c5cf8c
    netloc_topology_iter_nodes(topology, node, node_tmp) {
Packit Service c5cf8c
        if (!netloc_node_is_in_partition(node, partition))
Packit Service c5cf8c
            continue;
Packit Service c5cf8c
        void *userdata = node->userdata;
Packit Service c5cf8c
        node->userdata = (void *)malloc(sizeof(netloc_analysis_data));
Packit Service c5cf8c
        netloc_analysis_data *analysis_data = (netloc_analysis_data *)node->userdata;
Packit Service c5cf8c
        analysis_data->level = -1;
Packit Service c5cf8c
        analysis_data->userdata = userdata; 
Packit Service c5cf8c
Packit Service c5cf8c
        netloc_edge_t *edge, *edge_tmp;
Packit Service c5cf8c
        netloc_node_iter_edges(node, edge, edge_tmp) {
Packit Service c5cf8c
            void *userdata = edge->userdata;
Packit Service c5cf8c
            edge->userdata = (void *)malloc(sizeof(netloc_analysis_data));
Packit Service c5cf8c
            netloc_analysis_data *analysis_data = (netloc_analysis_data *)edge->userdata;
Packit Service c5cf8c
            analysis_data->level = -1;
Packit Service c5cf8c
            analysis_data->userdata = userdata; 
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        if (netloc_node_is_host(node)) {
Packit Service c5cf8c
            utarray_push_back(nodes, &node);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* We set the levels in the analysis data */
Packit Service c5cf8c
    /* Upward edges will have the level of the source node and downward edges
Packit Service c5cf8c
     * will have -1 as level */
Packit Service c5cf8c
    int num_levels = 0;
Packit Service c5cf8c
    netloc_node_t *current_node = /* pointer to one host node */
Packit Service c5cf8c
        *(void **)utarray_eltptr(nodes, 0);
Packit Service c5cf8c
    while (utarray_len(nodes)) {
Packit Service c5cf8c
        UT_array *new_nodes;
Packit Service c5cf8c
        utarray_new(new_nodes, &ut_ptr_icd);
Packit Service c5cf8c
Packit Service c5cf8c
        for (unsigned int n = 0; n < utarray_len(nodes); n++) {
Packit Service c5cf8c
            netloc_node_t *node = *(void **)utarray_eltptr(nodes, n);
Packit Service c5cf8c
            netloc_analysis_data *node_data = (netloc_analysis_data *)node->userdata;
Packit Service c5cf8c
            /* There is a problem, this is not a tree */
Packit Service c5cf8c
            if (node_data->level != -1 && node_data->level != num_levels) {
Packit Service c5cf8c
                utarray_free(new_nodes);
Packit Service c5cf8c
                ret = -1;
Packit Service c5cf8c
                goto end;
Packit Service c5cf8c
            }
Packit Service c5cf8c
            else {
Packit Service c5cf8c
                node_data->level = num_levels;
Packit Service c5cf8c
                netloc_edge_t *edge, *edge_tmp;
Packit Service c5cf8c
                netloc_node_iter_edges(node, edge, edge_tmp) {
Packit Service c5cf8c
                    if (!netloc_edge_is_in_partition(edge, partition))
Packit Service c5cf8c
                        continue;
Packit Service c5cf8c
                    netloc_analysis_data *edge_data = (netloc_analysis_data *)edge->userdata;
Packit Service c5cf8c
Packit Service c5cf8c
                    netloc_node_t *dest = edge->dest;
Packit Service c5cf8c
                    netloc_analysis_data *dest_data = (netloc_analysis_data *)dest->userdata;
Packit Service c5cf8c
                    /* If we are going back */
Packit Service c5cf8c
                    if (dest_data->level != -1 && dest_data->level < num_levels) {
Packit Service c5cf8c
                        continue;
Packit Service c5cf8c
                    }
Packit Service c5cf8c
                    else {
Packit Service c5cf8c
                        if (dest_data->level != num_levels) {
Packit Service c5cf8c
                            edge_data->level = num_levels;
Packit Service c5cf8c
                            utarray_push_back(new_nodes, &dest);
Packit Service c5cf8c
                        }
Packit Service c5cf8c
                    }
Packit Service c5cf8c
                }
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        num_levels++;
Packit Service c5cf8c
        utarray_free(nodes);
Packit Service c5cf8c
        nodes = new_nodes;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* We go though the tree to order the leaves  and find the tree
Packit Service c5cf8c
     * structure */
Packit Service c5cf8c
    UT_array *ordered_name_array = NULL;
Packit Service c5cf8c
    UT_array **down_degrees_by_level = NULL;
Packit Service c5cf8c
    NETLOC_int *max_down_degrees_by_level;
Packit Service c5cf8c
Packit Service c5cf8c
    utarray_new(ordered_name_array, &ut_ptr_icd);
Packit Service c5cf8c
Packit Service c5cf8c
    down_degrees_by_level = (UT_array **)malloc(num_levels*sizeof(UT_array *));
Packit Service c5cf8c
    for (int l = 0; l < num_levels; l++) {
Packit Service c5cf8c
        utarray_new(down_degrees_by_level[l], &ut_int_icd);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    max_down_degrees_by_level = (NETLOC_int *)
Packit Service c5cf8c
        calloc(num_levels-1, sizeof(NETLOC_int));
Packit Service c5cf8c
Packit Service c5cf8c
    UT_array *down_edges = NULL;
Packit Service c5cf8c
    utarray_new(down_edges, &ut_ptr_icd);
Packit Service c5cf8c
    netloc_edge_t *up_edge = current_node->edges;
Packit Service c5cf8c
    utarray_push_back(ordered_name_array, &current_node);
Packit Service c5cf8c
    while (1) {
Packit Service c5cf8c
        if (utarray_len(down_edges)) {
Packit Service c5cf8c
            netloc_edge_t *down_edge = *(void **)utarray_back(down_edges);
Packit Service c5cf8c
            utarray_pop_back(down_edges);
Packit Service c5cf8c
            netloc_node_t *dest_node = down_edge->dest;
Packit Service c5cf8c
            if (netloc_node_is_host(dest_node)) {
Packit Service c5cf8c
                utarray_push_back(ordered_name_array, &dest_node);
Packit Service c5cf8c
            }
Packit Service c5cf8c
            else {
Packit Service c5cf8c
                netloc_edge_t *edge, *edge_tmp;
Packit Service c5cf8c
                int num_edges = 0;
Packit Service c5cf8c
                netloc_node_iter_edges(dest_node, edge, edge_tmp) {
Packit Service c5cf8c
                    if (!netloc_edge_is_in_partition(edge, partition))
Packit Service c5cf8c
                        continue;
Packit Service c5cf8c
                    netloc_analysis_data *edge_data = (netloc_analysis_data *)edge->userdata;
Packit Service c5cf8c
                    int edge_level = edge_data->level;
Packit Service c5cf8c
                    if (edge_level == -1) {
Packit Service c5cf8c
                        utarray_push_back(down_edges, &edge);
Packit Service c5cf8c
                        num_edges++;
Packit Service c5cf8c
                    }
Packit Service c5cf8c
                }
Packit Service c5cf8c
                int level = ((netloc_analysis_data *)dest_node->userdata)->level;
Packit Service c5cf8c
                utarray_push_back(down_degrees_by_level[num_levels-1-level], &num_edges);
Packit Service c5cf8c
                max_down_degrees_by_level[num_levels-1-level] =
Packit Service c5cf8c
                    max_down_degrees_by_level[num_levels-1-level] > num_edges ?
Packit Service c5cf8c
                    max_down_degrees_by_level[num_levels-1-level]: num_edges;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        else {
Packit Service c5cf8c
            netloc_edge_t *new_up_edge = NULL;
Packit Service c5cf8c
            if (!up_edge)
Packit Service c5cf8c
                break;
Packit Service c5cf8c
Packit Service c5cf8c
            netloc_node_t *up_node = up_edge->dest;
Packit Service c5cf8c
            netloc_edge_t *edge, *edge_tmp;
Packit Service c5cf8c
            int num_edges = 0;
Packit Service c5cf8c
            netloc_node_iter_edges(up_node, edge, edge_tmp) {
Packit Service c5cf8c
                if (!netloc_edge_is_in_partition(edge, partition))
Packit Service c5cf8c
                    continue;
Packit Service c5cf8c
                netloc_analysis_data *edge_data = (netloc_analysis_data *)edge->userdata;
Packit Service c5cf8c
                int edge_level = edge_data->level;
Packit Service c5cf8c
Packit Service c5cf8c
                netloc_node_t *dest_node = edge->dest;
Packit Service c5cf8c
Packit Service c5cf8c
                /* If the is the node where we are from */
Packit Service c5cf8c
                if (dest_node == up_edge->node) {
Packit Service c5cf8c
                    num_edges++;
Packit Service c5cf8c
                    continue;
Packit Service c5cf8c
                }
Packit Service c5cf8c
Packit Service c5cf8c
                /* Downward edge */
Packit Service c5cf8c
                if (edge_level == -1) {
Packit Service c5cf8c
                    utarray_push_back(down_edges, &edge);
Packit Service c5cf8c
                    num_edges++;
Packit Service c5cf8c
                }
Packit Service c5cf8c
                /* Upward edge */
Packit Service c5cf8c
                else {
Packit Service c5cf8c
                    new_up_edge = edge;
Packit Service c5cf8c
                }
Packit Service c5cf8c
Packit Service c5cf8c
            }
Packit Service c5cf8c
            int level = ((netloc_analysis_data *)up_node->userdata)->level;
Packit Service c5cf8c
            utarray_push_back(down_degrees_by_level[num_levels-1-level], &num_edges);
Packit Service c5cf8c
            max_down_degrees_by_level[num_levels-1-level] =
Packit Service c5cf8c
                max_down_degrees_by_level[num_levels-1-level] > num_edges ?
Packit Service c5cf8c
                max_down_degrees_by_level[num_levels-1-level]: num_edges;
Packit Service c5cf8c
            up_edge = new_up_edge;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    tree->num_levels = num_levels-1;
Packit Service c5cf8c
    tree->degrees = max_down_degrees_by_level;
Packit Service c5cf8c
Packit Service c5cf8c
    int network_coeff = 2;
Packit Service c5cf8c
    tree->cost = (NETLOC_int *)malloc(sizeof(NETLOC_int[tree->num_levels]));
Packit Service c5cf8c
    tree->cost[tree->num_levels-1] = 1;
Packit Service c5cf8c
    for (int i = tree->num_levels-2; i >= 0 ; i--) {
Packit Service c5cf8c
        tree->cost[i] = tree->cost[i+1]*network_coeff;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* Now we have the degree of each node, so we can complete the topology to
Packit Service c5cf8c
     * have a complete balanced tree as requested by the tleaf structure */
Packit Service c5cf8c
    int *arch_idx;
Packit Service c5cf8c
    int num_nodes = utarray_len(ordered_name_array);
Packit Service c5cf8c
    netloc_arch_tree_complete(tree, down_degrees_by_level, num_nodes, &arch_idx);
Packit Service c5cf8c
Packit Service c5cf8c
    netloc_node_t **ordered_nodes = (netloc_node_t **)ordered_name_array->d;
Packit Service c5cf8c
    netloc_arch_node_t *named_nodes = NULL;
Packit Service c5cf8c
    for (int i = 0; i < num_nodes; i++) {
Packit Service c5cf8c
        netloc_arch_node_t *node = netloc_arch_node_construct();
Packit Service c5cf8c
        node->node = ordered_nodes[i];
Packit Service c5cf8c
        node->name = ordered_nodes[i]->hostname;
Packit Service c5cf8c
        node->idx_in_topo = arch_idx[i];
Packit Service c5cf8c
        HASH_ADD_KEYPTR(hh, named_nodes, node->name, strlen(node->name), node);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    free(arch_idx);
Packit Service c5cf8c
Packit Service c5cf8c
    arch->nodes_by_name = named_nodes;
Packit Service c5cf8c
Packit Service c5cf8c
end:
Packit Service c5cf8c
    if (nodes)
Packit Service c5cf8c
        utarray_free(nodes);
Packit Service c5cf8c
Packit Service c5cf8c
    if (ordered_name_array)
Packit Service c5cf8c
        utarray_free(ordered_name_array);
Packit Service c5cf8c
Packit Service c5cf8c
    if (down_degrees_by_level) {
Packit Service c5cf8c
        for (int l = 0; l < num_levels; l++) {
Packit Service c5cf8c
            utarray_free(down_degrees_by_level[l]);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        free(down_degrees_by_level);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (down_edges)
Packit Service c5cf8c
        utarray_free(down_edges);
Packit Service c5cf8c
Packit Service c5cf8c
    /* We copy back all userdata */
Packit Service c5cf8c
    netloc_topology_iter_nodes(topology, node, node_tmp) {
Packit Service c5cf8c
        if (!netloc_node_is_in_partition(node, partition))
Packit Service c5cf8c
            continue;
Packit Service c5cf8c
        netloc_analysis_data *analysis_data = (netloc_analysis_data *)node->userdata;
Packit Service c5cf8c
        if (analysis_data->level == -1 && ret != -1) {
Packit Service c5cf8c
            ret = -1;
Packit Service c5cf8c
            printf("The node %s was not browsed\n", node->description);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        free(analysis_data);
Packit Service c5cf8c
Packit Service c5cf8c
        netloc_edge_t *edge, *edge_tmp;
Packit Service c5cf8c
        netloc_node_iter_edges(node, edge, edge_tmp) {
Packit Service c5cf8c
            netloc_analysis_data *analysis_data = (netloc_analysis_data *)edge->userdata;
Packit Service c5cf8c
            node->userdata = analysis_data->userdata;
Packit Service c5cf8c
            free(analysis_data);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int netloc_arch_build(netloc_arch_t *arch, int add_slots)
Packit Service c5cf8c
{
Packit Service c5cf8c
    char *partition_name = getenv("NETLOC_PARTITION");
Packit Service c5cf8c
    char *topopath = getenv("NETLOC_TOPOFILE");
Packit Service c5cf8c
Packit Service c5cf8c
    if (!topopath) {
Packit Service c5cf8c
        fprintf(stderr, "Error: you need to set NETLOC_TOPOFILE in your environment.\n");
Packit Service c5cf8c
        return NETLOC_ERROR;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    topopath = strdup(topopath);
Packit Service c5cf8c
Packit Service c5cf8c
    netloc_topology_t *topology = netloc_topology_construct(topopath);
Packit Service c5cf8c
    if (topology == NULL) {
Packit Service c5cf8c
        fprintf(stderr, "Error: netloc_topology_construct failed\n");
Packit Service c5cf8c
        free(topopath);
Packit Service c5cf8c
        return NETLOC_ERROR;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    arch->topology = topology;
Packit Service c5cf8c
    arch->has_slots = add_slots;
Packit Service c5cf8c
Packit Service c5cf8c
    if (!partition_name) {
Packit Service c5cf8c
        fprintf(stderr, "Error: you need to set NETLOC_PARTITION in your environment.\n");
Packit Service c5cf8c
        fprintf(stderr, "\tIt can be: ");
Packit Service c5cf8c
        unsigned int num_partitions = utarray_len(topology->partitions);
Packit Service c5cf8c
        for (unsigned int p = 0; p < num_partitions; p++) {
Packit Service c5cf8c
            char *partition = *(char **)utarray_eltptr(topology->partitions, p);
Packit Service c5cf8c
            fprintf(stderr, "%s%s", partition, p != num_partitions-1 ? ", ": "\n");
Packit Service c5cf8c
        }
Packit Service c5cf8c
        return NETLOC_ERROR;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    int partition =
Packit Service c5cf8c
        netloc_topology_find_partition_idx(topology, partition_name);
Packit Service c5cf8c
Packit Service c5cf8c
    partition_topology_to_tleaf(topology, partition, 1, arch);
Packit Service c5cf8c
Packit Service c5cf8c
    return NETLOC_SUCCESS;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
netloc_arch_t * netloc_arch_construct(void)
Packit Service c5cf8c
{
Packit Service c5cf8c
    netloc_arch_t *arch = (netloc_arch_t *)calloc(1, sizeof(netloc_arch_t));
Packit Service c5cf8c
Packit Service c5cf8c
    return arch;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int netloc_arch_destruct(netloc_arch_t *arch)
Packit Service c5cf8c
{
Packit Service c5cf8c
    netloc_topology_destruct(arch->topology);
Packit Service c5cf8c
Packit Service c5cf8c
    netloc_arch_node_t *node, *node_tmp;
Packit Service c5cf8c
    HASH_ITER(hh, arch->nodes_by_name, node, node_tmp) {
Packit Service c5cf8c
        HASH_DEL(arch->nodes_by_name, node);
Packit Service c5cf8c
        netloc_arch_node_destruct(node);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    free(arch->arch.node_tree->degrees);
Packit Service c5cf8c
    free(arch->arch.node_tree->cost);
Packit Service c5cf8c
    free(arch->arch.node_tree);
Packit Service c5cf8c
    free(arch->current_hosts);
Packit Service c5cf8c
    free(arch->node_slot_by_idx);
Packit Service c5cf8c
Packit Service c5cf8c
    free(arch);
Packit Service c5cf8c
Packit Service c5cf8c
    return NETLOC_SUCCESS;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static netloc_arch_node_t *netloc_arch_node_construct(void)
Packit Service c5cf8c
{
Packit Service c5cf8c
    netloc_arch_node_t *arch_node = (netloc_arch_node_t *)
Packit Service c5cf8c
        calloc(1, sizeof(netloc_arch_node_t));
Packit Service c5cf8c
    arch_node->num_slots = -1;
Packit Service c5cf8c
Packit Service c5cf8c
    return arch_node;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static int netloc_arch_node_destruct(netloc_arch_node_t *arch_node)
Packit Service c5cf8c
{
Packit Service c5cf8c
    free(arch_node->slot_idx);
Packit Service c5cf8c
    free(arch_node->slot_os_idx);
Packit Service c5cf8c
    if (arch_node->slot_tree)
Packit Service c5cf8c
        netloc_arch_tree_destruct(arch_node->slot_tree);
Packit Service c5cf8c
    free(arch_node->current_slots);
Packit Service c5cf8c
    free(arch_node->slot_ranks);
Packit Service c5cf8c
    free(arch_node);
Packit Service c5cf8c
Packit Service c5cf8c
    return NETLOC_SUCCESS;
Packit Service c5cf8c
}