configuration.c 13.5 KB
Newer Older
Philip Carns's avatar
Philip Carns committed
1 2 3 4 5 6
/*
 * Copyright (C) 2013 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
 */

7 8
#include <stdio.h>
#include <stdlib.h>
9
#include <string.h>
10 11
#include <assert.h>
#include <errno.h>
12
#include <libgen.h>
13
#include "codes/configuration.h"
14
#include <ross.h>
15

16
#include "configfile.h"
17
#include "txt_configfile.h"
18

19 20 21 22 23
/*
 * Global to hold configuration in memory
 */
ConfigHandle config;

24 25 26
/* Global to hold LP configuration */
config_lpgroups_t lpconf;

27 28 29 30 31 32 33
int configuration_load (const char *filepath,
                        MPI_Comm comm,
                        ConfigHandle *handle)
{
    MPI_File   fh;
    MPI_Status status;
    MPI_Offset txtsize;
34 35 36 37 38
    FILE      *f = NULL;
    char      *txtdata = NULL;
    char      *error = NULL;
    int        rc = 0;
    char      *tmp_path = NULL;
39 40

    rc = MPI_File_open(comm, (char*)filepath, MPI_MODE_RDONLY, MPI_INFO_NULL, &fh);
41
    if (rc != MPI_SUCCESS) goto finalize;
42 43

    rc = MPI_File_get_size(fh, &txtsize);
44
    if (rc != MPI_SUCCESS) goto finalize;
45

Elsa Gonsiorowski (Uranus)'s avatar
Elsa Gonsiorowski (Uranus) committed
46
    txtdata = (char*) malloc(txtsize);
47
    assert(txtdata);
48 49

    rc = MPI_File_read_all(fh, txtdata, txtsize, MPI_BYTE, &status);
50
    if (rc != MPI_SUCCESS) goto finalize;
51

52 53 54
#ifdef __APPLE__
    f = fopen(filepath, "r");
#else
55
    f = fmemopen(txtdata, txtsize, "rb");
56
#endif
57
    if (!f) { rc = 1; goto finalize; }
58 59

    *handle = txtfile_openStream(f, &error);
60
    if (error) { rc = 1; goto finalize; }
61

62 63
    /* NOTE: posix version overwrites argument :(. */
    tmp_path = strdup(filepath);
64
    assert(tmp_path);
65
    (*handle)->config_dir = strdup(dirname(tmp_path));
66 67
    assert((*handle)->config_dir);

68
    rc = configuration_get_lpgroups(handle, "LPGROUPS", &lpconf);
69

70 71 72 73 74 75 76 77 78
finalize:
    if (fh != MPI_FILE_NULL) MPI_File_close(&fh);
    if (f) fclose(f);
    free(txtdata);
    free(tmp_path);
    if (error) {
        fprintf(stderr, "config error: %s\n", error);
        free(error);
    }
79

80 81 82 83 84 85
    return rc;
}

int configuration_get_value(ConfigHandle *handle,
                            const char *section_name,
                            const char *key_name,
86
                            const char *annotation,
87 88 89 90 91
                            char *value,
                            size_t len)
{
    SectionHandle section_handle;
    int           rc;
92 93 94 95 96 97 98 99 100
    // reading directly from the config, so need to inject the annotation
    // directly into the search string
    char key_name_tmp[CONFIGURATION_MAX_NAME];
    char *key_name_full;
    if (annotation==NULL){
        // sorry const type... we promise we won't change you
        key_name_full = (char*) key_name;
    }
    else{
101 102 103 104 105 106 107 108 109
        if (snprintf(key_name_tmp, CONFIGURATION_MAX_NAME, "%s@%s",
                    key_name, annotation) >= CONFIGURATION_MAX_NAME) {
            fprintf(stderr,
                    "config error: name@annotation pair too long: %s@%s\n",
                    key_name, annotation);
            return 1;
        }
        else
            key_name_full = key_name_tmp;
110
    }
111 112

    rc = cf_openSection(*handle, ROOT_SECTION, section_name, &section_handle);
113
    if (rc != 1) return 0;
114

115
    rc = cf_getKey(*handle, section_handle, key_name_full, value, len);
116 117 118 119 120
    (void) cf_closeSection(*handle, section_handle);

    return rc;
}

