First work on Z39.50 persistence.
authorAdam Dickmeiss <adam@indexdata.dk>
Wed, 19 Apr 1995 07:30:56 +0000 (07:30 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Wed, 19 Apr 1995 07:30:56 +0000 (07:30 +0000)
kernel/Makefile
kernel/default.res
kernel/kernel.h
kernel/main.c
kernel/persist.c [new file with mode: 0644]
kernel/urp.c

index 374c050..05f8b6f 100644 (file)
@@ -2,7 +2,10 @@
 # Europagate, 1995
 #
 # $Log: Makefile,v $
-# Revision 1.15  1995/04/17 11:27:29  quinn
+# Revision 1.16  1995/04/19 07:30:56  adam
+# First work on Z39.50 persistence.
+#
+# Revision 1.15  1995/04/17  11:27:29  quinn
 # Smallish
 #
 # Revision 1.14  1995/04/17  09:34:23  adam
 #
 SHELL=/bin/sh
 
-#ZPRE=/home/proj/zdist/zdist102b1-1/libz3950
-#ZINC=-I$(ZPRE)
-#ZLIB=$(ZPRE)/libz3950.a
+ZPRE=/home/proj/zdist/zdist102b1-1/libz3950
+ZINC=-I$(ZPRE)
+ZLIB=$(ZPRE)/libz3950.a
 
-ZLIB=../../yaz/lib/libyaz.a
+#ZLIB=../../yaz/lib/libyaz.a
 
 INCLUDE=-I../include
 #CFLAGS=-g -Wall 
@@ -67,7 +70,7 @@ USELIBS1=../lib/ccl.a ../lib/fml.a ../lib/libzass.a ../lib/libres+log.a \
 ../lib/util.a $(ZLIB) $(REGEXOBJ)
 
 PROG1=kernel
-O1=main.o urp.o
+O1=main.o urp.o persist.o
 
 PROG2=eti
 O2=eti.o
index 67bbac2..a16cfd8 100644 (file)
@@ -1,5 +1,5 @@
 # Email gateway - general kernel resources
-# $Id: default.res,v 1.15 1995/04/17 09:34:25 adam Exp $
+# $Id: default.res,v 1.16 1995/04/19 07:31:00 adam Exp $
 #
 # Important directories, programs, etc.
 gw.reply.mta: /usr/lib/sendmail
@@ -7,7 +7,8 @@ gw.reply.tmp.prefix: gwr
 gw.reply.tmp.dir: /tmp
 #gw.path: /home/adam/egate/kernel
 gw.marc.log: marc.log
-gw.timeout: 60
+gw.timeout: 20
+gw.resultset: 0
 
 # Retrieval settings
 gw.ignore.which: 1
index 7ca0316..dc2adc4 100644 (file)
@@ -2,7 +2,10 @@
  * Europagate, 1995
  *
  * $Log: kernel.h,v $
- * Revision 1.12  1995/04/17 09:34:29  adam
+ * Revision 1.13  1995/04/19 07:31:04  adam
+ * First work on Z39.50 persistence.
+ *
+ * Revision 1.12  1995/04/17  09:34:29  adam
  * Timeout (idletime) adjustable. Minor changes in kernel.
  *
  * Revision 1.11  1995/03/28  11:42:34  adam
 #define LINE_MAX 1024
 
 struct gw_user_set {
-    char *name;        /* name of result set */
-    int hits;          /* -1 on error */
+    char   *name;               /* name of result set */
+    int    hits;                /* -1 on error */
+    char   *database;           /* database(s) in which we search */
+    struct ccl_rpn_node *rpn;   /* rpn request */
+    int    present_flag;        /* present in target (presistency) */
     struct gw_user_set *prev;
 };
 
@@ -82,6 +88,7 @@ struct gw_kernel_info {
     int command_no;
     char  from_str[LINE_MAX+1];
     const char *reply_fname;
+    int setno;
 #if USE_FML
     Fml   fml;
 #endif
@@ -98,10 +105,26 @@ void urp_end     (void);
 
 void read_kernel_res (void);
 
-struct gw_user_set *user_set_add (const char *name, int hits);
+struct gw_user_set *user_set_add (const char *name, int hits,
+                                  const char *database,
+                                 struct ccl_rpn_node *rpn,
+                                 int present_flag);
 struct gw_user_set *user_set_search (const char *name);
 void user_set_init (void);
 
 int lgets (char *buf, int max, int fd);
 
+const struct zass_searchent *zass_p_search (ZASS zass, 
+                                      struct ccl_rpn_node *rpn,
+                                      const char *result_set,
+                                     const char *database,
+                                     struct gw_user_set *sets);
+const struct zass_presentent *zass_p_present (ZASS zass,
+                                      const char *result_set,
+                                     int offset, int number);
+
+int load_p_state (int userid);
+int save_p_state (int userid);
+int reopen_target (void);
+
 #define KERNEL_LOG "kernel"
index 9398e2b..f638c4b 100644 (file)
@@ -2,7 +2,10 @@
  * Europagate, 1995
  *
  * $Log: main.c,v $
- * Revision 1.15  1995/04/17 09:34:30  adam
+ * Revision 1.16  1995/04/19 07:31:07  adam
+ * First work on Z39.50 persistence.
+ *
+ * Revision 1.15  1995/04/17  09:34:30  adam
  * Timeout (idletime) adjustable. Minor changes in kernel.
  *
  * Revision 1.14  1995/03/28  11:42:34  adam
@@ -113,6 +116,8 @@ static void kernel_events (struct str_queue *queue, int userid)
        {
            gw_log (GW_LOG_STAT, KERNEL_LOG, "Timeout after %d seconds", 
                    timeout);
+           if (info.zass)
+               save_p_state (userid);
            break;
        }
        if (FD_ISSET (gip_fd, &set_r))
@@ -133,6 +138,8 @@ static void kernel_events (struct str_queue *queue, int userid)
                 while (lgets (line_buf, sizeof(line_buf)-1, gip_fd))
                     str_queue_enq (queue, line_buf);
                urp_start (continuation, queue);
+                if (!continuation)
+                   load_p_state (userid);      
                urp_command (queue);
                urp_end ();
                 while (str_queue_deq (queue, 0, 0))
@@ -172,6 +179,7 @@ int main (int argc, char **argv)
     info.override_hostname = NULL;
     info.databases = NULL;
     info.database = NULL;
+    info.setno = -1;
 #if USE_FML
     info.fml = NULL;
 #endif
@@ -308,17 +316,20 @@ int main (int argc, char **argv)
         else
             info.default_res = *argv;
     }
-    read_kernel_res ();
     if (!(queue = str_queue_mk ()))
     {
         gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, KERNEL_LOG, "str_queue_mk");
         exit (1);
     }
     if (userid != -1)
