diff options
Diffstat (limited to 'src/error.c')
-rw-r--r-- | src/error.c | 206 |
1 files changed, 179 insertions, 27 deletions
diff --git a/src/error.c b/src/error.c index fc13cad..6698ff8 100644 --- a/src/error.c +++ b/src/error.c @@ -6,6 +6,7 @@ #include <fcntl.h> #include <errno.h> #include <stdlib.h> +#include <limits.h> #include "config.h" @@ -281,33 +282,46 @@ static int prepare_config_error(struct lt_config_app *cfg, int n) { struct lt_error_app_return *ret; - struct lt_error_def *error_def = <_sh(cfg, error_def); - int i = 0; + struct lt_error_config *cfg_err; + int sym_cnt = 0; - bzero(error_def, sizeof(struct lt_error_def)); + /* get the nymber of configured symbols */ + lt_list_for_each_entry(ret, &run->head_return, list_run) { + struct lt_error_app_return_sym *sym; + lt_list_for_each_entry(sym, &ret->head_sym, list) + sym_cnt++; + } + + PRINT_VERBOSE(cfg, 1, "number of symbols %d\n", sym_cnt); + + cfg_err = malloc(sizeof(*cfg_err) + + sym_cnt * sizeof(struct lt_error_config_sym)); + if (!cfg_err) + return -ENOMEM; + + cfg_err->sym_cnt = sym_cnt; + cfg_err->n = n; + + sym_cnt = 0; lt_list_for_each_entry(ret, &run->head_return, list_run) { struct lt_error_app_return_sym *sym; lt_list_for_each_entry(sym, &ret->head_sym, list) { - struct lt_error_def_sym *sym_def; + struct lt_error_config_sym *cfg_sym; - sym_def = &error_def->sym[i]; - strncpy(sym_def->symbol, sym->name, LT_MAXNAME); - sym_def->ret = sym->val; - sym_def->filter.type = ret->filter.type; - sym_def->handle_sigsegv = sym->handle_sigsegv; + cfg_sym = &cfg_err->sym[sym_cnt++]; + strncpy(cfg_sym->symbol, sym->name, LT_MAXNAME); + cfg_sym->ret = sym->val; + cfg_sym->filter.type = ret->filter.type; + cfg_sym->handle_sigsegv = sym->handle_sigsegv; PRINT_VERBOSE(cfg, 1, "symbol %s, ret %s\n", sym->name, sym->val); - - if (i++ >= LT_ERROR_MAXSYM) - return -1; } } - lt_sh(cfg, error_def.n) = n; - PRINT_VERBOSE(cfg, 1, "N = %d\n", n); + cfg->error_config = cfg_err; return 0; } @@ -376,18 +390,82 @@ static int process_run(struct lt_config_app *cfg, return 0; } -static int process_go(struct lt_config_app *cfg, char *dir_base, - struct lt_error_app *app, - struct lt_error_app_go *go) +static int process_automated_cb(struct lt_config_app *cfg, + struct lt_thread *t, + struct lt_fifo_mbase *mbase) { - static char dir[LT_MAXFILE]; - int i; + return 0; +} - if (!app->no_storage && - dir_go(cfg, dir, dir_base, go)) +static int automated_get_all_syms(struct lt_config_app *cfg, + struct lt_error_app_go *go) +{ + struct lt_list_head *sym_all = &cfg->error_symbols_all; + struct lt_error_app_run *run; + int count = 0; + + lt_list_for_each_entry(run, &go->head_run, list_go) { + struct lt_error_app_return *ret; + + lt_list_for_each_entry(ret, &run->head_return, list_run) { + struct lt_error_app_return_sym *sym; + + lt_list_for_each_entry(sym, &ret->head_sym, list) { + lt_list_move_tail(&sym->list, sym_all); + count++; + } + } + } + + return count; +} + +static int process_go_automated(struct lt_config_app *cfg, char *dir, + struct lt_error_app *app, + struct lt_error_app_go *go) +{ + int ret = 0; + + if (lt_process_register(cfg, process_automated_cb)) return -1; - PRINT_VERBOSE(cfg, 1, "dir '%s'\n", dir); + if (!automated_get_all_syms(cfg, go)) { + PRINT_VERBOSE(cfg, 1, "no symbols defined\n"); + return -1; + } + + /* TODO + * 1) first run with no symbols + * 2) after each run add new symbol to the 'cur' list from global 'all' list + * 3) 'cur' list has fresh reallocated symbols giving the position and return + * for each symbol occurence + * 4) each 'cur' list symbol moves to new return value if all symbols 'below' it + * has changed all their return values + * 5) finish when first symbol cycles its all return values + * 6) repeating till there are new symbols (from 'all' list) visible + * + */ + + BUG_ON(lt_process_unregister(cfg, process_automated_cb)); + + return ret; +} + +static int process_go_replay(struct lt_config_app *cfg, char *dir, + struct lt_error_app *app, + struct lt_error_app_go *go) +{ + return 0; +} + +static int process_go_configured(struct lt_config_app *cfg, char *dir, + struct lt_error_app *app, + struct lt_error_app_go *go) +{ + int i; + + PRINT_VERBOSE(cfg, 1, "dir '%s', name %s, start %d, n %d\n", + dir, go->name, go->start, go->n); for(i = go->start; i < (go->start + go->n); i++) { struct lt_error_app_run *run; @@ -400,6 +478,28 @@ static int process_go(struct lt_config_app *cfg, char *dir_base, return 0; } +static int process_go(struct lt_config_app *cfg, char *dir_base, + struct lt_error_app *app, + struct lt_error_app_go *go) +{ + static char dir[LT_MAXFILE]; + + if (!app->no_storage && + dir_go(cfg, dir, dir_base, go)) + return -1; + + /* automated processing.. God save us */ + if (go->automated) + return process_go_automated(cfg, dir, app, go); + + /* exact symbols return replay */ + if (go->replay) + return process_go_replay(cfg, dir, app, go); + + /* Whatever user configuration wants.. */ + return process_go_configured(cfg, dir, app, go); +} + int lt_error_run(struct lt_config_app *cfg) { struct lt_error_app *app = cfg->error_app; @@ -493,7 +593,7 @@ int lt_error_run_return(struct lt_config_app *cfg, PRINT_VERBOSE(cfg, 1, "return %s, empty %d\n", ret->name, lt_list_empty(&ret->list_run)); - /* TODO Allow more than 1 RUN assignment to GO, + /* TODO Allow more than 1 RETURN assignment to RUN, * so far only one assignment is allowed. */ if (!lt_list_empty(&ret->list_run)) return -EINVAL; @@ -558,6 +658,7 @@ int lt_error_go(struct lt_config_app *cfg, struct lt_error_app_go **go, struct lt_error_app *error_app, char *name, int start, int n, + int automated, int replay, struct lt_list_head *runs) { struct lt_error_app_go *app_go = *go; @@ -574,6 +675,8 @@ int lt_error_go(struct lt_config_app *cfg, app_go->n = n; app_go->start = start; app_go->name = name; + app_go->automated = automated; + app_go->replay = replay; lt_list_for_each_entry_safe(ln, h, runs, list) { struct lt_error_app_run *run; @@ -625,11 +728,13 @@ app_return_get(struct lt_config_app *cfg, struct lt_error_app_return **ret) int lt_error_return_ass(struct lt_config_app *cfg, struct lt_error_app_return **ret, - char *name, unsigned long val, - int handle_sigsegv) + char *name, struct lt_list_head *list_vals, + int handle_sigsegv, int keep) { struct lt_error_app_return *app_ret = app_return_get(cfg, ret); struct lt_error_app_return_sym *sym; + struct lt_config_ln *ln, *h; + int vals_cnt = 0; if (!app_ret) return -ENOMEM; @@ -639,11 +744,41 @@ int lt_error_return_ass(struct lt_config_app *cfg, return -ENOMEM; sym->name = strdup(name); - sym->val = val; sym->handle_sigsegv = handle_sigsegv; + sym->keep = keep; - PRINT_VERBOSE(cfg, 1, "%s = %ld\n", sym->name, val); + /* process return values name list */ + lt_list_for_each_entry_safe(ln, h, list_vals, list) { + if (vals_cnt == LT_MAX_SYM_RETURNS) { + PRINT_VERBOSE(cfg, 1, + "failed: too many return values for (%d allowed) for symbol %s\n", + LT_MAX_SYM_RETURNS, name); + return -1; + } + + BUG_ON(ln->type != LT_CONFIG_LN_VALUE); + + sym->vals[vals_cnt++] = ln->val; + + lt_list_del(&ln->list); + free(ln); + } + + PRINT_VERBOSE(cfg, 1, "%s = %ld, handle_sigsegv = %d, keep %d\n", + sym->name, sym->val, handle_sigsegv, keep); + + if (vals_cnt > 1) { + int i; + + for(i = 0; i < vals_cnt; i++) + PRINT_VERBOSE(cfg, 1, + "\tret[%d] = %lu\n", + i, sym->vals[i]); + } + + /* It's essential we keep the user + * defined sequenece of symbols. */ lt_list_add_tail(&sym->list, &app_ret->head_sym); return 0; } @@ -673,3 +808,20 @@ int lt_error_app_init(struct lt_error_app *app) app->no_storage = 1; return 0; } + +int lt_error_config_write(struct lt_config_app *cfg, int fd) +{ + struct lt_error_config *cfg_err = cfg->error_config; + int size = sizeof(struct lt_error_config); + + BUG_ON(!cfg_err); + + size += cfg_err->sym_cnt * sizeof(struct lt_error_config_sym); + + if (size != write(fd, cfg_err, size)) { + perror("write failed"); + return -1; + } + + return 0; +} |