summaryrefslogtreecommitdiffstats
path: root/src/error.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/error.c')
-rw-r--r--src/error.c206
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 = &lt_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;
+}