+    {
+       read_kernel_res ();
         kernel_events (queue, userid);
+    }
     else
     {
         char line_buf[512];
+        read_kernel_res ();
         while (lgets (line_buf, sizeof(line_buf)-1, 0))
             str_queue_enq (queue, line_buf);
        urp_start (0, queue);
@@ -328,7 +339,10 @@ int main (int argc, char **argv)
     return 0;
 }
 
-struct gw_user_set *user_set_add (const char *name, int hits)
+struct gw_user_set *user_set_add (const char *name, int hits, 
+                                 const char *database, 
+                                 struct ccl_rpn_node *rpn,
+                                 int present_flag)
 {
     struct gw_user_set *s;
 
@@ -337,6 +351,9 @@ struct gw_user_set *user_set_add (const char *name, int hits)
 
     s->name = gw_strdup (name);
     s->hits = hits;
+    s->database = gw_strdup (database);
+    s->rpn = rpn;
+    s->present_flag = present_flag;
     s->prev = info.sets;
     info.sets = s;
     return s;
@@ -349,6 +366,8 @@ void user_set_init (void)
     for (s = info.sets; s; s = s1)
     {
         free (s->name);
+       free (s->database);
+       ccl_rpn_delete (s->rpn);
         s1 = s->prev;
         free (s);
     }
@@ -510,6 +529,8 @@ void read_kernel_res (void)
     if (info.override_hostname)
         strncpy (info.hostname, info.override_hostname,
                  sizeof(info.hostname)-1);
+    v = gw_res_get (info.kernel_res, "gw.result.set", NULL);
+    info.setno = v ? -1 : 0;
 #if USE_FML
     if (!info.fml)
     {
diff --git a/kernel/persist.c b/kernel/persist.c
new file mode 100644 (file)
index 0000000..e341536
--- /dev/null
@@ -0,0 +1,285 @@
+/* Gateway kernel - Z39.50 Persistence
+ * Europagate, 1995
+ *
+ * $Log: persist.c,v $
+ * Revision 1.1  1995/04/19 07:31:10  adam
+ * First work on Z39.50 persistence.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "kernel.h"
+
+static int set_change;
+
+static int obtain_set (ZASS zass, struct gw_user_set *set)
+{
+    const struct zass_searchent *p;
+
+    p = zass_search (zass, set->rpn, set->name, set->database);
+    if (!p)
+        return 2;
+    if (p->errcode != -1)
+        return 3;
+    if (p->num != set->hits)
+        set_change = 1;
+    set->present_flag = 1;
+    set->hits = p->num;
+    return 0;
+}
+
+static int obtain_sets (ZASS zass, struct ccl_rpn_node *rpn, 
+                        struct gw_user_set *sets)
+{
+    struct gw_user_set *set;
+    int r;
+
+    switch (rpn->kind)
+    {
+    case CCL_RPN_AND:
+    case CCL_RPN_OR:
+    case CCL_RPN_NOT:
+    case CCL_RPN_PROX:
+        if ((r=obtain_sets (zass, rpn->u.p[0], sets)))
+           return r;
+       return obtain_sets (zass, rpn->u.p[1], sets);
+    case CCL_RPN_TERM:
+       return 0;
+    case CCL_RPN_SET:
+        set = user_set_search (rpn->u.setname);
+       if (!set)
+           return 1;
+       if (set->present_flag)
+           return 0;
+    }
+    return obtain_set (zass, set);
+}
+
+const struct zass_searchent *zass_p_search (ZASS zass, 
+                       struct ccl_rpn_node *rpn, 
+                       const char *result_set,
+                       const char *database,
+                       struct gw_user_set *sets)
+{
+    int r;
+
+    set_change = 0;
+    r = obtain_sets (zass, rpn, sets);
+    if (r)
+        return NULL;
+    return zass_search (zass, rpn, (char*) result_set, (char*) database);
+}
+
+const struct zass_presentent *zass_p_present (ZASS zass,
+                        const char *result_set, int offset, int number)
+{
+    struct gw_user_set *set;
+
+    set = user_set_search (result_set);
+    if (!set)
+       return NULL;
+    if (!set->present_flag)
+    {
+        int r = obtain_set (zass, set);
+       if (r)
+           return NULL;
+    }
+    return zass_present (zass, (char*) result_set, offset, number);
+}
+
+struct ccl_rpn_node *load_rpn (char *buf, FILE *inf)
+{
+    struct ccl_rpn_node *rpn;
+    struct ccl_rpn_attr **attrp;
+    char *cp;
+    int type, value, no_read;
+
+    if (!fgets (buf, 1024, inf))
+        return NULL;
+    if ((cp = strchr (buf, '\n')))
+        *cp = '\0';
+    switch (*buf)
+    {
+    case 'A':
+        rpn = malloc (sizeof (*rpn));
+       if (!rpn)
+           return NULL;
+       rpn->kind = CCL_RPN_AND;
+       rpn->u.p[0] = load_rpn (buf, inf);
+       rpn->u.p[1] = load_rpn (buf, inf);
+        break;
+    case 'O':
+        rpn = malloc (sizeof (*rpn));
+       if (!rpn)
+           return NULL;
+       rpn->kind = CCL_RPN_OR;
+       rpn->u.p[0] = load_rpn (buf, inf);
+       rpn->u.p[1] = load_rpn (buf, inf);
+        break;
+    case 'N':
+        rpn = malloc (sizeof (*rpn));
+       if (!rpn)
+           return NULL;
+       rpn->kind = CCL_RPN_NOT;
+       rpn->u.p[0] = load_rpn (buf, inf);
+       rpn->u.p[1] = load_rpn (buf, inf);
+        break;
+    case 'P':
+        rpn = malloc (sizeof (*rpn));
+       if (!rpn)
+           return NULL;
+       rpn->kind = CCL_RPN_PROX;
+       rpn->u.p[0] = load_rpn (buf, inf);
+       rpn->u.p[1] = load_rpn (buf, inf);
+        break;
+    case 'T':
+        rpn = malloc (sizeof (*rpn));
+       if (!rpn)
+           return NULL;
+       rpn->kind = CCL_RPN_TERM;
+
+       rpn->u.t.term = gw_strdup (buf+2);
+       attrp = &rpn->u.t.attr_list;
+        if (!fgets (buf, 1024, inf))
+            return NULL;
+       cp = buf;
+       while (sscanf (cp, "%d %d%n", &type, &value, &no_read) > 1)
+       {
+            *attrp = malloc (sizeof(**attrp));
+           (*attrp)->type = type;
+           (*attrp)->value = value;
+           attrp = &(*attrp)->next;
+            cp += no_read; 
+       }
+       *attrp = NULL;
+       break;
+    case 'S':
+        rpn = malloc (sizeof (*rpn));
+       if (!rpn)
+           return NULL;
+       rpn->kind = CCL_RPN_SET;
+       rpn->u.setname = gw_strdup (buf+2);
+    }
+    return rpn;
+}
+
+int load_p_state (int userid)
+{
+    FILE *inf;
+    char fname[128];
+    char fline[1025];
+    char database[1024];
+    char resultname[32];
+    int hits;
+    struct gw_user_set *set;
+
+    sprintf (fname, "persist.%d", userid);
+
+    inf = fopen (fname, "r");
+    if (!inf)
+    {
+        gw_log (GW_LOG_WARN|GW_LOG_ERRNO, KERNEL_LOG, 
+               "Couldn't open %s", fname);
+        return -1;
+    }
+    gw_log (GW_LOG_FATAL, KERNEL_LOG, 
+       "Reading persistence file %s", fname);
+    if (!fgets (fline, 1024, inf))
+        return -1;
+    if (sscanf (fline, "%s", info.target) != 1)
+        *info.target = '\0';
+    gw_log (GW_LOG_FATAL, KERNEL_LOG, 
+           "Reading persistence file %s (2)", fname);
+    read_kernel_res ();
+    gw_log (GW_LOG_FATAL, KERNEL_LOG, "reopen_target start");
+    reopen_target ();
+    gw_log (GW_LOG_FATAL, KERNEL_LOG, "reopen_target end");
+    while (fgets (fline, 1024, inf))
+    {
+        gw_log (GW_LOG_FATAL, KERNEL_LOG, 
+              "Reading persistence file %s (3)", fname);
+        if (sscanf (fline, "%s %d %s", resultname, &hits, database) != 3)
+           return -1;
+       gw_log (GW_LOG_FATAL, KERNEL_LOG,
+               "Adding %s, %d hits, database %s",
+               resultname, hits, database);
+       set = user_set_add (resultname, hits, database, NULL, 0);
+       set->rpn = load_rpn (fline, inf);
+       ccl_pr_tree (set->rpn, stderr);
+       fgets (fline, 1024, inf);
+    }
+    fclose (inf);
+    return 0;
+}
+
+static void save_rpn (struct ccl_rpn_node *rpn, FILE *of)
+{
+    struct ccl_rpn_attr *attr;
+
+    switch (rpn->kind)
+    {
+    case CCL_RPN_AND:
+        fprintf (of, "A\n");
+       save_rpn (rpn->u.p[0], of);
+       save_rpn (rpn->u.p[1], of);
+       break;
+    case CCL_RPN_OR:
+        fprintf (of, "O\n");
+       save_rpn (rpn->u.p[0], of);
+       save_rpn (rpn->u.p[1], of);
+       break;
+    case CCL_RPN_NOT:
+        fprintf (of, "N\n");
+       save_rpn (rpn->u.p[0], of);
+       save_rpn (rpn->u.p[1], of);
+       break;
+    case CCL_RPN_PROX:
+        fprintf (of, "P\n");
+       save_rpn (rpn->u.p[0], of);
+       save_rpn (rpn->u.p[1], of);
+       break;
+    case CCL_RPN_TERM:
+       fprintf (of, "T %s\n", rpn->u.t.term);
+       for (attr = rpn->u.t.attr_list; attr; attr = attr->next)
+           fprintf (of, "%d %d ", attr->type, attr->value);
+       fprintf (of, "\n");
+       break;
+    case CCL_RPN_SET:
+        fprintf (of, "S %s\n", rpn->u.setname); 
+    }
+}
+
+int save_p_state (int userid)
+{
+    FILE *of;
+    char fname[128];
+    struct gw_user_set *sp;
+
+    sprintf (fname, "persist.%d", userid);
+
+    of = fopen (fname, "w");
+    if (!of)
+    {
+        gw_log (GW_LOG_WARN|GW_LOG_ERRNO, KERNEL_LOG, 
+               "Couldn't open %s", fname);
+        return -1;
+    }
+    gw_log (GW_LOG_DEBUG, KERNEL_LOG, "Writing persistence file %s", fname);
+    fprintf (of, "%s\n", info.target);
+    for (sp = info.sets; sp; sp = sp->prev)
+    {
+        fprintf (of, "%s %d %s\n", sp->name, sp->hits, sp->database);
+       save_rpn (sp->rpn, of);
+       fprintf (of, "X\n");
+    }
+    fclose (of);
+    return 0;
+}
+
index aaba374..032392c 100644 (file)
@@ -2,7 +2,10 @@
  * Europagate, 1995
  *
  * $Log: urp.c,v $
- * Revision 1.25  1995/04/17 09:34:33  adam
+ * Revision 1.26  1995/04/19 07:31:12  adam
+ * First work on Z39.50 persistence.
+ *
+ * Revision 1.25  1995/04/17  09:34:33  adam
  * Timeout (idletime) adjustable. Minor changes in kernel.
  *
  * Revision 1.24  1995/03/28  11:42:35  adam
@@ -129,7 +132,7 @@ int lgets (char *buf, int max, int fd)
     return 1;
 }
 
-static int reopen_target (void)
+int reopen_target (void)
 {
     const char *v;
     if (info.zass)
@@ -322,12 +325,16 @@ static int exec_find (struct ccl_token *list)
 {
     const struct zass_searchent *p;
     struct gw_user_set *us;
+    char setname[32];
 
     struct ccl_rpn_node *rpn;
     int error;
     const char *pos;
 
-    us = user_set_add ("Default", -1);
+    if (info.setno == -1)
+        strcpy (setname, "Default");
+    else
+        sprintf (setname, "%d", info.setno);
     rpn = ccl_find (info.bibset, list, &error, &pos);
     if (!rpn)
     {
@@ -360,9 +367,13 @@ static int exec_find (struct ccl_token *list)
     gw_log (GW_LOG_DEBUG, KERNEL_LOG, "Searching in database %s",
             info.database );
     assert (info.zass);
-    p = zass_search (info.zass, rpn, "Default", info.database );
+    fprintf (reply_fd, "Searching in database %s\n", info.database);
+    p = zass_p_search (info.zass, rpn, setname, info.database, info.sets);
     if (!p)
+    {
+        fprintf (reply_fd, "Search fail\n");
         return -1;
+    }
     if (p->errcode != -1)
     {
         display_diag_error (p->errcode, p->errstring);
@@ -370,7 +381,10 @@ static int exec_find (struct ccl_token *list)
     }
     fprintf (reply_fd, "%d %s\n", p->num,
              gw_res_get (info.kernel_res, "gw.msg.hits", "hit(s)"));
-    us->hits = p->num;
+    us = user_set_add (setname, p->num, info.database, rpn, 1);
+    fprintf (reply_fd, "Result-set %s created\n", setname);
+    if (info.setno >= 0)
+        info.setno++;
     return 0;
 }
 
@@ -442,7 +456,7 @@ static void present (const char *set, int offset, int number,
     gw_log (GW_LOG_DEBUG, KERNEL_LOG, "present in set %s", set);
     gw_log (GW_LOG_DEBUG, KERNEL_LOG, "present of %d records from offset %d",
             number, offset);
-    zp = zass_present(info.zass, (char *) set, offset, number);
+    zp = zass_p_present(info.zass, (char *) set, offset, number);
     if (zp)
     {
         int i;