121 122 123 124
int configuration_get_value_relpath(
        ConfigHandle *handle,
        const char * section_name,
        const char * key_name,
125
        const char *annotation,
126 127
        char *value,
        size_t length){
Elsa Gonsiorowski (Uranus)'s avatar
Elsa Gonsiorowski (Uranus) committed
128
    char *tmp = (char*) malloc(length);
129

130
    int w = configuration_get_value(handle, section_name, key_name, annotation, tmp,
131
            length);
132 133
    if (w <= 0)
        return w;
134 135

    /* concat the configuration value with the directory */
136
    w = snprintf(value, length, "%s/%s", (*handle)->config_dir, tmp);
137 138 139 140 141

    free(tmp);
    return w;
}

142 143 144
int configuration_get_multivalue(ConfigHandle *handle,
                                 const char *section_name,
                                 const char *key_name,
145
                                 const char *annotation,
146 147 148 149 150
                                 char ***values,
                                 size_t *len)
{
    SectionHandle section_handle;
    int           rc;
151 152 153 154 155 156 157 158 159
    // reading directly from the config, so need to inject the annotation
    // directly into the search string
    char key_name_tmp[CONFIGURATION_MAX_NAME];
    char *key_name_full;
    if (annotation==NULL){
        // sorry const type... we promise we won't change you
        key_name_full = (char*) key_name;
    }
    else{
160 161 162 163 164 165 166 167 168
        if (snprintf(key_name_tmp, CONFIGURATION_MAX_NAME, "%s@%s",
                    key_name, annotation) >= CONFIGURATION_MAX_NAME) {
            fprintf(stderr,
                    "config error: name@annotation pair too long: %s@%s\n",
                    key_name, annotation);
            return 1;
        }
        else
            key_name_full = key_name_tmp;
169
    }
170 171

    rc = cf_openSection(*handle, ROOT_SECTION, section_name, &section_handle);
172
    if (rc != 1) return rc;
173

174
    rc = cf_getMultiKey(*handle, section_handle, key_name_full, values, len);
175 176 177 178 179
    (void) cf_closeSection(*handle, section_handle);

    return rc;
}

180 181 182
int configuration_get_value_int (ConfigHandle *handle,
                                 const char *section_name,
                                 const char *key_name,
183
                                 const char *annotation,
184 185 186 187 188 189 190 191 192
                                 int *value)
{
    char valuestr[256];
    int rc = 1;
    int r;

    r = configuration_get_value(handle,
                                section_name,
                                key_name,
193
                                annotation,
194 195 196 197 198 199 200 201 202 203 204 205 206 207
                                valuestr,
                                sizeof(valuestr));
    if (r > 0)
    {
        *value = atoi(valuestr);
        rc = 0;
    }

    return rc;
}

int configuration_get_value_uint (ConfigHandle *handle,
                                  const char *section_name,
                                  const char *key_name,
208
                                  const char *annotation,
209 210 211 212 213 214 215 216 217
                                  unsigned int *value)
{
    char valuestr[256];
    int rc = 1;
    int r;

    r = configuration_get_value(handle,
                                section_name,
                                key_name,
218
                                annotation,
219 220 221 222 223 224 225 226 227 228 229 230 231 232
                                valuestr,
                                sizeof(valuestr));
    if (r > 0)
    {
        *value = (unsigned int) atoi(valuestr);
        rc = 0;
    }

    return rc;
}

