Zebra api extension tuned for SWIG
authorpop <pop>
Thu, 15 Sep 2005 09:27:18 +0000 (09:27 +0000)
committerpop <pop>
Thu, 15 Sep 2005 09:27:18 +0000 (09:27 +0000)
include/idzebra/api_swig.h [new file with mode: 0644]
include/idzebra/res.h
index/Makefile.am
index/api_swig.c [new file with mode: 0644]
index/zebraapi.c
util/res.c

diff --git a/include/idzebra/api_swig.h b/include/idzebra/api_swig.h
new file mode 100644 (file)
index 0000000..5d24224
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef API_SWIG_H
+#define API_SWIG_H
+
+#include <idzebra/res.h>
+#include <idzebra/api.h>
+
+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__ "<unknown>"
+# 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 */
index 68e2c90..fb2662a 100644 (file)
@@ -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
index 4fdeb38..3e1d7b6 100644 (file)
@@ -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 (file)
index 0000000..1abcb64
--- /dev/null
@@ -0,0 +1,320 @@
+#include <idzebra/api_swig.h>
+#include <idzebra/res.h>
+#include <idzebra/api.h>
+#include <stdarg.h>
+#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 = "<unknown>";
+      
+  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);
+  }
+}
index 2ffaed2..88540c0 100644 (file)
@@ -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 =
index 417cc0a..c5ebcea 100644 (file)
@@ -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 <yaz/yaz-util.h>
 #include <idzebra/res.h>
 
+#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);
+  }
+}