Undeclared constant LOG_DEBUG, should be YLOG_DEBUG.
[pazpar2-moved-to-github.git] / pazpar2.c
index 359e7a8..13b9b6c 100644 (file)
--- a/pazpar2.c
+++ b/pazpar2.c
@@ -1,4 +1,4 @@
-/* $Id: pazpar2.c,v 1.8 2006-12-03 06:43:24 quinn Exp $ */;
+/* $Id: pazpar2.c,v 1.15 2006-12-18 14:37:21 sondberg Exp $ */;
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -17,8 +17,6 @@
 #include <yaz/readconf.h>
 #include <yaz/pquery.h>
 #include <yaz/yaz-util.h>
-#include <yaz/ccl.h>
-#include <yaz/yaz-ccl.h>
 
 #include "pazpar2.h"
 #include "eventl.h"
 #include "relevance.h"
 
 #define PAZPAR2_VERSION "0.1"
-#define MAX_CHUNK 10
+#define MAX_CHUNK 15
 
 static void client_fatal(struct client *cl);
 static void connection_destroy(struct connection *co);
 static int client_prep_connection(struct client *cl);
+static void ingest_records(struct client *cl, Z_Records *r);
+void session_alert_watch(struct session *s, int what);
 
-IOCHAN channel_list = 0;  // Master list of connections we're listening to.
+IOCHAN channel_list = 0;  // Master list of connections we're handling events to
 
 static struct connection *connection_freelist = 0;
 static struct client *client_freelist = 0;
@@ -56,25 +56,14 @@ static char *client_states[] = {
     "Client_Stopped"
 };
 
-static struct parameters {
-    int timeout;               /* operations timeout, in seconds */
-    char implementationId[128];
-    char implementationName[128];
-    char implementationVersion[128];
-    int target_timeout; // seconds
-    int toget;
-    int chunk;
-    CCL_bibset ccl_filter;
-    yaz_marc_t yaz_marc;
-    ODR odr_out;
-    ODR odr_in;
-} global_parameters = 
+struct parameters global_parameters = 
 {
     30,
     "81",
     "Index Data PazPar2 (MasterKey)",
     PAZPAR2_VERSION,
     600, // 10 minutes
+    60,
     100,
     MAX_CHUNK,
     0,
@@ -151,6 +140,7 @@ static void send_search(IOCHAN i)
     char **databaselist;
     Z_Query *zquery;
     struct ccl_rpn_node *cn;
+    int ssub = 0, lslb = 100000, mspn = 10;
 
     yaz_log(YLOG_DEBUG, "Sending search");
 
@@ -169,6 +159,12 @@ static void send_search(IOCHAN i)
     for (ndb = 0; *db->databases[ndb]; ndb++)
        databaselist[ndb] = db->databases[ndb];
 
+    a->u.presentRequest->preferredRecordSyntax =
+            yaz_oidval_to_z3950oid(global_parameters.odr_out,
+            CLASS_RECSYN, VAL_USMARC);
+    a->u.searchRequest->smallSetUpperBound = &ssub;
+    a->u.searchRequest->largeSetLowerBound = &lslb;
+    a->u.searchRequest->mediumSetPresentNumber = &mspn;
     a->u.searchRequest->resultSetName = "Default";
     a->u.searchRequest->databaseNames = databaselist;
     a->u.searchRequest->num_databaseNames = ndb;
@@ -246,8 +242,14 @@ static void do_searchResponse(IOCHAN i, Z_APDU *a)
     if (*r->searchStatus)
     {
        cl->hits = *r->resultCount;
-        cl->state = Client_Idle;
         se->total_hits += cl->hits;
+        if (r->presentStatus && !*r->presentStatus && r->records)
+        {
+            yaz_log(YLOG_DEBUG, "Records in search response");
+            cl->records += *r->numberOfRecordsReturned;
+            ingest_records(cl, r->records);
+        }
+        cl->state = Client_Idle;
     }
     else
     {          /*"FAILED"*/
@@ -345,11 +347,11 @@ char *extract_title(struct session *s, const char *rec)
         }
     }
     wrbuf_putc(s->wrbuf, '\0');
-    obuf = nmem_strdup(s->nmem, wrbuf_buf(s->wrbuf));
+    obuf = (unsigned char*) nmem_strdup(s->nmem, wrbuf_buf(s->wrbuf));
     for (p = obuf; *p; p++)
         if (*p == '&' || *p == '<' || *p > 122 || *p < ' ')
             *p = ' ';
-    return obuf;
+    return (char*) obuf;
 }
 
 // Extract 245 $a $b 100 $a
@@ -594,7 +596,7 @@ static void pull_relevance_keys(struct session *s, struct record *head,  struct
     relevance_donerecord(s->relevance, head);
 }
 
-struct record *ingest_record(struct client *cl, char *buf, int len)
+static struct record *ingest_record(struct client *cl, char *buf, int len)
 {
     struct session *se = cl->session;
     struct record *res;
@@ -634,9 +636,10 @@ struct record *ingest_record(struct client *cl, char *buf, int len)
     return res;
 }
 
-void ingest_records(struct client *cl, Z_Records *r)
+static void ingest_records(struct client *cl, Z_Records *r)
 {
     struct record *rec;
+    struct session *s = cl->session;
     Z_NamePlusRecordList *rlist;
     int i;
 
@@ -668,6 +671,8 @@ void ingest_records(struct client *cl, Z_Records *r)
         if (!rec)
             continue;
     }
