configuration.c 12.7 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
14
#include "codes/configuration.h"

15
16
17
18
19
/*
 * Global to hold configuration in memory
 */
ConfigHandle config;

20
21
22
/* Global to hold LP configuration */
config_lpgroups_t lpconf;

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

    rc = MPI_File_open(comm, (char*)filepath, MPI_MODE_RDONLY, MPI_INFO_NULL, &fh);
37
    if (rc != MPI_SUCCESS) goto finalize;
38
39

    rc = MPI_File_get_size(fh, &txtsize);
40
    if (rc != MPI_SUCCESS) goto finalize;
41
42

    txtdata = malloc(txtsize);
43
    assert(txtdata);
44
45

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

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

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

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

    configuration_get_lpgroups(handle, "LPGROUPS", &lpconf);
65

66
67
68
69
70
71
72
73
74
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);
    }
75

76
77
78
79
80
81
    return rc;
}

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

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

111
    rc = cf_getKey(*handle, section_handle, key_name_full, value, len);
112
113
114
115
116
    (void) cf_closeSection(*handle, section_handle);

    return rc;
}

117
118
119
120
int configuration_get_value_relpath(
        ConfigHandle *handle,
        const char * section_name,
        const char * key_name,
121
        const char *annotation,
122
123
124
125
        char *value,
        size_t length){
    char *tmp = malloc(length);

126
127
    configuration_get_value(handle, section_name, key_name, annotation, tmp,
            length);
128
129
130
131
132
133
134
135

    /* concat the configuration value with the directory */
    int w = snprintf(value, length, "%s/%s", (*handle)->config_dir, tmp);

    free(tmp);
    return w;
}

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

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

168
    rc = cf_getMultiKey(*handle, section_handle, key_name_full, values, len);
169
170
171
172
173
    (void) cf_closeSection(*handle, section_handle);

    return rc;
}

174
175
176
int configuration_get_value_int (ConfigHandle *handle,
                                 const char *section_name,
                                 const char *key_name,
177
                                 const char *annotation,
178
179
180
181
182
183
184
185
186
                                 int *value)
{
    char valuestr[256];
    int rc = 1;
    int r;

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

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

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

    r = configuration_get_value(handle,
                                section_name,
                                key_name,
263
                                annotation,
264
265
266
267
268
269
270
271
272
273
274
275
                                valuestr,
                                sizeof(valuestr));
    if (r > 0)
    {
        errno = 0;
        *value = strtod(valuestr, NULL);
        rc = errno;
    }

    return rc;
}

276
277
278
279
static void check_add_anno(
        const char *anno,
        config_anno_map_t *map){
    if (anno[0] == '\0'){
280
        map->has_unanno_lp = 1;
281
282
283
284
285
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
313
314
315
316
    }
    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);
        }
    }
    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;
317
        map->has_unanno_lp = 0;
318
319
320
321
322
323
324
        memset(map->num_anno_lps, 0, 
                CONFIGURATION_MAX_ANNOS*sizeof(*map->num_anno_lps));
        check_add_anno(anno, map);
        lpgroups->lpannos_count++;
    }
}

325
326
327
int configuration_get_lpgroups (ConfigHandle *handle,
                                const char *section_name,
                                config_lpgroups_t *lpgroups)
328
329
330
331
332
333
334
335
336
337
{
    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];

338
    memset (lpgroups, 0, sizeof(*lpgroups));
339

340
341
    cf_openSection(*handle, ROOT_SECTION, section_name, &sh);
    cf_listSection(*handle, sh, se, &se_count); 
342
343
344

    for (i = 0; i < se_count; i++)
    {
345
        //printf("section: %s type: %d\n", se[i].name, se[i].type);
346
347
348
        if (se[i].type == SE_SECTION)
        {
            subse_count = 10;
349
350
351
            cf_openSection(*handle, sh, se[i].name, &subsh);
            cf_listSection(*handle, subsh, subse, &subse_count);
            strncpy(lpgroups->lpgroups[i].name, se[i].name,
352
                    CONFIGURATION_MAX_NAME);
353
354
            lpgroups->lpgroups[i].repetitions = 1;
            lpgroups->lpgroups_count++;
355
356
357
358
            for (j = 0, lpt = 0; j < subse_count; j++)
            {
                if (subse[j].type == SE_KEY)
                {
359
360
                   cf_getKey(*handle, subsh, subse[j].name, data, sizeof(data));
                   //printf("key: %s value: %s\n", subse[j].name, data);
361
362
                   if (strcmp("repetitions", subse[j].name) == 0)
                   {
363
364
                       lpgroups->lpgroups[i].repetitions = atoi(data);
		       //printf("\n Repetitions: %ld ", lpgroups->lpgroups[i].repetitions);
365
366
367
                   }
                   else
                   {
368
369
370
                       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;
371
                       // assume these are lptypes and counts
372
373
374
375
376
377
378
379
380
381
382
                       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';
                       }
383
384
                       // add to anno map
                       check_add_lp_type_anno(nm, anno, lpgroups);
385
386
                       lpgroups->lpgroups[i].lptypes[lpt].count = atoi(data);
                       lpgroups->lpgroups[i].lptypes_count++;
387
388
389
390
                       lpt++;
                   }
                }
            }
391
            cf_closeSection(*handle, subsh);
392
393
394
        }
    }

395
    cf_closeSection(*handle, sh);
396
397
398
    
    return 0;
}
Philip Carns's avatar
Philip Carns committed
399

400
401
402
403
404
/*
 * 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
405
406
 * If anno is not found or a NULL anno is passed in,
 * -1 is returned */
407
408
int configuration_get_annotation_index(const char *              anno,
                                       const config_anno_map_t * anno_map){
409
    if (anno == NULL) return -1;
410
    for (uint64_t i = 0; i < anno_map->num_annos; i++){
411
        if (!strcmp(anno, anno_map->annotations[i])){
412
413
414
415
416
417
            return (int)i;
        }
    }
    return -1;
}

Philip Carns's avatar
Philip Carns committed
418
419
420
421
422
423
424
425
/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ts=8 sts=4 sw=4 expandtab
 */