From 5c6e78a48473f4ac68d8c4eacab8bce0af70b7c9 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Wed, 19 Apr 1995 07:30:56 +0000 Subject: [PATCH] First work on Z39.50 persistence. --- kernel/Makefile | 15 +-- kernel/default.res | 5 +- kernel/kernel.h | 31 +++++- kernel/main.c | 27 ++++- kernel/persist.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/urp.c | 26 +++-- 6 files changed, 368 insertions(+), 21 deletions(-) create mode 100644 kernel/persist.c diff --git a/kernel/Makefile b/kernel/Makefile index 374c050..05f8b6f 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -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 @@ -53,11 +56,11 @@ # 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 diff --git a/kernel/default.res b/kernel/default.res index 67bbac2..a16cfd8 100644 --- a/kernel/default.res +++ b/kernel/default.res @@ -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 diff --git a/kernel/kernel.h b/kernel/kernel.h index 7ca0316..dc2adc4 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -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 @@ -60,8 +63,11 @@ #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" diff --git a/kernel/main.c b/kernel/main.c index 9398e2b..f638c4b 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -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 index 0000000..e341536 --- /dev/null +++ b/kernel/persist.c @@ -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 +#include +#include +#include +#include +#include +#include + +#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; +} + diff --git a/kernel/urp.c b/kernel/urp.c index aaba374..032392c 100644 --- a/kernel/urp.c +++ b/kernel/urp.c @@ -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; -- 1.7.10.4