From: pop Date: Thu, 15 Sep 2005 09:27:18 +0000 (+0000) Subject: Zebra api extension tuned for SWIG X-Git-Tag: before.bug.529~321 X-Git-Url: http://git.indexdata.com/?p=idzebra-moved-to-github.git;a=commitdiff_plain;h=7f02bad575a64004a3a0122a99666afd41dd8966 Zebra api extension tuned for SWIG --- diff --git a/include/idzebra/api_swig.h b/include/idzebra/api_swig.h new file mode 100644 index 0000000..5d24224 --- /dev/null +++ b/include/idzebra/api_swig.h @@ -0,0 +1,106 @@ +#ifndef API_SWIG_H +#define API_SWIG_H + +#include +#include + +typedef short IDZEBRA_RES; +#define RES_LIST char** res_args + +/* +------------------------------------------------------------------------------- + API Calls +------------------------------------------------------------------------------- +*/ +void idzebra_api_init(void); + +char **api_errors(void); + +int api_check_error(void); + +void api_clear_error(void); + + +ZebraService idzebra_start (RES_LIST); + +IDZEBRA_RES idzebra_stop(ZebraService zs); + + +ZebraHandle idzebra_open (ZebraService zs, RES_LIST); + +IDZEBRA_RES idzebra_close(ZebraHandle zh); + +IDZEBRA_RES idzebra_samplefunc(ZebraHandle zh, RES_LIST); + + +/* +------------------------------------------------------------------------------- + Utility functions for argument handling +------------------------------------------------------------------------------- +*/ + +#if __STDC_VERSION__ < 199901L +# if __GNUC__ >= 2 +# define __func__ __FUNCTION__ +# else +# define __func__ "" +# endif +#endif + +#define API_SET_CONTEXT api_error_context = __func__ + +void args_parse_res (Res r, + const char **valid_args, + Res skip, + char **args); + +void args_use (ZebraHandle zh, + Res r, + Res rr, + int mandatory, + const char **args); + +#define ARG_MODE_OPTIONAL 0 +#define ARG_MODE_MANDATORY 1 +#define ARG_MODE_FORCE 2 + +#define RES_OPEN(var,def,over) \ + var = res_open(def, over); \ + res_set(var,"__context__", __func__ ); \ + +#define ARGS_INIT \ + Res local = 0; \ + Res func_res = 0; \ + Res temp_res = 0; \ + +#define ARGS_PARSE(...) \ + { \ + const char *vargs[] = { __VA_ARGS__ , 0 }; \ + RES_OPEN(func_res, 0, 0); \ + RES_OPEN(local, 0, 0); \ + args_parse_res(func_res, vargs, local, res_args); \ + } \ + +#define ARGS_APPLY \ + temp_res = res_add_over(zh->session_res, func_res); \ + +#define ARGS_PROCESS(mode, ...) \ + { \ + const char *vargs[] = { __VA_ARGS__ , 0 }; \ + args_use(zh, local, func_res, mode, vargs); \ + } \ + +#define ARGS_REVOKE \ + { \ + const char **used; \ + res_remove_over(temp_res); \ + used = res_get_array(local, "_used"); \ + args_use(zh, zh->session_res, 0, ARG_MODE_FORCE, used); \ + free_array(used); \ + } \ + +#define ARGS_DONE \ + if (func_res) res_close(func_res); \ + if (local) res_close(local); \ + +#endif /* API_SWIG_H */ diff --git a/include/idzebra/res.h b/include/idzebra/res.h index 68e2c90..fb2662a 100644 --- a/include/idzebra/res.h +++ b/include/idzebra/res.h @@ -1,4 +1,4 @@ -/* $Id: res.h,v 1.7 2005-09-13 11:51:06 adam Exp $ +/* $Id: res.h,v 1.8 2005-09-15 09:27:18 pop Exp $ Copyright (C) 1995-2005 Index Data ApS @@ -67,6 +67,30 @@ const char *res_get_prefix(Res r, const char *name, const char *prefix, YAZ_EXPORT ZEBRA_RES res_get_int(Res r, const char *name, int *val); + +/* == pop ================================================================= */ + +YAZ_EXPORT +Res res_add_over (Res p, Res t); + +YAZ_EXPORT +void res_remove_over (Res r); + +YAZ_EXPORT +void res_close_over (Res r); + +YAZ_EXPORT +void res_add (Res r, const char *name, const char *value); + +YAZ_EXPORT +char **res_2_array (Res r); + +YAZ_EXPORT +char **res_get_array(Res r, const char* name); + +YAZ_EXPORT +void res_dump (Res r, int level); + YAZ_END_CDECL #endif diff --git a/index/Makefile.am b/index/Makefile.am index 4fdeb38..3e1d7b6 100644 --- a/index/Makefile.am +++ b/index/Makefile.am @@ -1,4 +1,4 @@ -## $Id: Makefile.am,v 1.32 2005-08-19 09:21:34 adam Exp $ +## $Id: Makefile.am,v 1.33 2005-09-15 09:27:18 pop Exp $ noinst_PROGRAMS = apitest kdump @@ -6,7 +6,8 @@ lib_LTLIBRARIES = libidzebra-api.la libidzebra_api_la_SOURCES = dir.c dirs.c trav.c kinput.c kcompare.c \ attribute.c symtab.c recindex.c recstat.c lockutil.c \ - zebraapi.c zinfo.c invstat.c sortidx.c compact.c zsets.c zrpn.c \ + zebraapi.c api_swig.c \ + zinfo.c invstat.c sortidx.c compact.c zsets.c zrpn.c \ rank1.c trunc.c retrieve.c extract.c rankstatic.c \ index.h recindex.h recindxp.h \ zinfo.h zserver.h zvrank.c limit.c kcontrol.c diff --git a/index/api_swig.c b/index/api_swig.c new file mode 100644 index 0000000..1abcb64 --- /dev/null +++ b/index/api_swig.c @@ -0,0 +1,320 @@ +#include +#include +#include +#include +#include "index.h" + +#define DEFAULT_APPROX_LIMIT 2000000000 + +/* == API errors, debug ==================================================== */ +static Res api_error = 0; +const char* api_error_context = 0; +void api_add_error(const char *fmt, ...); +void api_clear_error(void); +void free_array(const char **args); +ZebraHandle zebra_get_handle (ZebraService zs); + + +/* == API init, destroy =================================================== */ +void idzebra_api_init(void) +{ + yaz_log_init_prefix("API_SWIG"); + yaz_log(YLOG_LOG, "IDZebra API initialized"); +} + +/* == Service start/stop =================================================== */ + +ZebraService idzebra_start(RES_LIST) +{ + ZebraService zs = 0; + + ARGS_INIT; + API_SET_CONTEXT; + + ARGS_PARSE ("configName", + "chdir", + "modulePath", + "profilePath", + "register", + "shadow", + "isam", + "keyTmpDir", + "setTmpDir", + "lockDir"); + + zs = zebra_start_res(res_get(func_res,"configName"), NULL, func_res); + + /* Function resources are kept for service (zs->global_res); */ + func_res = 0; + ARGS_DONE; + + return (zs); +} + +IDZEBRA_RES idzebra_stop(ZebraService zs) +{ + /* Global res have an over part here */ + res_close_over(zs->global_res); + return (zebra_stop(zs)); +} + +/* == Session open/close =================================================== */ +ZebraHandle idzebra_open (ZebraService zs, RES_LIST) +{ + + ZebraHandle zh; + + ARGS_INIT; + API_SET_CONTEXT; + + ARGS_PARSE ("tempfiles", + "openRW", + "memmax", + "encoding", + "estimatehits", + "staticrank"); + + zh = zebra_open(zs, func_res); + + /* Function resources are kept for session (zh->res->over_res); */ + func_res = 0; + ARGS_DONE; + + yaz_log (YLOG_DEBUG, "zebra_open zs=%p returns %p", zs, zh); + + return (zh); +} + +IDZEBRA_RES idzebra_close(ZebraHandle zh) +{ + res_close_over(zh->session_res); + return (zebra_close(zh)); +} +/* == Sample function == =================================================== */ +IDZEBRA_RES idzebra_samplefunc(ZebraHandle zh, RES_LIST) +{ + ARGS_INIT; + API_SET_CONTEXT; + ARGS_PARSE("strucc"); + ARGS_PROCESS(ARG_MODE_OPTIONAL,"encoding"); + ARGS_APPLY; + + yaz_log (YLOG_DEBUG, "Got strucc:%s\n",res_get(zh->res,"strucc")); + res_dump (zh->res,0); + + ARGS_REVOKE; + ARGS_DONE; + return (ZEBRA_OK); +} + + +/* +------------------------------------------------------------------------------- + Utility functions for argument handling +------------------------------------------------------------------------------- +*/ +void arg_parse_res (Res r, + const char **valid_args, + Res skip, + char *name, char *value) +{ + if ((name) && (value)) { + int i = 0; + int gotit = 0; + while (valid_args[i]) { + if (!strcmp(name, valid_args[i])) { + res_set(r, name, value); + gotit = 1; + break; + } + i++; + } + if (!gotit) + yaz_log (YLOG_DEBUG, "skip: %s=%s",name, value); + res_add (skip, name, value); + } +} + +void args_parse_res (Res r, + const char **valid_args, + Res skip, + char **args) +{ + char *argname; + char *argvalue; + int i = 0; + if (args) { + while (args[i] && args[i+1]) { + argname = args[i++]; + argvalue = args[i++]; + arg_parse_res (r, valid_args, skip, argname, argvalue); + } + } +} + +/* == special resource handlers ============================================ */ + +void idzebra_res_encoding (ZebraHandle zh, const char *value) +{ + if (value) + zebra_octet_term_encoding(zh, value); + else + zebra_octet_term_encoding(zh, "ISO-8859-1"); + +} + +void idzebra_res_estimatehits (ZebraHandle zh, const char *value) +{ + int val = 0; + if (value) + if (! (sscanf(value, "%d", &val) == 1)) + api_add_error( "Expected integer value for 'estimatehits'"); + + zebra_set_approx_limit(zh, val); +} + +void idzebra_res_staticrank (ZebraHandle zh, const char *value) +{ + int val = 0; + if (value) + if (! (sscanf(value, "%d", &val) == 1)) + api_add_error( "Expected integer value for 'estimatehits'"); + + zh->m_staticrank = val; +} + +/* == applying and revoking call-scope resources =========================== */ + +void arg_use (ZebraHandle zh, + Res r, + Res rr, + int mode, + const char *name) +{ + if (name) { + const char *value = res_get(r, name); + int gotit = 0; + + /* in FORCE mode resource is used with default value also */ + if ((value) || (mode & ARG_MODE_FORCE)) { + + /* encoding */ + if (!strcmp(name,"encoding")) { + idzebra_res_encoding(zh, value); + gotit = 1; + } + + /* estimatehits */ + else if (!strcmp(name,"estimatehits")) { + idzebra_res_estimatehits(zh, value); + gotit = 1; + } + + /* staticrank */ + else if (!strcmp(name,"staticrank")) { + idzebra_res_staticrank(zh, value); + gotit = 1; + } + + /* collects provided arguments in order to revoke them + at the end of the function */ + if (gotit) { + if (! (mode & ARG_MODE_FORCE)) res_add(r, "_used", name); + if ( (rr) && (name) && (value) ) res_add(rr, name, value); + } + } else { + /* value missing */ + if (mode & ARG_MODE_MANDATORY) + api_add_error( "Missing mandatory argument '%s'", name); + } + } +} + +void args_use (ZebraHandle zh, + Res r, + Res rr, + int mode, + const char **args) +{ + int i = 0; + if (args) { + while (args[i]) { + arg_use (zh, r, rr, mode, args[i++]); + } + } +} + +/* == API errors =========================================================== */ + +void api_add_error(const char *fmt, ...) +{ + + va_list ap; + char buf[4096]; + const char *context; + va_start(ap, fmt); + +#ifdef WIN32 + _vsnprintf(buf, sizeof(buf)-1, fmt, ap); +#else +/* !WIN32 */ +#if HAVE_VSNPRINTF + vsnprintf(buf, sizeof(buf), fmt, ap); +#else + vsprintf(buf, fmt, ap); +#endif +#endif + + va_end (ap); + + if (! api_error) + api_error = res_open(0,0); + + if (api_error_context) + context = api_error_context; + else + context = ""; + + res_add(api_error, context, buf); +} + +char **api_errors(void) +{ + static char **res = 0; + + res = res_2_array(api_error); + if (!res) { + res = xmalloc(sizeof(char *)); + res[0] = 0 ; + } + return (&res[0]); + +} + + +int api_check_error(void) +{ + if (api_error) + return (1); + else + return (0); +} + +void api_clear_error(void) +{ + if (api_error) + res_close(api_error); + api_error = 0; +} + +void free_array(const char **args) +{ + int i = 0; + if (args) { + while (args[i]) { + xfree((char *) args[i]); + i++; + } + xfree (args); + } +} diff --git a/index/zebraapi.c b/index/zebraapi.c index 2ffaed2..88540c0 100644 --- a/index/zebraapi.c +++ b/index/zebraapi.c @@ -1,4 +1,4 @@ -/* $Id: zebraapi.c,v 1.185 2005-09-13 11:51:06 adam Exp $ +/* $Id: zebraapi.c,v 1.186 2005-09-15 09:27:18 pop Exp $ Copyright (C) 1995-2005 Index Data ApS @@ -129,6 +129,8 @@ ZebraHandle zebra_open(ZebraService zs, Res res) zh->shadow_enable = 1; zh->m_staticrank = 0; + zebra_open_res(zh); + default_encoding = res_get_def(zh->session_res, "encoding", "ISO-8859-1"); zh->iconv_to_utf8 = diff --git a/util/res.c b/util/res.c index 417cc0a..c5ebcea 100644 --- a/util/res.c +++ b/util/res.c @@ -1,4 +1,4 @@ -/* $Id: res.c,v 1.45 2005-09-13 11:51:11 adam Exp $ +/* $Id: res.c,v 1.46 2005-09-15 09:27:18 pop Exp $ Copyright (C) 1995-2005 Index Data ApS @@ -34,6 +34,8 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include #include +#define YLOG_RES 0 + struct res_entry { char *name; char *value; @@ -224,11 +226,9 @@ ZEBRA_RES res_read_file(Res r, const char *fname) fclose(fr); return ZEBRA_OK; } - Res res_open(Res def_res, Res over_res) { Res r; - r = (Res) xmalloc(sizeof(*r)); r->first = r->last = NULL; r->def_res = def_res; @@ -428,3 +428,117 @@ ZEBRA_RES res_get_int(Res r, const char *name, int *val) } return ZEBRA_FAIL; } + +/* == pop ================================================================= */ +Res res_add_over (Res p, Res t) +{ + if ((!p) || (!t)) + return (0); + + while (p->over_res) + p = p->over_res; + + p->over_res = t; + return (p); +} + +void res_remove_over (Res r) +{ + if (!r) + return; + r->over_res = 0; +} + +void res_close_over (Res r) +{ + if (!r) + return; + if (r->over_res) + res_close(r->over_res); + r->over_res = 0; +} + +void res_add (Res r, const char *name, const char *value) +{ + struct res_entry *re; + assert (r); + if ((name) && (value)) + yaz_log (YLOG_RES, "res_add res=%p, name=%s, value=%s", r, name, value); + + re = add_entry (r); + re->name = xstrdup (name); + re->value = xstrdup_env (value); +} + +char **res_2_array (Res r) +{ + struct res_entry *re; + int i = 0; + char **list; + + if (!r) + return 0; + + list = xmalloc(sizeof(char *)); + + for (re = r->first; re; re=re->next) { + list = xrealloc(list, ((i+3) * sizeof(char *))); + list[i++] = strdup(re->name); + if (re->value) + list[i++] = strdup(re->value); + else + list[i++] = strdup(""); + yaz_log(YLOG_RES, "res2array: %s=%s",re->name, re->value); + } + list[i++] = 0; + return (list); +} + +char **res_get_array(Res r, const char* name) +{ + struct res_entry *re; + int i = 0; + char **list; + + if (!r) + return 0; + + list = xmalloc(sizeof(char *)); + + for (re = r->first; re; re=re->next) + if (re->value && !yaz_matchstr (re->name, name)) + { + list = xrealloc(list, (i+2) * sizeof(char *)); + list[i++] = xstrdup(re->value); + } + + if (i == 0) + return (res_get_array(r->def_res, name)); + + list[i++] = 0; + return (list); +} + +void res_dump (Res r, int level) +{ + struct res_entry *re; + + if (!r) + return; + + printf ("RES:\n", level * 4,""); + + for (re = r->first; re; re=re->next) { + printf("%*s - %s:='%s'\n",level * 4,"",re->name,re->value); + } + + if (r->def_res) { + printf ("%*s DEF ",level * 4,""); + res_dump (r->def_res, level + 1); + } + + if (r->over_res) { + printf ("%*s OVER ",level * 4,""); + res_dump (r->over_res, level + 1); + } +}