From: Sebastian Hammer Date: Tue, 14 Nov 2006 20:44:36 +0000 (+0000) Subject: Initial revision X-Git-Tag: start~1 X-Git-Url: http://jsfdemo.indexdata.com/?a=commitdiff_plain;h=852a79d842c7294e2191ee23e072510c5bd98f0c;p=pazpar2-moved-to-github.git Initial revision --- 852a79d842c7294e2191ee23e072510c5bd98f0c diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..62661d9 --- /dev/null +++ b/.cvsignore @@ -0,0 +1 @@ +paraz diff --git a/.gdb_history b/.gdb_history new file mode 100644 index 0000000..4377013 --- /dev/null +++ b/.gdb_history @@ -0,0 +1,208 @@ +break main +run -c 2000 +quit +break main +run -c 2000 +next +ste +step +next +print hostbuf +next +un +run +nexrt +next +step +next +step +next +print p +print *p +next +cont +run +quit +break main +run -c 2000 +next +step +next +print hostbuf +next +list +bt +frame 1 +list +break event_loop +delete 1 +run +next +print *p +next +quit +break command_accept +run -c 2000 +next +print s +next +print channel_list +print *channel_list +print *channel_list->next +next +print max +next +next +quit +breack command_command +break command_command +run -c 2000 +run +next +print *s +print *s->channel +run +run +run +quit +run -c 2000 +break command_command +cont +next +break command_accept +cont +run +finish +cont +next +cont +next +print res +next +cont +con +cont +quit +run -c 2000 +break command_io +cont +cont +next +print buf +quit +run -c 2000 +break command_command +cont +next +print argv +cont +next +list +break 54 +cont +print argv +print argc +cont +quit +break load_targets +run -c 2000 +finish +print channel_list +print *channel_list +print *channel_list->data +print *channel_list->next +next +break handler +cont +next +print *target +print *t +next +print res +print errno +print erddrno +print (int)errno +quit +run -c 2000 +run -c 2001 +run +run -c 2000 +break handler +cont +next +print res +next +cont +next +h +run -c 2001 +next +cont +next +cont +print channel_list +print *channel_list +print *channel_list->next +print *channel_list->next->next +run -c 2000 +next +cont +next +cont +next +print *a +print *a->u.initResponse +next +step +next +cont +delete 1 +cont +cont +run -c 2000 +bt +frame 4 +list +print *session +print *s +list +print *i +run +run -c 2001 +run -c 2000 +run -c 2001 +run -c 2000 +cont +quit +run -c 2000 +break handler +cont +cont +cont +cont +cont +next +print *p +next +print *p +next +next +print *p +next +print *p +next +cont +next +print *t +next +print *t +print *s +next +quit +break do_presentResponse +run -c 2002 +next +print *r +print *r->presentStatus +print *r->numberOfRecordsReturned +quit diff --git a/.pazpar2.c.swp b/.pazpar2.c.swp new file mode 100644 index 0000000..64715bb Binary files /dev/null and b/.pazpar2.c.swp differ diff --git a/.pazpar2.h.swp b/.pazpar2.h.swp new file mode 100644 index 0000000..44d32aa Binary files /dev/null and b/.pazpar2.h.swp differ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..51ce3df --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +# ParaZ. Copyright (C) 2000-2004, Index Data ApS +# All rights reserved. +# $Id: Makefile,v 1.1 2006-11-14 20:44:38 quinn Exp $ + +SHELL=/bin/sh + +CC=gcc + +YAZCONF=yaz-config +YAZLIBS=`$(YAZCONF) --libs` +YAZCFLAGS=`$(YAZCONF) --cflags` + +PROG=pazpar2 +PROGO=pazpar2.o eventl.o util.o command.o + +all: $(PROG) + +$(PROG): $(PROGO) + $(CC) $(CFLAGS) $(YAZCFLAGS) -o $(PROG) $(PROGO) $(YAZLIBS) + +.c.o: + $(CC) -c $(CFLAGS) -I. $(YAZCFLAGS) $< + +clean: + rm -f *.[oa] test core mon.out gmon.out errlist $(PROG) + diff --git a/bad.pz b/bad.pz new file mode 100644 index 0000000..6522dff --- /dev/null +++ b/bad.pz @@ -0,0 +1,17 @@ +# one good target: +target bagel.indexdata.dk/gils + +# One bad port with something behind it +#target bagel.indexdata.dk:23/Telnet +# Seems to hang for ever + +# One bad port with nothing behind it +target bagel.indexdata.dk:2/BadPort + +# One unknonw host +target unknown.indexdata.dk + +connect +init +search @attr 1=4 utah +present diff --git a/command.c b/command.c new file mode 100644 index 0000000..4ea72e1 --- /dev/null +++ b/command.c @@ -0,0 +1,350 @@ +/* $Id: command.c,v 1.1 2006-11-14 20:44:37 quinn Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "command.h" +#include "util.h" +#include "eventl.h" +#include "pazpar2.h" + +extern IOCHAN channel_list; + +struct command_session { + IOCHAN channel; + char *outbuf; + + int outbuflen; + int outbufwrit; + + struct session *psession; +}; + +void command_destroy(struct command_session *s); +void command_prompt(struct command_session *s); +void command_puts(struct command_session *s, const char *buf); + +static int cmd_quit(struct command_session *s, char **argv, int argc) +{ + IOCHAN i = s->channel; + close(iochan_getfd(i)); + iochan_destroy(i); + command_destroy(s); + return 0; +} + +static int cmd_load(struct command_session *s, char **argv, int argc) +{ + if (argc != 2) { + command_puts(s, "Usage: load filename\n"); + } + if (load_targets(s->psession, argv[1]) < 0) + command_puts(s, "Failed to open file\n"); + return 1; +} + +static int cmd_search(struct command_session *s, char **argv, int argc) +{ + if (argc != 2) + { + command_puts(s, "Usage: search word\n"); + return 1; + } + search(s->psession, argv[1]); + return 1; +} + +static int cmd_hitsbytarget(struct command_session *s, char **argv, int argc) +{ + int count; + int i; + + struct hitsbytarget *ht = hitsbytarget(s->psession, &count); + for (i = 0; i < count; i++) + { + char buf[1024]; + + sprintf(buf, "%s: %d (%d records, diag=%d, state=%s)\n", ht[i].id, ht[i].hits, + ht[i].records, ht[i].diagnostic, ht[i].state); + command_puts(s, buf); + } + return 1; +} + +static int cmd_stat(struct command_session *s, char **argv, int argc) +{ + char buf[1024]; + struct statistics stat; + + statistics(s->psession, &stat); + sprintf(buf, "Number of connections: %d\n", stat.num_connections); + command_puts(s, buf); + if (stat.num_no_connection) + { + sprintf(buf, "#No_connection: %d\n", stat.num_no_connection); + command_puts(s, buf); + } + if (stat.num_connecting) + { + sprintf(buf, "#Connecting: %d\n", stat.num_connecting); + command_puts(s, buf); + } + if (stat.num_initializing) + { + sprintf(buf, "#Initializing: %d\n", stat.num_initializing); + command_puts(s, buf); + } + if (stat.num_searching) + { + sprintf(buf, "#Searching: %d\n", stat.num_searching); + command_puts(s, buf); + } + if (stat.num_presenting) + { + sprintf(buf, "#Ppresenting: %d\n", stat.num_presenting); + command_puts(s, buf); + } + if (stat.num_idle) + { + sprintf(buf, "#Idle: %d\n", stat.num_idle); + command_puts(s, buf); + } + if (stat.num_failed) + { + sprintf(buf, "#Failed: %d\n", stat.num_failed); + command_puts(s, buf); + } + if (stat.num_error) + { + sprintf(buf, "#Error: %d\n", stat.num_error); + command_puts(s, buf); + } + return 1; +} + +static struct { + char *cmd; + int (*fun)(struct command_session *s, char *argv[], int argc); +} cmd_array[] = { + {"quit", cmd_quit}, + {"load", cmd_load}, + {"search", cmd_search}, + {"ht", cmd_hitsbytarget}, + {"stat", cmd_stat}, + {0,0} +}; + +void command_command(struct command_session *s, char *command) +{ + char *p; + char *argv[20]; + int argc = 0; + int i; + int res = -1; + + p = command; + while (*p) + { + while (isspace(*p)) + p++; + if (!*p) + break; + argv[argc++] = p; + while (*p && !isspace(*p)) + p++; + if (!*p) + break; + *(p++) = '\0'; + } + if (argc) { + for (i = 0; cmd_array[i].cmd; i++) + { + if (!strcmp(cmd_array[i].cmd, argv[0])) { + res = (cmd_array[i].fun)(s, argv, argc); + + break; + } + } + if (res < 0) { + command_puts(s, "Unknown command.\n"); + command_prompt(s); + } + else if (res == 1) { + command_prompt(s); + } + } + else + command_prompt(s); + +} + + +static void command_io(IOCHAN i, int event) +{ + int res; + char buf[1024]; + struct command_session *s; + + s = iochan_getdata(i); + + + switch (event) + { + case EVENT_INPUT: + res = read(iochan_getfd(i), buf, 1024); + if (res <= 0) + { + yaz_log(YLOG_WARN|YLOG_ERRNO, "read command"); + close(iochan_getfd(i)); + iochan_destroy(i); + command_destroy(s); + return; + } + if (!index(buf, '\n')) { + yaz_log(YLOG_WARN|YLOG_ERRNO, "Did not receive complete command"); + close(iochan_getfd(i)); + iochan_destroy(i); + command_destroy(s); + return; + } + buf[res] = '\0'; + command_command(s, buf); + break; + case EVENT_OUTPUT: + if (!s->outbuflen || s->outbufwrit < 0) + { + yaz_log(YLOG_WARN, "Called with outevent but no data"); + iochan_clearflag(i, EVENT_OUTPUT); + } + else + { + res = write(iochan_getfd(i), s->outbuf + s->outbufwrit, s->outbuflen - + s->outbufwrit); + if (res < 0) { + yaz_log(YLOG_WARN|YLOG_ERRNO, "write command"); + close(iochan_getfd(i)); + iochan_destroy(i); + command_destroy(s); + } + else + { + s->outbufwrit += res; + if (s->outbufwrit >= s->outbuflen) + { + s->outbuflen = s->outbufwrit = 0; + iochan_clearflag(i, EVENT_OUTPUT); + } + } + } + break; + default: + yaz_log(YLOG_WARN, "Bad voodoo on socket"); + } +} + +void command_puts(struct command_session *s, const char *buf) +{ + int len = strlen(buf); + memcpy(s->outbuf + s->outbuflen, buf, len); + s->outbuflen += len; + iochan_setflag(s->channel, EVENT_OUTPUT); +} + +void command_prompt(struct command_session *s) +{ + command_puts(s, "Pazpar2> "); +} + + +/* Accept a new command connection */ +static void command_accept(IOCHAN i, int event) +{ + struct sockaddr_in addr; + int fd = iochan_getfd(i); + socklen_t len; + int s; + IOCHAN c; + struct command_session *ses; + int flags; + + len = sizeof addr; + if ((s = accept(fd, (struct sockaddr *) &addr, &len)) < 0) + { + yaz_log(YLOG_WARN|YLOG_ERRNO, "accept"); + return; + } + if ((flags = fcntl(s, F_GETFL, 0)) < 0) + yaz_log(YLOG_FATAL|YLOG_ERRNO, "fcntl"); + if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) + yaz_log(YLOG_FATAL|YLOG_ERRNO, "fcntl2"); + + yaz_log(YLOG_LOG, "New command connection"); + c = iochan_create(s, command_io, EVENT_INPUT | EVENT_EXCEPT); + + ses = xmalloc(sizeof(*ses)); + ses->outbuf = xmalloc(50000); + ses->outbuflen = 0; + ses->outbufwrit = 0; + ses->channel = c; + ses->psession = new_session(); + iochan_setdata(c, ses); + + command_puts(ses, "Welcome to pazpar2\n\n"); + command_prompt(ses); + + c->next = channel_list; + channel_list = c; +} + +void command_destroy(struct command_session *s) { + xfree(s->outbuf); + xfree(s); +} + +/* Create a command-channel listener */ +void command_init(int port) +{ + IOCHAN c; + int l; + struct protoent *p; + struct sockaddr_in myaddr; + + yaz_log(YLOG_LOG, "Command port is %d", port); + if (!(p = getprotobyname("tcp"))) { + abort(); + } + if ((l = socket(PF_INET, SOCK_STREAM, p->p_proto)) < 0) + yaz_log(YLOG_FATAL|YLOG_ERRNO, "socket"); + bzero(&myaddr, sizeof myaddr); + myaddr.sin_family = AF_INET; + myaddr.sin_addr.s_addr = INADDR_ANY; + myaddr.sin_port = port; + if (bind(l, (struct sockaddr *) &myaddr, sizeof myaddr) < 0) + yaz_log(YLOG_FATAL|YLOG_ERRNO, "bind"); + if (listen(l, 5) < 0) + yaz_log(YLOG_FATAL|YLOG_ERRNO, "listen"); + + c = iochan_create(l, command_accept, EVENT_INPUT | EVENT_EXCEPT); + //iochan_setdata(c, &l); + c->next = channel_list; + channel_list = c; +} + +/* + * Local variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ diff --git a/command.h b/command.h new file mode 100644 index 0000000..25e5b99 --- /dev/null +++ b/command.h @@ -0,0 +1,6 @@ +#ifndef COMMAND_H +#define COMMAND_H + +void command_init(int port); + +#endif diff --git a/danish.pz b/danish.pz new file mode 100644 index 0000000..ba1cc52 --- /dev/null +++ b/danish.pz @@ -0,0 +1,21 @@ +target cosmos.dnlb.dk:9909/DNL01 +target odin.dtv.dk:210/DTV01 +target dvjb1.kvl.dk:9909/dvj01 +target hermes.lib.cbs.dk:2100/S +target a800.hha.dk:9909/hba01 +target z3950.kb.dk:2100/kgl01 +target hans.ruc.dk:2210/S +target a500.aub.auc.dk:9909/AUB01 +target z3950.dbc.dk:213/def1forsk +target z3950.dbc.dk:213/def1total +target z3950.dbc.dk:213/danbibv2 +target hcb.bibnet.dk:2100/S +target z3950.bibsys.no:2100/BIBSYS +target z3950.libris.kb.se:210/libr +target bagel.indexdata.dk/gils +target www.deff.dk:2100/Default +target www.deff.dk:2102/Default +connect +init +search @attr 1=4 danmarks +present diff --git a/def.pz b/def.pz new file mode 100644 index 0000000..1351fde --- /dev/null +++ b/def.pz @@ -0,0 +1,17 @@ +target cosmos.dnlb.dk:9909/DNL01 +target odin.dtv.dk:210/DTV01 +target dvjb1.kvl.dk:9909/dvj01 +target hermes.lib.cbs.dk:2100/S +target a800.hha.dk:9909/hba01 +target z3950.kb.dk:2100/kgl01 +target hans.ruc.dk:2210/S +target a500.aub.auc.dk:9909/AUB01 +target z3950.dbc.dk:213/def1forsk +target z3950.dbc.dk:213/def1total +target z3950.dbc.dk:213/danbibv2 +target bagel/gils +connect +wait reset +init +wait reset +search @attr 1=4 @attr 2=3 @attr 3=3 @attr 4=1 @attr 5=100 @attr 6=2 "pigen med" diff --git a/defport.pz b/defport.pz new file mode 100644 index 0000000..de0df23 --- /dev/null +++ b/defport.pz @@ -0,0 +1,5 @@ +target www.deff.dk:2102/Default +connect +init +search @attr 1=4 danmarks +present diff --git a/eventl.c b/eventl.c new file mode 100644 index 0000000..fc188a3 --- /dev/null +++ b/eventl.c @@ -0,0 +1,142 @@ +/* + * ParaZ - a simple tool for harvesting performance data for parallel + * operations using Z39.50. + * Copyright (c) 2000-2004 Index Data ApS + * See LICENSE file for details. + */ + +/* + * $Id: eventl.c,v 1.1 2006-11-14 20:44:37 quinn Exp $ + * Based on revision YAZ' server/eventl.c 1.29. + */ + +#include +#include +#ifdef WIN32 +#include +#else +#include +#endif +#include +#include +#include + +#include +#include +#include +#include +#include "eventl.h" +#include + +IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags) +{ + IOCHAN new_iochan; + + if (!(new_iochan = (IOCHAN)xmalloc(sizeof(*new_iochan)))) + return 0; + new_iochan->destroyed = 0; + new_iochan->fd = fd; + new_iochan->flags = flags; + new_iochan->fun = cb; + new_iochan->force_event = 0; + new_iochan->last_event = new_iochan->max_idle = 0; + new_iochan->next = NULL; + return new_iochan; +} + +int event_loop(IOCHAN *iochans) +{ + do /* loop as long as there are active associations to process */ + { + IOCHAN p, nextp; + fd_set in, out, except; + int res, max; + static struct timeval nullto = {0, 0}, to; + struct timeval *timeout; + + FD_ZERO(&in); + FD_ZERO(&out); + FD_ZERO(&except); + timeout = &to; /* hang on select */ + to.tv_sec = 30; + to.tv_usec = 0; + max = 0; + for (p = *iochans; p; p = p->next) + { + if (p->force_event) + timeout = &nullto; /* polling select */ + if (p->flags & EVENT_INPUT) + FD_SET(p->fd, &in); + if (p->flags & EVENT_OUTPUT) + FD_SET(p->fd, &out); + if (p->flags & EVENT_EXCEPT) + FD_SET(p->fd, &except); + if (p->fd > max) + max = p->fd; + } + if ((res = select(max + 1, &in, &out, &except, timeout)) < 0) + { + if (errno == EINTR) + continue; + else + abort(); + } + for (p = *iochans; p; p = p->next) + { + int force_event = p->force_event; + time_t now = time(0); + + p->force_event = 0; + if (!p->destroyed && (FD_ISSET(p->fd, &in) || + force_event == EVENT_INPUT)) + { + p->last_event = now; + (*p->fun)(p, EVENT_INPUT); + } + if (!p->destroyed && (FD_ISSET(p->fd, &out) || + force_event == EVENT_OUTPUT)) + { + p->last_event = now; + (*p->fun)(p, EVENT_OUTPUT); + } + if (!p->destroyed && (FD_ISSET(p->fd, &except) || + force_event == EVENT_EXCEPT)) + { + p->last_event = now; + (*p->fun)(p, EVENT_EXCEPT); + } + if (!p->destroyed && ((p->max_idle && now - p->last_event > + p->max_idle) || force_event == EVENT_TIMEOUT)) + { + p->last_event = now; + (*p->fun)(p, EVENT_TIMEOUT); + } + } + for (p = *iochans; p; p = nextp) + { + nextp = p->next; + + if (p->destroyed) + { + IOCHAN tmp = p, pr; + + /* Now reset the pointers */ + if (p == *iochans) + *iochans = p->next; + else + { + for (pr = *iochans; pr; pr = pr->next) + if (pr->next == p) + break; + assert(pr); /* grave error if it weren't there */ + pr->next = p->next; + } + if (nextp == p) + nextp = p->next; + xfree(tmp); + } + } + } + while (*iochans); + return 0; +} diff --git a/eventl.h b/eventl.h new file mode 100644 index 0000000..b275852 --- /dev/null +++ b/eventl.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1995-1999, Index Data + * See the file LICENSE for details. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: eventl.h,v $ + * Revision 1.1 2006-11-14 20:44:38 quinn + * Initial revision + * + * Revision 1.1.1.1 2000/02/23 14:40:18 heikki + * Original import to cvs + * + * Revision 1.11 1999/04/20 09:56:48 adam + * Added 'name' paramter to encoder/decoder routines (typedef Odr_fun). + * Modified all encoders/decoders to reflect this change. + * + * Revision 1.10 1998/01/29 13:30:23 adam + * Better event handle system for NT/Unix. + * + * Revision 1.9 1997/09/01 09:31:48 adam + * Removed definition statserv_remove from statserv.h to eventl.h. + * + * Revision 1.8 1995/06/19 12:39:09 quinn + * Fixed bug in timeout code. Added BER dumper. + * + * Revision 1.7 1995/06/16 10:31:34 quinn + * Added session timeout. + * + * Revision 1.6 1995/05/16 08:51:02 quinn + * License, documentation, and memory fixes + * + * Revision 1.5 1995/05/15 11:56:37 quinn + * Asynchronous facilities. Restructuring of seshigh code. + * + * Revision 1.4 1995/03/27 08:34:23 quinn + * Added dynamic server functionality. + * Released bindings to session.c (is now redundant) + * + * Revision 1.3 1995/03/15 08:37:42 quinn + * Now we're pretty much set for nonblocking I/O. + * + * Revision 1.2 1995/03/14 10:28:00 quinn + * More work on demo server. + * + * Revision 1.1 1995/03/10 18:22:45 quinn + * The rudiments of an asynchronous server. + * + */ + +#ifndef EVENTL_H +#define EVENTL_H + +#include + +struct iochan; + +typedef void (*IOC_CALLBACK)(struct iochan *i, int event); + +typedef struct iochan +{ + int fd; + int flags; +#define EVENT_INPUT 0x01 +#define EVENT_OUTPUT 0x02 +#define EVENT_EXCEPT 0x04 +#define EVENT_TIMEOUT 0x08 +#define EVENT_WORK 0x10 +int force_event; + IOC_CALLBACK fun; + void *data; + int destroyed; + time_t last_event; + time_t max_idle; + + struct iochan *next; +} *IOCHAN; + +#define iochan_destroy(i) (void)((i)->destroyed = 1) +#define iochan_getfd(i) ((i)->fd) +#define iochan_setfd(i, f) ((i)->fd = (f)) +#define iochan_getdata(i) ((i)->data) +#define iochan_setdata(i, d) ((i)->data = d) +#define iochan_getflags(i) ((i)->flags) +#define iochan_setflags(i, d) ((i)->flags = d) +#define iochan_setflag(i, d) ((i)->flags |= d) +#define iochan_clearflag(i, d) ((i)->flags &= ~(d)) +#define iochan_getflag(i, d) ((i)->flags & d ? 1 : 0) +#define iochan_getfun(i) ((i)->fun) +#define iochan_setfun(i, d) ((i)->fun = d) +#define iochan_setevent(i, e) ((i)->force_event = (e)) +#define iochan_getnext(i) ((i)->next) +#define iochan_settimeout(i, t) ((i)->max_idle = (t), (i)->last_event = time(0)) + +IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags); +int event_loop(IOCHAN *iochans); +#endif diff --git a/h1.pz b/h1.pz new file mode 100644 index 0000000..2e2f0fa --- /dev/null +++ b/h1.pz @@ -0,0 +1,9 @@ +target bagel.indexdata.dk/gils +#target bagel.indexdata.dk:2100/Default +#target unknown.indexdata.dk +target localhost:9999/Default +connect +wait reset +init +search @attr 1=4 utah +present 2 diff --git a/local.pz b/local.pz new file mode 100644 index 0000000..4056d53 --- /dev/null +++ b/local.pz @@ -0,0 +1,10 @@ +target bagel.indexdata.dk/gils +connect +init +search @attr 1=4 utah +present 1 +wait +present 2 +wait +present +wait \ No newline at end of file diff --git a/multi.pz b/multi.pz new file mode 100644 index 0000000..436f34f --- /dev/null +++ b/multi.pz @@ -0,0 +1,9 @@ +target bagel.indexdata.dk/gils +target bagel.indexdata.dk/Marc +target muffin.indexdata.dk:8888/Default +target muffin.indexdata.dk:9002/E97 +target ximum.indexdata.dk:9999/resolutions +connect +init +search @attr 1=4 utah +present diff --git a/multi.txt b/multi.txt new file mode 100644 index 0000000..55eb1b0 --- /dev/null +++ b/multi.txt @@ -0,0 +1,220 @@ + 950876489,CONNECTED , 0.001341, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876489,CONNECTED , 0.001592, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876489,CONNECTED , 0.001684, bagel.indexdata.dk/Marc, , 0, 0 + 950876489,CONNECTED , 0.001911, bagel.indexdata.dk/gils, , 0, 0 + 950876489,CONNECTED , 0.002035, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876489,INIT , 0.009192, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876489,INIT , 0.024619, bagel.indexdata.dk/Marc, , 0, 0 + 950876489,INIT , 0.026139, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876489,INIT , 0.046127, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876489,FAILED , 0.046881, bagel.indexdata.dk/Marc, search error, 0, 0 + 950876489,FINISHED , 0.047016, bagel.indexdata.dk/Marc, , 0, 0 + 950876489,FAILED , 0.060261, muffin.indexdata.dk:9002/E97, search error, 0, 0 + 950876489,FINISHED , 0.060485, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876489,INIT , 0.064298, bagel.indexdata.dk/gils, , 0, 0 + 950876489,SEARCH , 0.083986, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876489,FINISHED , 0.084146, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876489,FAILED , 0.088662, ximum.indexdata.dk:9999/resolutions, search error, 0, 0 + 950876489,FINISHED , 0.088829, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876489,SEARCH , 0.090702, bagel.indexdata.dk/gils, , 9, 0 + 950876489,PRESENT , 0.126084, bagel.indexdata.dk/gils, failed, 0, 0 + 950876489,FINISHED , 0.126188, bagel.indexdata.dk/gils, , 0, 0 + 950876489,COMPLETE , 0.126206, (all), , 0, 0 + 950876492,CONNECTED , 0.000596, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876492,CONNECTED , 0.000838, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876492,CONNECTED , 0.000930, bagel.indexdata.dk/Marc, , 0, 0 + 950876492,CONNECTED , 0.001110, bagel.indexdata.dk/gils, , 0, 0 + 950876492,CONNECTED , 0.001257, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876492,INIT , 0.008360, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876492,INIT , 0.018452, bagel.indexdata.dk/Marc, , 0, 0 + 950876492,INIT , 0.024710, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876492,FAILED , 0.040495, bagel.indexdata.dk/Marc, search error, 0, 0 + 950876492,FINISHED , 0.040674, bagel.indexdata.dk/Marc, , 0, 0 + 950876492,INIT , 0.048323, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876492,INIT , 0.058978, bagel.indexdata.dk/gils, , 0, 0 + 950876492,FAILED , 0.060665, muffin.indexdata.dk:9002/E97, search error, 0, 0 + 950876492,FINISHED , 0.060778, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876492,SEARCH , 0.085355, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876492,FINISHED , 0.085575, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876492,SEARCH , 0.085628, bagel.indexdata.dk/gils, , 9, 0 + 950876492,FAILED , 0.087761, ximum.indexdata.dk:9999/resolutions, search error, 0, 0 + 950876492,FINISHED , 0.087854, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876492,PRESENT , 0.120268, bagel.indexdata.dk/gils, failed, 0, 0 + 950876492,FINISHED , 0.120381, bagel.indexdata.dk/gils, , 0, 0 + 950876492,COMPLETE , 0.120399, (all), , 0, 0 + 950876494,CONNECTED , 0.000545, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876494,CONNECTED , 0.000790, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876494,CONNECTED , 0.000881, bagel.indexdata.dk/Marc, , 0, 0 + 950876494,CONNECTED , 0.001021, bagel.indexdata.dk/gils, , 0, 0 + 950876494,CONNECTED , 0.001220, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876494,INIT , 0.008265, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876494,INIT , 0.019415, bagel.indexdata.dk/Marc, , 0, 0 + 950876494,INIT , 0.023800, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876494,FAILED , 0.041508, bagel.indexdata.dk/Marc, search error, 0, 0 + 950876494,FINISHED , 0.041694, bagel.indexdata.dk/Marc, , 0, 0 + 950876494,INIT , 0.046970, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876494,FAILED , 0.050530, muffin.indexdata.dk:9002/E97, search error, 0, 0 + 950876494,FINISHED , 0.050647, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876494,INIT , 0.058910, bagel.indexdata.dk/gils, , 0, 0 + 950876494,SEARCH , 0.070817, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876494,FINISHED , 0.070987, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876494,SEARCH , 0.085523, bagel.indexdata.dk/gils, , 9, 0 + 950876494,FAILED , 0.086797, ximum.indexdata.dk:9999/resolutions, search error, 0, 0 + 950876494,FINISHED , 0.086904, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876494,PRESENT , 0.121230, bagel.indexdata.dk/gils, failed, 0, 0 + 950876494,FINISHED , 0.121337, bagel.indexdata.dk/gils, , 0, 0 + 950876494,COMPLETE , 0.121355, (all), , 0, 0 + 950876496,CONNECTED , 0.000778, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876496,CONNECTED , 0.001021, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876496,CONNECTED , 0.001168, bagel.indexdata.dk/Marc, , 0, 0 + 950876496,CONNECTED , 0.001307, bagel.indexdata.dk/gils, , 0, 0 + 950876496,CONNECTED , 0.001470, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876496,INIT , 0.008356, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876496,INIT , 0.018489, bagel.indexdata.dk/Marc, , 0, 0 + 950876496,INIT , 0.025407, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876496,FAILED , 0.040572, bagel.indexdata.dk/Marc, search error, 0, 0 + 950876496,FINISHED , 0.040706, bagel.indexdata.dk/Marc, , 0, 0 + 950876496,INIT , 0.045839, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876496,INIT , 0.057905, bagel.indexdata.dk/gils, , 0, 0 + 950876496,FAILED , 0.058305, muffin.indexdata.dk:9002/E97, search error, 0, 0 + 950876496,FINISHED , 0.058395, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876496,SEARCH , 0.082661, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876496,FINISHED , 0.082791, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876496,SEARCH , 0.085132, bagel.indexdata.dk/gils, , 9, 0 + 950876496,FAILED , 0.088815, ximum.indexdata.dk:9999/resolutions, search error, 0, 0 + 950876496,FINISHED , 0.088918, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876496,PRESENT , 0.119781, bagel.indexdata.dk/gils, failed, 0, 0 + 950876496,FINISHED , 0.119867, bagel.indexdata.dk/gils, , 0, 0 + 950876496,COMPLETE , 0.119884, (all), , 0, 0 + 950876498,CONNECTED , 0.000566, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876498,CONNECTED , 0.000812, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876498,CONNECTED , 0.000903, bagel.indexdata.dk/Marc, , 0, 0 + 950876498,CONNECTED , 0.001005, bagel.indexdata.dk/gils, , 0, 0 + 950876498,CONNECTED , 0.001236, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876498,INIT , 0.008423, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876498,INIT , 0.018266, bagel.indexdata.dk/Marc, , 0, 0 + 950876498,INIT , 0.025240, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876498,FAILED , 0.041354, bagel.indexdata.dk/Marc, search error, 0, 0 + 950876498,FINISHED , 0.041536, bagel.indexdata.dk/Marc, , 0, 0 + 950876498,INIT , 0.047206, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876498,FAILED , 0.052106, muffin.indexdata.dk:9002/E97, search error, 0, 0 + 950876498,FINISHED , 0.052232, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876498,INIT , 0.058767, bagel.indexdata.dk/gils, , 0, 0 + 950876498,SEARCH , 0.076203, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876498,FINISHED , 0.076352, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876498,SEARCH , 0.085108, bagel.indexdata.dk/gils, , 9, 0 + 950876498,FAILED , 0.085488, ximum.indexdata.dk:9999/resolutions, search error, 0, 0 + 950876498,FINISHED , 0.085584, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876498,PRESENT , 0.134660, bagel.indexdata.dk/gils, failed, 0, 0 + 950876498,FINISHED , 0.134770, bagel.indexdata.dk/gils, , 0, 0 + 950876498,COMPLETE , 0.134788, (all), , 0, 0 + 950876500,CONNECTED , 0.001486, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876500,CONNECTED , 0.001957, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876500,CONNECTED , 0.002047, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876500,CONNECTED , 0.002151, bagel.indexdata.dk/Marc, , 0, 0 + 950876500,CONNECTED , 0.002239, bagel.indexdata.dk/gils, , 0, 0 + 950876500,INIT , 0.008435, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876500,INIT , 0.019691, bagel.indexdata.dk/Marc, , 0, 0 + 950876500,INIT , 0.026277, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876500,FAILED , 0.041745, bagel.indexdata.dk/Marc, search error, 0, 0 + 950876500,FINISHED , 0.041963, bagel.indexdata.dk/Marc, , 0, 0 + 950876500,INIT , 0.045740, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876500,FAILED , 0.057801, muffin.indexdata.dk:9002/E97, search error, 0, 0 + 950876500,FINISHED , 0.057956, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876500,INIT , 0.059066, bagel.indexdata.dk/gils, , 0, 0 + 950876500,SEARCH , 0.082227, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876500,FINISHED , 0.082353, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876500,SEARCH , 0.086360, bagel.indexdata.dk/gils, , 9, 0 + 950876500,FAILED , 0.087483, ximum.indexdata.dk:9999/resolutions, search error, 0, 0 + 950876500,FINISHED , 0.087572, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876500,PRESENT , 0.140876, bagel.indexdata.dk/gils, failed, 0, 0 + 950876500,FINISHED , 0.140986, bagel.indexdata.dk/gils, , 0, 0 + 950876500,COMPLETE , 0.141004, (all), , 0, 0 + 950876502,CONNECTED , 0.000538, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876502,CONNECTED , 0.000788, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876502,CONNECTED , 0.000878, bagel.indexdata.dk/Marc, , 0, 0 + 950876502,CONNECTED , 0.001104, bagel.indexdata.dk/gils, , 0, 0 + 950876502,CONNECTED , 0.001210, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876502,INIT , 0.008454, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876502,INIT , 0.018353, bagel.indexdata.dk/Marc, , 0, 0 + 950876502,INIT , 0.024693, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876502,FAILED , 0.040460, bagel.indexdata.dk/Marc, search error, 0, 0 + 950876502,FINISHED , 0.040658, bagel.indexdata.dk/Marc, , 0, 0 + 950876502,INIT , 0.045000, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876502,FAILED , 0.060012, muffin.indexdata.dk:9002/E97, search error, 0, 0 + 950876502,FINISHED , 0.060171, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876502,INIT , 0.069047, bagel.indexdata.dk/gils, , 0, 0 + 950876502,SEARCH , 0.083532, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876502,FINISHED , 0.083687, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876502,FAILED , 0.087489, ximum.indexdata.dk:9999/resolutions, search error, 0, 0 + 950876502,FINISHED , 0.087666, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876502,SEARCH , 0.095443, bagel.indexdata.dk/gils, , 9, 0 + 950876502,PRESENT , 0.131127, bagel.indexdata.dk/gils, failed, 0, 0 + 950876502,FINISHED , 0.131228, bagel.indexdata.dk/gils, , 0, 0 + 950876502,COMPLETE , 0.131246, (all), , 0, 0 + 950876505,CONNECTED , 0.000569, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876505,CONNECTED , 0.000819, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876505,CONNECTED , 0.000908, bagel.indexdata.dk/Marc, , 0, 0 + 950876505,CONNECTED , 0.001122, bagel.indexdata.dk/gils, , 0, 0 + 950876505,CONNECTED , 0.001227, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876505,INIT , 0.008352, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876505,INIT , 0.024935, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876505,INIT , 0.033138, bagel.indexdata.dk/Marc, , 0, 0 + 950876505,INIT , 0.042941, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876505,FAILED , 0.056214, bagel.indexdata.dk/Marc, search error, 0, 0 + 950876505,FINISHED , 0.056397, bagel.indexdata.dk/Marc, , 0, 0 + 950876505,FAILED , 0.057998, muffin.indexdata.dk:9002/E97, search error, 0, 0 + 950876505,FINISHED , 0.058145, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876505,INIT , 0.073656, bagel.indexdata.dk/gils, , 0, 0 + 950876505,SEARCH , 0.082495, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876505,FINISHED , 0.082632, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876505,FAILED , 0.088327, ximum.indexdata.dk:9999/resolutions, search error, 0, 0 + 950876505,FINISHED , 0.088488, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876505,SEARCH , 0.100023, bagel.indexdata.dk/gils, , 9, 0 + 950876505,PRESENT , 0.135071, bagel.indexdata.dk/gils, failed, 0, 0 + 950876505,FINISHED , 0.135178, bagel.indexdata.dk/gils, , 0, 0 + 950876505,COMPLETE , 0.135196, (all), , 0, 0 + 950876507,CONNECTED , 0.000567, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876507,CONNECTED , 0.000813, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876507,CONNECTED , 0.000902, bagel.indexdata.dk/Marc, , 0, 0 + 950876507,CONNECTED , 0.001112, bagel.indexdata.dk/gils, , 0, 0 + 950876507,CONNECTED , 0.001218, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876507,INIT , 0.008370, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876507,INIT , 0.016265, bagel.indexdata.dk/Marc, , 0, 0 + 950876507,INIT , 0.026364, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876507,FAILED , 0.038337, bagel.indexdata.dk/Marc, search error, 0, 0 + 950876507,FINISHED , 0.038532, bagel.indexdata.dk/Marc, , 0, 0 + 950876507,INIT , 0.045492, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876507,INIT , 0.055726, bagel.indexdata.dk/gils, , 0, 0 + 950876507,FAILED , 0.059609, muffin.indexdata.dk:9002/E97, search error, 0, 0 + 950876507,FINISHED , 0.059735, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876507,SEARCH , 0.082128, bagel.indexdata.dk/gils, , 9, 0 + 950876507,SEARCH , 0.083731, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876507,FINISHED , 0.083835, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876507,FAILED , 0.104254, ximum.indexdata.dk:9999/resolutions, search error, 0, 0 + 950876507,FINISHED , 0.104440, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876507,PRESENT , 0.118206, bagel.indexdata.dk/gils, failed, 0, 0 + 950876507,FINISHED , 0.118315, bagel.indexdata.dk/gils, , 0, 0 + 950876507,COMPLETE , 0.118333, (all), , 0, 0 + 950876509,CONNECTED , 0.003709, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876509,CONNECTED , 0.004189, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876509,CONNECTED , 0.004281, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876509,CONNECTED , 0.004387, bagel.indexdata.dk/Marc, , 0, 0 + 950876509,CONNECTED , 0.004512, bagel.indexdata.dk/gils, , 0, 0 + 950876509,INIT , 0.008799, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876509,INIT , 0.028480, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876509,INIT , 0.032066, bagel.indexdata.dk/Marc, , 0, 0 + 950876509,INIT , 0.045047, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876509,FAILED , 0.055137, bagel.indexdata.dk/Marc, search error, 0, 0 + 950876509,FINISHED , 0.055310, bagel.indexdata.dk/Marc, , 0, 0 + 950876509,FAILED , 0.056695, muffin.indexdata.dk:9002/E97, search error, 0, 0 + 950876509,FINISHED , 0.056838, muffin.indexdata.dk:9002/E97, , 0, 0 + 950876509,INIT , 0.072675, bagel.indexdata.dk/gils, , 0, 0 + 950876509,SEARCH , 0.081390, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876509,FINISHED , 0.081532, muffin.indexdata.dk:8888/Default, , 0, 0 + 950876509,FAILED , 0.087422, ximum.indexdata.dk:9999/resolutions, search error, 0, 0 + 950876509,FINISHED , 0.087590, ximum.indexdata.dk:9999/resolutions, , 0, 0 + 950876509,SEARCH , 0.099116, bagel.indexdata.dk/gils, , 9, 0 + 950876509,PRESENT , 0.134118, bagel.indexdata.dk/gils, failed, 0, 0 + 950876509,FINISHED , 0.134221, bagel.indexdata.dk/gils, , 0, 0 + 950876509,COMPLETE , 0.134239, (all), , 0, 0 diff --git a/pazpar2.c b/pazpar2.c new file mode 100644 index 0000000..b003664 --- /dev/null +++ b/pazpar2.c @@ -0,0 +1,643 @@ +/* $Id: pazpar2.c,v 1.1 2006-11-14 20:44:38 quinn Exp $ */ + + +#define PAZPAR2_VERSION "0.1" +#define MAX_DATABASES 512 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "pazpar2.h" +#include "eventl.h" +#include "command.h" + +char *myname; +static long int runId=-1; + +struct target +{ + struct session *session; + char fullname[256]; + char hostport[128]; + char *ibuf; + int ibufsize; + char databases[MAX_DATABASES][128]; + COMSTACK link; + ODR odr_in, odr_out; + struct target *next; + void *addr; + int hits; + int records; + int setno; + int requestid; // ID of current outstanding request + int diagnostic; + enum target_state + { + No_connection, + Connecting, + Connected, + Initializing, + Searching, + Presenting, + Error, + Idle, + Failed + } state; +}; + +static char *state_strings[] = { + "No_connection", + "Connecting", + "Connected", + "Initializing", + "Searching", + "Presenting", + "Error", + "Idle", + "Failed" +}; + + +IOCHAN channel_list = 0; + +static struct parameters { + int timeout; /* operations timeout, in seconds */ + char implementationId[128]; + char implementationName[128]; + char implementationVersion[128]; + struct timeval base_time; + int toget; + int chunk; +} global_parameters = +{ + 30, + "81", + "Index Data PazPar2 (MasterKey)", + PAZPAR2_VERSION, + {0,0}, + 100, + 10 +}; + + +static int send_apdu(struct target *t, Z_APDU *a) +{ + char *buf; + int len, r; + + if (!z_APDU(t->odr_out, &a, 0, 0)) + { + odr_perror(t->odr_out, "Encoding APDU"); + abort(); + } + buf = odr_getbuf(t->odr_out, &len, 0); + r = cs_put(t->link, buf, len); + if (r < 0) + { + yaz_log(YLOG_WARN, "cs_put: %s", cs_errmsg(cs_errno(t->link))); + return -1; + } + else if (r == 1) + { + fprintf(stderr, "cs_put incomplete (ParaZ does not handle that)\n"); + } + odr_reset(t->odr_out); /* release the APDU structure */ + return 0; +} + + +static void send_init(IOCHAN i) +{ + struct target *t = iochan_getdata(i); + Z_APDU *a = zget_APDU(t->odr_out, Z_APDU_initRequest); + + a->u.initRequest->implementationId = global_parameters.implementationId; + a->u.initRequest->implementationName = global_parameters.implementationName; + a->u.initRequest->implementationVersion = + global_parameters.implementationVersion; + ODR_MASK_SET(a->u.initRequest->options, Z_Options_search); + ODR_MASK_SET(a->u.initRequest->options, Z_Options_present); + ODR_MASK_SET(a->u.initRequest->options, Z_Options_namedResultSets); + + ODR_MASK_SET(a->u.initRequest->protocolVersion, Z_ProtocolVersion_1); + ODR_MASK_SET(a->u.initRequest->protocolVersion, Z_ProtocolVersion_2); + ODR_MASK_SET(a->u.initRequest->protocolVersion, Z_ProtocolVersion_3); + if (send_apdu(t, a) >= 0) + { + iochan_setflags(i, EVENT_INPUT); + t->state = Initializing; + } + else + { + iochan_destroy(i); + t->state = Failed; + cs_close(t->link); + } +} + +static void send_search(IOCHAN i) +{ + struct target *t = iochan_getdata(i); + struct session *s = t->session; + Z_APDU *a = zget_APDU(t->odr_out, Z_APDU_searchRequest); + int ndb; + char **databaselist; + Z_Query *zquery; + + yaz_log(YLOG_DEBUG, "Sending search"); + a->u.searchRequest->query = zquery = odr_malloc(t->odr_out, sizeof(Z_Query)); + zquery->which = Z_Query_type_1; + zquery->u.type_1 = p_query_rpn(t->odr_out, PROTO_Z3950, s->query); + + for (ndb = 0; *t->databases[ndb]; ndb++) + ; + databaselist = odr_malloc(t->odr_out, sizeof(char*) * ndb); + for (ndb = 0; *t->databases[ndb]; ndb++) + databaselist[ndb] = t->databases[ndb]; + + a->u.searchRequest->resultSetName = "Default"; + a->u.searchRequest->databaseNames = databaselist; + a->u.searchRequest->num_databaseNames = ndb; + + if (send_apdu(t, a) >= 0) + { + iochan_setflags(i, EVENT_INPUT); + t->state = Searching; + t->requestid = s->requestid; + } + else + { + iochan_destroy(i); + t->state = Failed; + cs_close(t->link); + } + odr_reset(t->odr_out); +} + +static void send_present(IOCHAN i) +{ + struct target *t = iochan_getdata(i); + Z_APDU *a = zget_APDU(t->odr_out, Z_APDU_presentRequest); + int toget; + + toget = global_parameters.chunk; + if (toget > t->hits - t->records) + toget = t->hits - t->records; + + yaz_log(YLOG_DEBUG, "Trying to present %d records\n", toget); + + a->u.presentRequest->numberOfRecordsRequested = &toget; + + a->u.presentRequest->resultSetId = "Default"; + + if (send_apdu(t, a) >= 0) + { + iochan_setflags(i, EVENT_INPUT); + t->state = Presenting; + } + else + { + iochan_destroy(i); + t->state = Failed; + cs_close(t->link); + } + odr_reset(t->odr_out); +} + +static void do_initResponse(IOCHAN i, Z_APDU *a) +{ + struct target *t = iochan_getdata(i); + Z_InitResponse *r = a->u.initResponse; + + yaz_log(YLOG_DEBUG, "Received init response"); + + if (*r->result) + { + t->state = Idle; + } + else + { + t->state = Failed; + iochan_destroy(i); + cs_close(t->link); + } +} + +#if 0 +static char *search_geterror(Z_SearchRequest *r) +{ +#endif + + +static void do_searchResponse(IOCHAN i, Z_APDU *a) +{ + struct target *t = iochan_getdata(i); + Z_SearchResponse *r = a->u.searchResponse; + + yaz_log(YLOG_DEBUG, "Searchresponse (status=%d)", *r->searchStatus); + + if (*r->searchStatus) + { + t->hits = *r->resultCount; + t->state = Idle; + } + else + { /*"FAILED"*/ + t->hits = 0; + t->state = Failed; + if (r->records) { + Z_Records *recs = r->records; + if (recs->which == Z_Records_NSD) + { + yaz_log(YLOG_WARN, "Non-surrogate diagnostic"); + t->diagnostic = *recs->u.nonSurrogateDiagnostic->condition; + t->state = Error; + } + } + } +} + +// FIXME Catch present errors!!!!!!! +static void do_presentResponse(IOCHAN i, Z_APDU *a) +{ + struct target *t = iochan_getdata(i); + Z_PresentResponse *r = a->u.presentResponse; + + if (r->records) { + Z_Records *recs = r->records; + if (recs->which == Z_Records_NSD) + { + yaz_log(YLOG_WARN, "Non-surrogate diagnostic"); + t->diagnostic = *recs->u.nonSurrogateDiagnostic->condition; + t->state = Error; + } + else + { + yaz_log(YLOG_DEBUG, "Got Records!"); + } + } + + if (!*r->presentStatus && t->state != Error) + { + yaz_log(YLOG_DEBUG, "Good Present response"); + t->records += *r->numberOfRecordsReturned; + t->state = Idle; + } + else if (*r->presentStatus) + { + yaz_log(YLOG_WARN, "Bad Present response"); + t->state = Error; + } +} + +static void handler(IOCHAN i, int event) +{ + struct target *t = iochan_getdata(i); + struct session *s = t->session; + //static int waiting = 0; + + if (t->state == No_connection) /* Start connection */ + { + int res = cs_connect(t->link, t->addr); + + t->state = Connecting; + if (!res) /* we are go */ + iochan_setevent(i, EVENT_OUTPUT); + else if (res == 1) + iochan_setflags(i, EVENT_OUTPUT); + else + { + yaz_log(YLOG_WARN|YLOG_ERRNO, "ERROR %s connect\n", t->hostport); + cs_close(t->link); + t->state = Failed; + iochan_destroy(i); + } + } + + else if (t->state == Connecting && event & EVENT_OUTPUT) + { + int errcode; + socklen_t errlen = sizeof(errcode); + + if (getsockopt(cs_fileno(t->link), SOL_SOCKET, SO_ERROR, &errcode, + &errlen) < 0 || errcode != 0) + { + cs_close(t->link); + iochan_destroy(i); + t->state = Failed; + return; + } + else + { + yaz_log(YLOG_DEBUG, "Connect OK"); + t->state = Connected; + } + } + + else if (event & EVENT_INPUT) + { + int len = cs_get(t->link, &t->ibuf, &t->ibufsize); + + if (len < 0) + { + cs_close(t->link); + iochan_destroy(i); + t->state = Failed; + return; + } + if (len == 0) + { + cs_close(t->link); + iochan_destroy(i); + t->state = Failed; + return; + } + else if (len > 1) + { + if (t->requestid == s->requestid || t->state == Initializing) + { + Z_APDU *a; + + odr_reset(t->odr_in); + odr_setbuf(t->odr_in, t->ibuf, len, 0); + if (!z_APDU(t->odr_in, &a, 0, 0)) + { + cs_close(t->link); + iochan_destroy(i); + t->state = Failed; + return; + } + switch (a->which) + { + case Z_APDU_initResponse: + do_initResponse(i, a); + break; + case Z_APDU_searchResponse: + do_searchResponse(i, a); + break; + case Z_APDU_presentResponse: + do_presentResponse(i, a); + break; + default: + yaz_log(YLOG_WARN, "Unexpected result from server"); + cs_close(t->link); + iochan_destroy(i); + t->state = Failed; + return; + } + // if (cs_more(t->link)) + // iochan_setevent(i, EVENT_INPUT); + } + else // we throw away response and go to idle mode + t->state = Idle; + } + /* if len==1 we do nothing but wait for more input */ + } + + else if (t->state == Connected) { + send_init(i); + } + + if (t->state == Idle) + { + if (t->requestid != s->requestid) { + send_search(i); + } + else if (t->hits > 0 && t->records < global_parameters.toget && + t->records < t->hits) { + send_present(i); + } + } +} + +int load_targets(struct session *s, const char *fn) +{ + FILE *f = fopen(fn, "r"); + char line[256]; + struct target **target_p; + + if (!f) + { + yaz_log(YLOG_WARN|YLOG_ERRNO, "open %s", fn); + return -1; + } + + target_p = &s->targets; + while (fgets(line, 255, f)) + { + char *url, *p; + struct target *target; + IOCHAN new; + + if (strncmp(line, "target ", 7)) + continue; + url = line + 7; + url[strlen(url) - 1] = '\0'; + yaz_log(LOG_DEBUG, "Target: %s", url); + + *target_p = target = xmalloc(sizeof(**target_p)); + target->next = 0; + target_p = &target->next; + target->state = No_connection; + target->ibuf = 0; + target->ibufsize = 0; + target->odr_in = odr_createmem(ODR_DECODE); + target->odr_out = odr_createmem(ODR_ENCODE); + target->hits = -1; + target->setno = 0; + target->session = s; + target->requestid = -1; + target->records = 0; + target->diagnostic = 0; + strcpy(target->fullname, url); + if ((p = strchr(url, '/'))) + { + *p = '\0'; + strcpy(target->hostport, url); + *p = '/'; + p++; + strcpy(target->databases[0], p); + target->databases[1][0] = '\0'; + } + else + { + strcpy(target->hostport, url); + strcpy(target->databases[0], "Default"); + target->databases[1][0] = '\0'; + } + + if (!(target->link = cs_create(tcpip_type, 0, PROTO_Z3950))) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create comstack"); + exit(1); + } + if (!(target->addr = cs_straddr(target->link, target->hostport))) + { + printf("ERROR %s bad-address", target->hostport); + target->state = Failed; + continue; + } + new = iochan_create(cs_fileno(target->link), handler, 0); + iochan_setdata(new, target); + iochan_setevent(new, EVENT_EXCEPT); + new->next = channel_list; + channel_list = new; + } + fclose(f); + + return 0; +} + +void search(struct session *s, char *query) +{ + IOCHAN c; + + yaz_log(YLOG_DEBUG, "Search"); + + // Determine what iochans belong to this session + // It might have been better to have a list of them + + strcpy(s->query, query); + s->requestid++; + nmem_reset(s->nmem); + for (c = channel_list; c; c = c->next) + { + struct target *t; + + if (iochan_getfun(c) != handler) // Not a Z target + continue; + t = iochan_getdata(c); + if (t->session == s) + { + t->hits = -1; + t->records = 0; + t->diagnostic = 0; + + if (t->state == Error) + t->state = Idle; + + if (t->state == Idle) + iochan_setflag(c, EVENT_OUTPUT); + } + } +} + +struct session *new_session() +{ + struct session *session = xmalloc(sizeof(*session)); + + yaz_log(YLOG_DEBUG, "New pazpar2 session"); + + session->requestid = -1; + session->targets = 0; + session->pqf_parser = yaz_pqf_create(); + session->query[0] = '\0'; + session->nmem = nmem_create(); + + return session; +} + +struct hitsbytarget *hitsbytarget(struct session *s, int *count) +{ + static struct hitsbytarget res[1000]; // FIXME MM + IOCHAN c; + + *count = 0; + for (c = channel_list; c; c = c->next) + if (iochan_getfun(c) == handler) + { + struct target *t = iochan_getdata(c); + if (t->session == s) + { + strcpy(res[*count].id, t->hostport); + res[*count].hits = t->hits; + res[*count].records = t->records; + res[*count].diagnostic = t->diagnostic; + res[*count].state = state_strings[(int) t->state]; + (*count)++; + } + } + + return res; +} + + +void statistics(struct session *s, struct statistics *stat) +{ + IOCHAN c; + int i; + + bzero(stat, sizeof(*stat)); + for (i = 0, c = channel_list; c; i++, c = c->next) + { + struct target *t; + if (iochan_getfun(c) != handler) + continue; + t = iochan_getdata(c); + switch (t->state) + { + case No_connection: stat->num_no_connection++; break; + case Connecting: stat->num_connecting++; break; + case Initializing: stat->num_initializing++; break; + case Searching: stat->num_searching++; break; + case Presenting: stat->num_presenting++; break; + case Idle: stat->num_idle++; break; + case Failed: stat->num_failed++; break; + case Error: stat->num_error++; break; + default: break; + } + } + + stat->num_connections = i; +} + +int main(int argc, char **argv) +{ + int ret; + char *arg; + + if (signal(SIGPIPE, SIG_IGN) < 0) + yaz_log(YLOG_WARN|YLOG_ERRNO, "signal"); + + myname = argv[0]; + yaz_log_init(YLOG_DEFAULT_LEVEL|YLOG_DEBUG, "pazpar2", 0); + + while ((ret = options("c:", argv, argc, &arg)) != -2) + { + switch (ret) { + case 0: + break; + case 'c': + command_init(atoi(arg)); + break; + default: + fprintf(stderr, "Usage: pazpar2 -d comport"); + exit(1); + } + + } + + event_loop(&channel_list); + + return 0; +} + +/* + * Local variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ diff --git a/pazpar2.h b/pazpar2.h new file mode 100644 index 0000000..1e22b78 --- /dev/null +++ b/pazpar2.h @@ -0,0 +1,57 @@ +#ifndef PAZPAR2_H +#define PAZPAR2_H + +#include + +struct session { + struct target *targets; + YAZ_PQF_Parser pqf_parser; + int requestid; + char query[1024]; + NMEM nmem; +}; + +struct record { + struct target *target; + int target_offset; + char *buf; + char *merge_key; + struct record *next_cluster; + struct record *head_cluster; +}; + +struct statistics { + int num_connections; + int num_no_connection; + int num_connecting; + int num_initializing; + int num_searching; + int num_presenting; + int num_idle; + int num_failed; + int num_error; +}; + +struct hitsbytarget { + char id[256]; + int hits; + int diagnostic; + int records; + char* state; +}; + +struct hitsbytarget *hitsbytarget(struct session *s, int *count); +struct session *new_session(); +int load_targets(struct session *s, const char *fn); +void statistics(struct session *s, struct statistics *stat); +void search(struct session *s, char *query); + +#endif + +/* + * Local variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ diff --git a/test.pz b/test.pz new file mode 100644 index 0000000..0fb10c8 --- /dev/null +++ b/test.pz @@ -0,0 +1 @@ +target localhost:9999/Default diff --git a/util.c b/util.c new file mode 100644 index 0000000..a92d340 --- /dev/null +++ b/util.c @@ -0,0 +1,13 @@ +/* $Id: util.c,v 1.1 2006-11-14 20:44:38 quinn Exp $ */ + +#include +#include + +extern char *myname; + +void die(char *string, char *add) +{ + fprintf(stderr, "%s: %s (%s)\n", myname, string, add ? add : ""); + abort(); +} + diff --git a/util.h b/util.h new file mode 100644 index 0000000..10f7981 --- /dev/null +++ b/util.h @@ -0,0 +1,8 @@ +/* $Id: util.h,v 1.1 2006-11-14 20:44:38 quinn Exp $ */ + +#ifndef UTIL_H +#define UTIL_H + +void die(char *string, char *add); + +#endif