int configuration_get_value_longint (ConfigHandle *handle,
                                     const char *section_name,
                                     const char *key_name,
233
                                     const char *annotation,
234 235 236 237 238 239 240 241 242
                                     long int *value)
{
    char valuestr[256];
    int rc = 1;
    int r;

    r = configuration_get_value(handle,
                                section_name,
                                key_name,
243
                                annotation,
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
                                valuestr,
                                sizeof(valuestr));
    if (r > 0)
    {
        errno = 0;
        *value = strtol(valuestr, NULL, 10);
        rc = errno;
    }

    return rc;
}

int configuration_get_value_double (ConfigHandle *handle,
                                    const char *section_name,
                                    const char *key_name,
259
                                    const char *annotation,
260 261 262 263 264 265 266 267 268
                                    double *value)
{
    char valuestr[256];
    int rc = 1;
    int r;

    r = configuration_get_value(handle,
                                section_name,
                                key_name,
269
                                annotation,
270 271 272 273 274 275 276 277 278 279 280 281
                                valuestr,
                                sizeof(valuestr));
    if (r > 0)
    {
        errno = 0;
        *value = strtod(valuestr, NULL);
        rc = errno;
    }

    return rc;
}

282 283 284 285
static void check_add_anno(
        const char *anno,
        config_anno_map_t *map){
    if (anno[0] == '\0'){
286
        map->has_unanno_lp = 1;
287 288
        if (!map->num_annos)
            map->is_unanno_first = 1;
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
    }
    else{
        uint64_t a = 0;
        for (; a < map->num_annos; a++){
            if (strcmp(map->annotations[a], anno) == 0){
                map->num_anno_lps[a]++;
                break;
            }
        }
        if (a == map->num_annos){
            // we have a new anno!
            assert(a < CONFIGURATION_MAX_ANNOS);
            map->annotations[a] = strdup(anno);
            map->num_annos++;
            map->num_anno_lps[a] = 1;
        } // else anno was already there, do nothing
    }
}
static void check_add_lp_type_anno(
        const char *lp_name,
        const char *anno,
        config_lpgroups_t *lpgroups){
    uint64_t lpt_anno = 0;
    for (; lpt_anno < lpgroups->lpannos_count; lpt_anno++){
        config_anno_map_t *map = &lpgroups->lpannos[lpt_anno];
        if (strcmp(map->lp_name, lp_name) == 0){
            check_add_anno(anno, map);
Jonathan Jenkins's avatar
Jonathan Jenkins committed
316
            break;
317 318 319 320 321 322 323 324 325
        }
    }
    if (lpt_anno == lpgroups->lpannos_count){
        // we haven't seen this lp type before
        assert(lpt_anno < CONFIGURATION_MAX_TYPES);
        config_anno_map_t *map = &lpgroups->lpannos[lpt_anno];
        // initialize this annotation map
        strcpy(map->lp_name, lp_name);
        map->num_annos = 0;
326
        map->has_unanno_lp = 0;
327
        map->is_unanno_first = 0;
328 329 330 331 332 333 334
        memset(map->num_anno_lps, 0, 
                CONFIGURATION_MAX_ANNOS*sizeof(*map->num_anno_lps));
        check_add_anno(anno, map);
        lpgroups->lpannos_count++;
    }
}

335 336 337
int configuration_get_lpgroups (ConfigHandle *handle,
                                const char *section_name,
                                config_lpgroups_t *lpgroups)
