jobmap-list.c 5.65 KB
Newer Older
1 2 3 4 5
/*
 * Copyright (C) 2015 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
 */
6
#include <string.h>
7 8 9
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
Jonathan Jenkins's avatar
Jonathan Jenkins committed
10
#include "../codes-jobmap-method-impl.h"
11

12 13 14 15 16 17 18 19 20
#define LIST_DEBUG 0
#define dprintf(_fmt, ...) \
    do { \
        if (LIST_DEBUG) { \
            fprintf(stdout, "jobmap-list: "); \
            fprintf(stdout, _fmt, ##__VA_ARGS__); \
        } \
    } while (0)

21 22
#define ERR(str, ...)\
    do{\
23 24 25 26
        if (LIST_DEBUG) { \
            fprintf(stderr, "ERROR at %s:%d: " str "\n", \
                    __FILE__, __LINE__, ##__VA_ARGS__);\
        } \
27 28
        return -1; \
    }while(0)
29

30
struct jobmap_list {
31
    int num_jobs;
32 33
    int *rank_counts;
    int **global_ids;
34 35
};

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
#define COND_REALLOC(_len_expr, _cap_var, _buf_var) \
    do { \
        if ((_len_expr) == _cap_var) { \
            _buf_var = realloc(_buf_var, (_cap_var)*2*sizeof(*(_buf_var))); \
            assert(_buf_var); \
            _cap_var *= 2; \
        } \
    } while (0)

static int parse_line(
        FILE *f,
        char **line_buf,
        int *line_cap,
        int *num_ranks,
        int **rank_list)
51
{
52 53 54 55
    char * buf = *line_buf;

    int cap = *line_cap;
    int pos = 0;
56

57 58 59 60 61
    *num_ranks = 0;

    for (int c = fgetc(f); c != EOF && c != '\n'; c = fgetc(f)) {
        buf[pos++] = (char)c;
        COND_REALLOC(pos, cap, buf);
62
    }
63 64 65 66 67 68
    if (ferror(f)) {
        *num_ranks = -1;
        goto end;
    }
    else {
        buf[pos]='\0';
69
    }
70

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    int list_cap = 8;
    int *lst = malloc(list_cap * sizeof(*lst));
    assert(lst);
    int rank;

    *num_ranks = 0;
    for (char * tok = strtok(buf, " \t\r"); tok != NULL;
            tok = strtok(NULL, " \t\r")) {
        int rc = sscanf(tok, "%d", &rank);
        if (rc != 1) {
            fprintf(stderr,
                    "jobmap-list: unable to read alloc file - bad rank (%s)\n",
                    tok);
            *num_ranks = -1;
            break;
86
        }
87 88 89
        COND_REALLOC(*num_ranks, list_cap, lst);
        lst[*num_ranks] = rank;
        *num_ranks += 1;
90
    }
91

92 93 94
    if (*num_ranks <= 0) {
        *rank_list = NULL;
        free(lst);
95
    }
96 97 98 99 100 101 102
    else
        *rank_list = lst;
end:
    *line_buf = buf;
    *line_cap = cap;
    return (*num_ranks < 0) ? -1 : 0;
}
103

104 105 106 107 108 109 110 111 112
static int jobmap_list_configure(void const * params, void ** ctx)
{
    struct codes_jobmap_params_list const * p = params;
    struct jobmap_list *lst = malloc(sizeof(*lst));
    assert(lst);

    FILE *f = fopen(p->alloc_file, "r");
    if(!f) {
        ERR("Could not open file %s", p->alloc_file);
113 114
    }

115 116 117
    // job storage
    lst->num_jobs = 0;
    int job_cap = 8;
118 119 120 121
    lst->rank_counts = calloc(job_cap, sizeof(*lst->rank_counts));
    assert(lst->rank_counts);
    lst->global_ids = calloc(job_cap, sizeof(*lst->global_ids));
    assert(lst->global_ids);
122

123 124 125 126 127 128 129 130
    // line storage
    int line_cap = 1<<10;
    char *line_buf = malloc(line_cap);
    assert(line_buf);

    int rc = 0;
    do {
        rc = parse_line(f, &line_buf, &line_cap,
131 132
                &lst->rank_counts[lst->num_jobs],
                &lst->global_ids[lst->num_jobs]);
133 134 135 136 137 138
        if (rc == -1) {
            // error and exit
            if (ferror(f)) {
                perror("fgets");
                break;
            }
139
        }
140
        else if (lst->rank_counts[lst->num_jobs] > 0) {
141 142 143 144 145
            lst->num_jobs++;
        }
        // resize if needed
        if (!feof(f) && lst->num_jobs == job_cap) {
            int tmp = job_cap;
146 147
            COND_REALLOC(lst->num_jobs, tmp, lst->rank_counts);
            COND_REALLOC(lst->num_jobs, job_cap, lst->global_ids);
148 149
        }
    } while (!feof(f));
150

151 152 153 154 155 156 157 158
    if (rc == 0) {
        fclose(f);
        free(line_buf);
        *ctx = lst;
        return 0;
    }
    else {
        for (int i = 0; i < job_cap; i++) {
159
            free(lst->global_ids[i]);
160
        }
161 162
        free(lst->global_ids);
        free(lst->rank_counts);
163 164 165 166
        free(lst);
        *ctx = NULL;
        return -1;
    }
167
}
168

169
static struct codes_jobmap_id jobmap_list_to_local(int id, void const * ctx)
170 171
{
    struct codes_jobmap_id rtn;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
172 173 174
    rtn.job = -1;
    rtn.rank = -1;

175
    struct jobmap_list const *lst = (struct jobmap_list const *)ctx;
176

Jonathan Jenkins's avatar
Jonathan Jenkins committed
177
    for(int i=0; i<lst->num_jobs; i++) {
178 179
        for(int j=0; j < lst->rank_counts[i]; j++) {
            if(id == lst->global_ids[i][j]) {
180 181 182 183 184
                rtn.job = i;
                rtn.rank = j;
                return rtn;
            }
        }
185
    }
186

187 188 189
    return rtn;
}

190
static int jobmap_list_to_global(struct codes_jobmap_id id, void const * ctx)
191
{
192
    struct jobmap_list const *lst = (struct jobmap_list*)ctx;
193

194
    if (id.job < lst->num_jobs)
195
        return lst->global_ids[id.job][id.rank];
196 197 198 199
    else
        return -1;
}

Jonathan Jenkins's avatar
Jonathan Jenkins committed
200
static int jobmap_list_get_num_jobs(void const * ctx)
201
{
202 203
    struct jobmap_list *lst = (struct jobmap_list*)ctx;
    return lst->num_jobs;
204
}
205

206 207 208 209 210 211 212
static int jobmap_list_get_num_ranks(int job_id, void const * ctx)
{
    struct jobmap_list const *lst = (struct jobmap_list const *) ctx;
    if (job_id < 0 || job_id >= lst->num_jobs)
        return -1;
    else
        return lst->rank_counts[job_id];
213 214
}

215
static void jobmap_list_destroy(void * ctx)
216
{
217 218
    struct jobmap_list *lst = (struct jobmap_list*)ctx;
    for(int i=0; i<lst->num_jobs; i++){
219
        free(lst->global_ids[i]);
220 221
    }

222 223
    free(lst->global_ids);
    free(lst->rank_counts);
224
    free(ctx);
225 226
}

227

228 229 230 231 232
struct codes_jobmap_impl jobmap_list_impl = {
    jobmap_list_configure,
    jobmap_list_destroy,
    jobmap_list_to_local,
    jobmap_list_to_global,
233 234
    jobmap_list_get_num_jobs,
    jobmap_list_get_num_ranks
235 236 237 238 239 240 241 242 243 244 245
};

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  indent-tabs-mode: nil
 * End:
 *
 * vim: ts=8 sts=4 sw=4 expandtab
 */