smash-MPI

A runtime library for injecting faults and delays into Open MPI.
git clone git@git.mpah.dev/smash-MPI.git
Log | Files | Refs | README | LICENSE

parser.c (3163B)


      1 #include <fcntl.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <sys/mman.h>
      6 #include <sys/stat.h>
      7 #include <stdlib.h>
      8 #include <unistd.h>
      9 #include <regex.h>
     10 
     11 #include "parser.h"
     12 
     13 static void *
     14 smash_load_file_in_memory(const char *filename, size_t *data_size)
     15 {
     16 	int fd;
     17 	char *data;
     18 	struct stat finfo;
     19 
     20 	if ((fd = open(filename, O_RDONLY, S_IRUSR | S_IWUSR)) < 0)
     21 		goto err1;
     22 
     23 	if (fstat(fd, &finfo) < 0)
     24 		goto err2;
     25 
     26 	if ((data = mmap(NULL, finfo.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0))
     27 			== MAP_FAILED)
     28 		goto err2;
     29 
     30 	*data_size = finfo.st_size;
     31 	close(fd);
     32 	return data;
     33 err2:
     34 	close(fd);
     35 err1:
     36 	return NULL;
     37 }
     38 
     39 static void
     40 smash_populate_delay(const char *line, size_t n, const regmatch_t *rm, struct cfg_delays *delays)
     41 {
     42 	delays->delays[n].src = strtol(line + rm[1].rm_so, NULL, 10);
     43 	delays->delays[n].dst = strtol(line + rm[2].rm_so, NULL, 10);
     44 	delays->delays[n].delay = strtol(line + rm[3].rm_so, NULL, 10);
     45 	delays->delays[n].msg = strtol(line + rm[4].rm_so, NULL, 10);
     46 }
     47 
     48 static void
     49 smash_populate_failure(const char *line, size_t n, const regmatch_t *rm, struct cfg_failures *failures)
     50 {
     51 	failures->failures[n].node = strtol(line + rm[1].rm_so, NULL, 10);
     52 	failures->failures[n].time = strtol(line + rm[2].rm_so, NULL, 10);
     53 }
     54 
     55 static char *
     56 smash_get_config_path(enum CFG ctype)
     57 {
     58 	return getenv((ctype == CFG_DELAY ? CFG_DELAY_PATH : CFG_FAILURE_PATH));
     59 }
     60 
     61 static int
     62 count_lines(const char *rs)
     63 {
     64 	int lines = 0;
     65 	while (*(rs)++ != '\0')
     66 		if (*rs == '\n' || *rs == '\r')
     67 			lines++;
     68 	return lines;
     69 }
     70 
     71 int
     72 smash_parse_cfg(enum CFG ctype, void **cfg)
     73 {
     74 	struct cfg_delays *delays;
     75 	struct cfg_failures *failures;
     76 	void *data;
     77 	int ret, lines;
     78 	size_t data_size, nline, n_cfg;
     79 	char *config_path, *line, err_buf[100];
     80 	const char *rs;
     81 	regex_t r;
     82 	regmatch_t rm[5];
     83 	void (*f)();
     84 
     85 	if (!(config_path = smash_get_config_path(ctype))) {
     86 		*cfg = NULL;
     87 		return ctype == CFG_DELAY ? -1 : 0;
     88 	}
     89 
     90 	if (!(data = smash_load_file_in_memory(config_path, &data_size)))
     91 		return -1;
     92 
     93 	lines = count_lines(data);
     94 	*cfg = malloc(ctype == CFG_DELAY ? sizeof(struct cfg_delays) +
     95 					      lines * sizeof(struct cfg_delay)
     96 					: sizeof(struct cfg_failures) +
     97 					      lines * sizeof(struct cfg_delay));
     98 
     99 	if (ctype == CFG_DELAY) {
    100 		delays = *cfg;
    101 		delays->size = lines;
    102 		rs = "([0-9]+);([0-9]+);([0-9]+);(-?[0-9]+)";
    103 		n_cfg = 5;
    104 		f = smash_populate_delay;
    105 	} else {
    106 		failures = *cfg;
    107 		failures->size = lines;
    108 		rs = "([0-9]+);([0-9]+)";
    109 		n_cfg = 3;
    110 		f = smash_populate_failure;
    111 	}
    112 
    113 	if ((ret = regcomp(&r, rs, REG_EXTENDED)) != 0) {
    114 		regerror(ret, &r, err_buf, 100);
    115 		fprintf(stderr, "failed to compile regex <%s>:%s\n", rs,
    116 			err_buf);
    117 		goto err;
    118 	}
    119 
    120 	nline = 0;
    121 	line = strtok(data, "\n");
    122 	while (line) {
    123 		/* if line is a comment or snaphot, do smth */
    124 		if ((ret = regexec(&r, line, n_cfg, rm, 0)) != 0) {
    125 			regerror(ret, &r, err_buf, 100);
    126 			fprintf(stderr, "line %ld: %s\n", nline + 1, err_buf);
    127 			goto err;
    128 		}
    129 		f(line, nline, rm, *cfg);
    130 		nline++;
    131 		line = strtok(NULL, "\n");
    132 	}
    133 
    134 	regfree(&r);
    135 	munmap(data, data_size);
    136 	return 0;
    137 err:
    138 	regfree(&r);
    139 	munmap(data, data_size);
    140 	return -1;
    141 }