configuration.c 13.3 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 17
#include "configfile.h"

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

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

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

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

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

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

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

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

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

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

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

69 70 71 72 73 74 75 76 77
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);
    }
78

79 80 81 82 83 84
    return rc;
}

int configuration_get_value(ConfigHandle *handle,
                            const char *section_name,
                            const char *key_name,
85
                            const char *annotation,
86 87 88 89 90
                            char *value,
                            size_t len)
{
    SectionHandle section_handle;
    int           rc;
91 92 93 94 95 96 97 98 99
    // 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{
100 101 102 103 104 105 106 107 108
        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;
109
    }
110 111

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

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

    return rc;
}

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

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

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

    free(tmp);
    return w;
}

141 142 143
int configuration_get_multivalue(ConfigHandle *handle,
                                 const char *section_name,
                                 const char *key_name,
144
                                 const char *annotation,
145 146 147 148 149
                                 char ***values,
                                 size_t *len)
{
    SectionHandle section_handle;
    int           rc;
150 151 152 153 154 155 156 157 158
    // 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{
159 160 161 162 163 164 165 166 167
        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;
168
    }
169 170

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

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

    return rc;
}

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

    r = configuration_get_value(handle,
                                section_name,
                                key_name,
192
                                annotation,
193 194 195 196 197 198 199 200 201 202 203 204 205 206
                                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,
207
                                  const char *annotation,
208 209 210 211 212 213 214 215 216
                                  unsigned int *value)
{
    char valuestr[256];
    int rc = 1;
    int r;

    r = configuration_get_value(handle,
                                section_name,
                                key_name,
217
                                annotation,
218 219 220 221 222 223 224 225 226 227 228 229 230 231
                                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,
232
                                     const char *annotation,
233 234 235 236 237 238 239 240 241
                                     long int *value)
{
    char valuestr[256];
    int rc = 1;
    int r;

    r = configuration_get_value(handle,
                                section_name,
                                key_name,
242
                                annotation,
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
                                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,
258
                                    const char *annotation,
259 260 261 262 263 264 265 266 267
                                    double *value)
{
    char valuestr[256];
    int rc = 1;
    int r;

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

    return rc;
}

281 282 283 284
static void check_add_anno(
        const char *anno,
        config_anno_map_t *map){
    if (anno[0] == '\0'){
285
        map->has_unanno_lp = 1;
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
    }
    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
313
            break;
314 315 316 317 318 319 320 321 322
        }
    }
    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;
323
        map->has_unanno_lp = 0;
324 325 326 327 328 329 330
        memset(map->num_anno_lps, 0, 
                CONFIGURATION_MAX_ANNOS*sizeof(*map->num_anno_lps));
        check_add_anno(anno, map);
        lpgroups->lpannos_count++;
    }
}

331 332 333
int configuration_get_lpgroups (ConfigHandle *handle,
                                const char *section_name,
                                config_lpgroups_t *lpgroups)
334 335 336 337 338 339 340 341 342 343
{
    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];

344
    memset (lpgroups, 0, sizeof(*lpgroups));
345

346 347 348
    int ret = cf_openSection(*handle, ROOT_SECTION, section_name, &sh);
    if (ret == -1)
        return -1;
349
    cf_listSection(*handle, sh, se, &se_count); 
350

351 352 353 354 355 356 357 358 359 360 361
#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);

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

416
    cf_closeSection(*handle, sh);
417 418 419
    
    return 0;
}
Philip Carns's avatar
Philip Carns committed
420

421 422 423 424 425
/*
 * 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
426 427
 * If anno is not found or a NULL anno is passed in,
 * -1 is returned */
428 429
int configuration_get_annotation_index(const char *              anno,
                                       const config_anno_map_t * anno_map){
430
    if (anno == NULL) return -1;
431
    for (uint64_t i = 0; i < anno_map->num_annos; i++){
432
        if (!strcmp(anno, anno_map->annotations[i])){
433 434 435 436 437 438
            return (int)i;
        }
    }
    return -1;
}

Philip Carns's avatar
Philip Carns committed
439 440 441 442 443 444 445 446
/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ts=8 sts=4 sw=4 expandtab
 */