338 339 340 341 342 343 344 345 346 347
{
    SectionHandle sh;
    SectionHandle subsh;
    SectionEntry se[10];
    SectionEntry subse[10];
    size_t se_count = 10;
    size_t subse_count = 10;
    int i, j, lpt;
    char data[256];

348
    memset (lpgroups, 0, sizeof(*lpgroups));
349

350 351 352
    int ret = cf_openSection(*handle, ROOT_SECTION, section_name, &sh);
    if (ret == -1)
        return -1;
353
    cf_listSection(*handle, sh, se, &se_count); 
354

355 356 357 358 359 360 361 362 363 364 365
#define CHECKED_STRTOL(_val, _field, _data) \
    do{ \
        errno = 0; \
        long int _rd = strtol(_data, NULL, 10); \
        if (_rd <= 0 || errno) \
            tw_error(TW_LOC, "bad value (expected positive integer) for " \
                    "\"%s\": %s\n", _field, _data); \
        else \
            _val = _rd; \
    }while(0);

366 367
    for (i = 0; i < se_count; i++)
    {
368
        //printf("section: %s type: %d\n", se[i].name, se[i].type);
369 370 371
        if (se[i].type == SE_SECTION)
        {
            subse_count = 10;
372 373 374
            cf_openSection(*handle, sh, se[i].name, &subsh);
            cf_listSection(*handle, subsh, subse, &subse_count);
            strncpy(lpgroups->lpgroups[i].name, se[i].name,
375
                    CONFIGURATION_MAX_NAME);
376 377
            lpgroups->lpgroups[i].repetitions = 1;
            lpgroups->lpgroups_count++;
378 379 380 381
            for (j = 0, lpt = 0; j < subse_count; j++)
            {
                if (subse[j].type == SE_KEY)
                {
382 383
                   cf_getKey(*handle, subsh, subse[j].name, data, sizeof(data));
                   //printf("key: %s value: %s\n", subse[j].name, data);
384 385
                   if (strcmp("repetitions", subse[j].name) == 0)
                   {
386 387
                       CHECKED_STRTOL(lpgroups->lpgroups[i].repetitions,
                               "repetitions", data);
388
		       //printf("\n Repetitions: %ld ", lpgroups->lpgroups[i].repetitions);
389 390 391
                   }
                   else
                   {
392 393 394
                       size_t s = sizeof(lpgroups->lpgroups[i].lptypes[lpt].name);
                       char *nm   = lpgroups->lpgroups[i].lptypes[lpt].name;
                       char *anno = lpgroups->lpgroups[i].lptypes[lpt].anno;
395
                       // assume these are lptypes and counts
396 397 398 399 400 401 402 403 404 405 406
                       strncpy(nm, subse[j].name, s-1);
                       lpgroups->lpgroups[i].lptypes[lpt].name[s-1] = '\0';

                       char *c = strchr(nm, '@');
                       if (c) {
                           strcpy(anno, c+1);
                           *c = '\0';
                       }
                       else {
                           anno[0] = '\0';
                       }
407 408
                       // add to anno map
                       check_add_lp_type_anno(nm, anno, lpgroups);
409 410
                       CHECKED_STRTOL(lpgroups->lpgroups[i].lptypes[lpt].count,
                               nm, data);
411
                       lpgroups->lpgroups[i].lptypes_count++;
412 413 414 415
                       lpt++;
                   }
                }
            }
416
            cf_closeSection(*handle, subsh);
417 418 419
        }
    }

420
    cf_closeSection(*handle, sh);
421 422 423
    
    return 0;
}
Philip Carns's avatar
Philip Carns committed
424

425 426 427 428 429
/*
 * Helper function - get the position in the LP annotation list of the
 * given annotation. Used for configuration schemes where an array of
 * configuration values is generated based on the annotations in
 * config_anno_map_t
430 431
 * If anno is not found or a NULL anno is passed in,
 * -1 is returned */
432 433
int configuration_get_annotation_index(const char *              anno,
                                       const config_anno_map_t * anno_map){
434
    if (anno == NULL) return -1;
435
    for (uint64_t i = 0; i < anno_map->num_annos; i++){
436
        if (!strcmp(anno, anno_map->annotations[i])){
437 438 439 440 441 442
            return (int)i;
        }
    }
    return -1;
}

Philip Carns's avatar
Philip Carns committed
443 444 445 446 447 448 449 450
/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ts=8 sts=4 sw=4 expandtab
 */