configuration.c 12.8 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
    int w = configuration_get_value(handle, section_name, key_name, annotation, tmp,
127
            length);
128
129
    if (w <= 0)
        return w;
130
131

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

    free(tmp);
    return w;
}

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

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

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

    return rc;
}

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

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

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

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

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

    return rc;
}

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

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

340
    memset (lpgroups, 0, sizeof(*lpgroups));
341

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

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

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

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

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