configuration.c 13.4 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
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
    }
    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
314
            break;
315
316
317
318
319
320
321
322
323
        }
    }
    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;
324
        map->has_unanno_lp = 0;
325
326
327
328
329
330
331
        memset(map->num_anno_lps, 0, 
                CONFIGURATION_MAX_ANNOS*sizeof(*map->num_anno_lps));
        check_add_anno(anno, map);
        lpgroups->lpannos_count++;
    }
}

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

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

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

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

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

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

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

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