+    if (s->watchlist[SESSION_WATCH_RECORDS].fun && rlist->num_records)
+        session_alert_watch(s, SESSION_WATCH_RECORDS);
 }
 
 static void do_presentResponse(IOCHAN i, Z_APDU *a)
@@ -735,12 +740,14 @@ static void handler(IOCHAN i, int event)
 
        if (len < 0)
        {
-            client_fatal(cl);
+            yaz_log(YLOG_WARN|YLOG_ERRNO, "Error reading from Z server");
+            connection_destroy(co);
            return;
        }
         else if (len == 0)
        {
-            client_fatal(cl);
+            yaz_log(YLOG_WARN, "EOF reading from Z server");
+            connection_destroy(co);
            return;
        }
        else if (len > 1) // We discard input if we have no connection
@@ -969,7 +976,7 @@ void load_simpletargets(const char *fn)
             continue;
         url = line + 7;
         url[strlen(url) - 1] = '\0';
-        yaz_log(LOG_DEBUG, "Target: %s", url);
+        yaz_log(YLOG_DEBUG, "Target: %s", url);
         if ((db = strchr(url, '/')))
             *(db++) = '\0';
         else
@@ -1107,11 +1114,26 @@ void client_destroy(struct client *c)
             cc->next = c->next;
     }
     if (c->connection)
-        connection_destroy(c->connection);
+        connection_release(c->connection);
     c->next = client_freelist;
     client_freelist = c;
 }
 
+void session_set_watch(struct session *s, int what, session_watchfun fun, void *data)
+{
+    s->watchlist[what].fun = fun;
+    s->watchlist[what].data = data;
+}
+
+void session_alert_watch(struct session *s, int what)
+{
+    if (!s->watchlist[what].fun)
+        return;
+    (*s->watchlist[what].fun)(s->watchlist[what].data);
+    s->watchlist[what].fun = 0;
+    s->watchlist[what].data = 0;
+}
+
 // This should be extended with parameters to control selection criteria
 // Associates a set of clients with a session;
 int select_targets(struct session *se)
@@ -1168,8 +1190,18 @@ char *search(struct session *se, char *query)
     return 0;
 }
 
+void destroy_session(struct session *s)
+{
+    yaz_log(YLOG_LOG, "Destroying session");
+    while (s->clients)
+        client_destroy(s->clients);
+    nmem_destroy(s->nmem);
+    wrbuf_free(s->wrbuf, 1);
+}
+
 struct session *new_session() 
 {
+    int i;
     struct session *session = xmalloc(sizeof(*session));
 
     yaz_log(YLOG_DEBUG, "New pazpar2 session");
@@ -1183,17 +1215,17 @@ struct session *new_session()
     session->query[0] = '\0';
     session->nmem = nmem_create();
     session->wrbuf = wrbuf_alloc();
+    for (i = 0; i <= SESSION_WATCH_MAX; i++)
+    {
+        session->watchlist[i].data = 0;
+        session->watchlist[i].fun = 0;
+    }
 
     select_targets(session);
 
     return session;
 }
 
-void session_destroy(struct session *s)
-{
-    // FIXME do some shit here!!!!
-}
-
 struct hitsbytarget *hitsbytarget(struct session *se, int *count)
 {
     static struct hitsbytarget res[1000]; // FIXME MM
@@ -1293,6 +1325,7 @@ int main(int argc, char **argv)
 {
     int ret;
     char *arg;
+    int setport = 0;
 
     if (signal(SIGPIPE, SIG_IGN) < 0)
         yaz_log(YLOG_WARN|YLOG_ERRNO, "signal");
@@ -1302,16 +1335,16 @@ int main(int argc, char **argv)
     while ((ret = options("c:h:p:C:s:", argv, argc, &arg)) != -2)
     {
        switch (ret) {
-           case 0:
-               break;
            case 'c':
                command_init(atoi(arg));
+                setport++;
                break;
-            case 'C':
-                global_parameters.ccl_filter = load_cclfile(arg);
-                break;
             case 'h':
                 http_init(atoi(arg));
+                setport++;
+                break;
+            case 'C':
+                global_parameters.ccl_filter = load_cclfile(arg);
                 break;
             case 'p':
                 http_set_proxyaddr(arg);
@@ -1320,11 +1353,22 @@ int main(int argc, char **argv)
                 load_simpletargets(arg);
                 break;
            default:
-               fprintf(stderr, "Usage: pazpar2 -d comport");
+               fprintf(stderr, "Usage: pazpar2\n"
+                        "    -h httpport             (REST)\n"
+                        "    -c cmdport              (telnet-style)\n"
+                        "    -C cclconfig\n"
+                        "    -s simpletargetfile\n"
+                        "    -p hostname[:portno]    (HTTP proxy)\n");
                exit(1);
        }
     }
 
+    if (!setport)
+    {
+        fprintf(stderr, "Set command port with -h or -c\n");
+        exit(1);
+    }
+
     global_parameters.ccl_filter = load_cclfile("default.bib");
     global_parameters.yaz_marc = yaz_marc_create();
     yaz_marc_subfield_str(global_parameters.yaz_marc, "\t");