diff --git a/pgworker/pgworker/pg_worker.c b/pgworker/pgworker/pg_worker.c index 3dc65d7..408c8dc 100644 --- a/pgworker/pgworker/pg_worker.c +++ b/pgworker/pgworker/pg_worker.c @@ -1,7 +1,7 @@ /* - Copyright (C) 2004, Wolfgang Hottgenroth + Copyright (C) 2004, 2005 Wolfgang Hottgenroth - This file is part of smmapdfw. + This file is part of smmapdfw-pgworker. smmapdfw is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,8 +18,10 @@ Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + #include #include +#include #include @@ -49,6 +51,7 @@ typedef struct pg_container_handle_s { int counter; cfgl_t *cfg; char *sql_statement; + int param_cnt; char *input_delimiter; char *output_format_string; } pg_container_handle_t; @@ -56,17 +59,89 @@ typedef struct pg_container_handle_s { typedef struct pg_worker_handle_s { int counter; pg_container_handle_t *pch; + char **param_array; /* pre-allocated space for separated params */ } pg_worker_handle_t; +int debug = 0; + + +#define MAX_PARAM_DIGIT_NUM 2 +#define MAX_PARAM_COUNT 99 +int count_params(const char *stmt) { + const char *paramPtr = stmt; + const char *spacePtr; + char numBuf[MAX_PARAM_DIGIT_NUM + 1]; + char checkArray[MAX_PARAM_COUNT]; + int i, x, cnt=0, done, res=0; + + memset(checkArray, 0, MAX_PARAM_COUNT); + + if (debug) syslog(LOG_DEBUG, "pgworker count_params: start %s", paramPtr); + while ((paramPtr = strchr(paramPtr, '$')) && (res == 0)) { + paramPtr++; + if (debug) syslog(LOG_DEBUG, "pgworker count_params: step %s", paramPtr); + for (i = 0, done = 0; (i <= MAX_PARAM_DIGIT_NUM) && !done; i++) { + if (isdigit(*paramPtr)) { + numBuf[i] = *paramPtr; + if (debug) syslog(LOG_DEBUG, "pgworker count_params: i=%d, nb=%c", i, numBuf[i]); + paramPtr++; + } else { + numBuf[i] = '\0'; + if (debug) syslog(LOG_DEBUG, "pgworker count_params: end, i=%d, nb=%s", i, numBuf); + x = atoi(numBuf); + if (x == 0) { + syslog(LOG_ERR, "pgworker count_params: failure, x=0"); + break; + } + checkArray[x-1] = 1; + cnt++; + done = 1; + } + } + if (!done) { + syslog(LOG_ERR, "pgworker count_params: not done, failure"); + res = -1; + break; + } + } + + if (done) { + for (i = 0; (i <= MAX_PARAM_COUNT) && checkArray[i]; i++); + if (i != cnt) { + syslog(LOG_ERR, "pgworker count_params: none continuous sequence of param numbers, failure"); + res = -1; + } else { + if (debug) syslog(LOG_DEBUG, "pgworker count_params: %d params", cnt); + res = cnt; + } + } + + if (debug) syslog(LOG_DEBUG, "pgworker count_params: finish, res=%d", res); + return res; +} + + int pg_worker_init(cfgl_t *cfg, void **handle) { pg_container_handle_t *pch = (pg_container_handle_t*)htmalloc(sizeof(pg_container_handle_t)); pch->counter = 0; pch->cfg = cfg; + debug = atoi(findcfglx(pch->cfg, "debug", "0")); pch->sql_statement = findcfgl(pch->cfg, "sql_statement"); + if (pch->sql_statement == NULL) { + syslog(LOG_ERR, "pgworker pg_worker_init: missing SQL statement"); + return -1; + } + pch->param_cnt = count_params(pch->sql_statement); + if (pch->param_cnt <= 0) + return -1; pch->input_delimiter = findcfgl(pch->cfg, "input_delimiter"); - pch->output_format_string = findcfgl(pch->cfg, "output_format_string", "$0"); + if ((pch->param_cnt > 1) && (pch->input_delimiter == NULL)) { + syslog(LOG_ERR, "pgworker pg_worker_init: more than one parameter but no input_delimiter given"); + return -1; + } + pch->output_format_string = findcfgl(pch->cfg, "output_format_string"); *handle = pch; return 0; } @@ -82,12 +157,16 @@ int pg_worker_work_setup(void *handle, void **work_handle) { pwh->counter = 0; pwh->pch = handle; *work_handle = pwh; + pwh->param_array = (char **) htmalloc(sizeof(char*) * pwh->pch->param_cnt); + syslog(LOG_DEBUG, "pgworker c=%p w=%p", pwh->pch, pwh); return 0; } int pg_worker_work_destroy(void *handle, void *work_handle) { - syslog(LOG_DEBUG, "pg_worker_destroy: freeing the worker handle"); - free(work_handle); + pg_worker_handle_t *pwh = (pg_worker_handle_t*) work_handle; + syslog(LOG_DEBUG, "pgworker (%p) pg_worker_destroy: freeing the worker handle", pwh); + free(pwh->param_array); + free(pwh); } int pg_worker_work(void *handle, void *work_handle, char *input, char *output) { @@ -95,6 +174,8 @@ int pg_worker_work(void *handle, void *work_handle, char *input, char *output) { pg_container_handle_t *pch = (pg_container_handle_t*) handle; pg_worker_handle_t *pwh = (pg_worker_handle_t*) work_handle; + syslog(LOG_DEBUG, "pgworker (%p) pg_worker_work entered", pwh); + sprintf(output, "pg-worker receives %s (pch %p, pwh %p) (called %d)\n", input, pch, pwh, pwh->counter++); @@ -103,22 +184,61 @@ int pg_worker_work(void *handle, void *work_handle, char *input, char *output) { return SMM_OK; } -int process(pg_worker_handle_t *pwh, char *input, char *output) { - /* pwh->pch->psql_statement is something like - SELECT m.mailRoutingAddress - FROM mailAddress_t m, - domain_t d - WHERE m.address = $1 AND - d.name = $2 AND - d.id = m.domain - */ - - + +int break_input(pg_worker_handle_t *pwh, char *input) { + char *param, *nextptr; + int cnt=0; + + if (pwh->pch->input_delimiter == NULL) { + syslog(LOG_DEBUG, "pgworker (%p) break_input: input is %s", pwh, input); + pwh->param_array[0] = input; + } else { + nextptr = input; + while (NULL != (param = strstr(nextptr, pwh->pch->input_delimiter))) { + *param = '\0'; + if (cnt >= pwh->pch->param_cnt) { + syslog(LOG_ERR, "pgworker (%p) break_input: too much parameters", pwh); + return -1; + } + pwh->param_array[cnt] = nextptr; + cnt++; + syslog(LOG_DEBUG, "pgworker (%p) break_input: param found (cnt=%d): {%s}", pwh, cnt, nextptr); + nextptr = param + strlen(pwh->pch->input_delimiter); + } + + /* last */ + if (cnt >= pwh->pch->param_cnt) { + syslog(LOG_ERR, "pgworker (%p) break_input: too much parameters", pwh); + return -1; + } + pwh->param_array[cnt] = nextptr; + cnt++; + syslog(LOG_DEBUG, "pgworker (%p) break_input: last param (cnt=%d): {%s}", pwh, cnt, nextptr); + + if (cnt < pwh->pch->param_cnt) { + syslog(LOG_ERR, "pgworker (%p) break_input: too few parameters", pwh); + return -1; + } + + syslog(LOG_DEBUG, "pgworker (%p) break_input: end", pwh); + } return 0; } +int process(pg_worker_handle_t *pwh, char *input, char *output) { + int i, res; + + if (0 == (res = break_input(pwh, input))) { + for (i = 0; i < pwh->pch->param_cnt; i++) { + syslog(LOG_DEBUG, "pgworker (%p) process: param %d --> %s", pwh, i+1, pwh->param_array[i]); + } + } + + return res; +} + /** A: - An instance of the pgworker will get an SQL-statement.