Implemented session timeout; ping command
authorSebastian Hammer <quinn@indexdata.com>
Tue, 12 Dec 2006 02:36:24 +0000 (02:36 +0000)
committerSebastian Hammer <quinn@indexdata.com>
Tue, 12 Dec 2006 02:36:24 +0000 (02:36 +0000)
PROTOCOL
TODO
eventl.c
eventl.h
http.h
http_command.c
pazpar2.c
pazpar2.h

index 2f9c22f..62bd822 100644 (file)
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -18,6 +18,23 @@ Response example:
   <session>2044502273</session>
 </init>
 
+ping
+
+Keeps a session alive. An idle session will time out after one minute. The
+ping command can be used to keep the session alive absent other activity. It
+is suggested that any browser client have a simple alarm handler which
+sends a ping every 50 seconds or so once a session has been initialized.
+
+Example:
+
+search.pz?command=ping&session=2044502273
+
+Response example:
+
+<ping>
+  <status>OK</status>
+</ping>
+
 search
 
 Launches a search, parameters:
diff --git a/TODO b/TODO
index 4d6696d..096e8e3 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,19 +1,18 @@
 Short term: 
 
-Structured target profiles -- Zeerex?
+Structured target profiles -- Zeerex?  -- requires libxml
 Normalization of records -- test if libXSLT is fast enough to:
   -- Extract Subject headings, titles, dates, authors for facets and display
   -- Merge keys for relevance ranking, etc.
   -- Also normalize to UTF-8.
-Implement timeout of sessions, so they don't sit there forever (simple).
 Factor Z39.50 stuff out from pazpar2.c to separate file to make room for
    later SRU implementation.
 Sort by title, date, author. Parameter to 'show' webservice command.
-Additional facets. At least do 'author'.. think about making it general.
+Additional facets. At least do 'author'.. think about making it general. -- libxml
 Support for 'blocking' requests, at least for record display before first records
    are retrieved (to reduce polling).
 Implement detection of 'search complete', so client knows when to stop polling.
-Full record retrieval.
+Full record retrieval. -- libxml
 Implement hitsbytarget function to emulate traditional LOT-style U/I
 
 Longer term:
index fc188a3..87bd1ba 100644 (file)
--- a/eventl.c
+++ b/eventl.c
@@ -6,7 +6,7 @@
  */
 
 /*
- * $Id: eventl.c,v 1.1 2006-11-14 20:44:37 quinn Exp $
+ * $Id: eventl.c,v 1.2 2006-12-12 02:36:24 quinn Exp $
  * Based on revision YAZ' server/eventl.c 1.29.
  */
 
@@ -63,6 +63,8 @@ int event_loop(IOCHAN *iochans)
        max = 0;
        for (p = *iochans; p; p = p->next)
        {
+            if (p->fd < 0)
+                continue;
            if (p->force_event)
                timeout = &nullto;        /* polling select */
            if (p->flags & EVENT_INPUT)
@@ -87,6 +89,14 @@ int event_loop(IOCHAN *iochans)
            time_t now = time(0);
 
            p->force_event = 0;
+           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);
+           }
+            if (p->fd < 0)
+                continue;
            if (!p->destroyed && (FD_ISSET(p->fd, &in) ||
                force_event == EVENT_INPUT))
            {
@@ -105,12 +115,6 @@ int event_loop(IOCHAN *iochans)
                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)
        {
@@ -140,3 +144,11 @@ int event_loop(IOCHAN *iochans)
     while (*iochans);
     return 0;
 }
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
index 967d5dc..9e10817 100644 (file)
--- a/eventl.h
+++ b/eventl.h
@@ -4,7 +4,10 @@
  * Sebastian Hammer, Adam Dickmeiss
  *
  * $Log: eventl.h,v $
- * Revision 1.2  2006-11-18 05:00:38  quinn
+ * Revision 1.3  2006-12-12 02:36:24  quinn
+ * Implemented session timeout; ping command
+ *
+ * Revision 1.2  2006/11/18 05:00:38  quinn
  * Added record retrieval, etc.
  *
  * Revision 1.1.1.1  2006/11/14 20:44:38  quinn
@@ -93,6 +96,7 @@ typedef struct iochan
 #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))
+#define iochan_activity(i) ((i)->last_event = time(0))
 
 IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags);
 int event_loop(IOCHAN *iochans);
diff --git a/http.h b/http.h
index 3fa3a3b..d5b1d07 100644 (file)
--- a/http.h
+++ b/http.h
@@ -21,7 +21,7 @@ struct http_channel
     enum
     {
         Http_Idle,
-        Http_Busy      // Don't process new HTTP requests
+        Http_Busy      // Don't process new HTTP requests while we're busy
     } state;
     NMEM nmem;
     WRBUF wrbuf;
index 517ea10..194cb8c 100644 (file)
@@ -1,5 +1,5 @@
 /*_response(c, rs);
- * $Id: http_command.c,v 1.7 2006-12-08 21:40:58 quinn Exp $
+ * $Id: http_command.c,v 1.8 2006-12-12 02:36:24 quinn Exp $
  */
 
 #include <stdio.h>
 #include "http.h"
 #include "http_command.h"
 
+extern struct parameters global_parameters;
+extern IOCHAN channel_list;
+
 struct http_session {
+    IOCHAN timeout_iochan;     // NOTE: This is NOT associated with a socket
     struct session *psession;
     int session_id;
     int timestamp;
@@ -29,6 +33,14 @@ struct http_session {
 
 static struct http_session *session_list = 0;
 
+void http_session_destroy(struct http_session *s);
+
+static void session_timeout(IOCHAN i, int event)
+{
+    struct http_session *s = iochan_getdata(i);
+    http_session_destroy(s);
+}
+
 struct http_session *http_session_create()
 {
     struct http_session *r = xmalloc(sizeof(*r));
@@ -37,6 +49,11 @@ struct http_session *http_session_create()
     r->timestamp = 0;
     r->next = session_list;
     session_list = r;
+    r->timeout_iochan = iochan_create(-1, session_timeout, 0);
+    iochan_setdata(r->timeout_iochan, r);
+    iochan_settimeout(r->timeout_iochan, global_parameters.session_timeout);
+    r->timeout_iochan->next = channel_list;
+    channel_list = r->timeout_iochan;
     return r;
 }
 
@@ -50,7 +67,8 @@ void http_session_destroy(struct http_session *s)
             *p = (*p)->next;
             break;
         }
-    session_destroy(s->psession);
+    iochan_destroy(s->timeout_iochan);
+    destroy_session(s->psession);
     xfree(s);
 }
 
@@ -96,7 +114,10 @@ static struct http_session *locate_session(struct http_request *rq, struct http_
     id = atoi(session);
     for (p = session_list; p; p = p->next)
         if (id == p->session_id)
+        {
+            iochan_activity(p->timeout_iochan);
             return p;
+        }
     error(rs, "417", "Session does not exist, or it has expired", 0);
     return 0;
 }
@@ -107,6 +128,7 @@ static void cmd_exit(struct http_channel *c)
     exit(0);
 }
 
+
 static void cmd_init(struct http_channel *c)
 {
     int sesid;
@@ -236,6 +258,17 @@ static void cmd_show(struct http_channel *c)
     http_send_response(c);
 }
 
+static void cmd_ping(struct http_channel *c)
+{
+    struct http_request *rq = c->request;
+    struct http_response *rs = c->response;
+    struct http_session *s = locate_session(rq, rs);
+    if (!s)
+        return;
+    rs->payload = "<ping><status>OK</status></ping>";
+    http_send_response(c);
+}
+
 static void cmd_search(struct http_channel *c)
 {
     struct http_request *rq = c->request;
@@ -299,14 +332,12 @@ struct {
 } commands[] = {
     { "init", cmd_init },
     { "stat", cmd_stat },
-#ifdef GAGA
-    { "load", cmd_load },
-#endif
     { "bytarget", cmd_bytarget },
     { "show", cmd_show },
     { "search", cmd_search },
     { "termlist", cmd_termlist },
     { "exit", cmd_exit },
+    { "ping", cmd_ping },
     {0,0}
 };
 
index d8d8756..f953a7d 100644 (file)
--- a/pazpar2.c
+++ b/pazpar2.c
@@ -1,4 +1,4 @@
-/* $Id: pazpar2.c,v 1.11 2006-12-08 21:40:58 quinn Exp $ */;
+/* $Id: pazpar2.c,v 1.12 2006-12-12 02:36:24 quinn 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"
@@ -57,25 +55,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,
@@ -1121,7 +1108,7 @@ 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;
 }
@@ -1182,6 +1169,15 @@ 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() 
 {
     struct session *session = xmalloc(sizeof(*session));
@@ -1203,11 +1199,6 @@ struct session *new_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
index 0aab010..a14d691 100644 (file)
--- a/pazpar2.h
+++ b/pazpar2.h
@@ -7,6 +7,8 @@ struct record;
 
 #include <yaz/comstack.h>
 #include <yaz/pquery.h>
+#include <yaz/ccl.h>
+#include <yaz/yaz-ccl.h>
 #include "termlists.h"
 #include "relevance.h"
 #include "eventl.h"
@@ -124,10 +126,25 @@ struct hitsbytarget {
     int connected;
 };
 
+struct parameters {
+    int timeout;               /* operations timeout, in seconds */
+    char implementationId[128];
+    char implementationName[128];
+    char implementationVersion[128];
+    int target_timeout; // seconds
+    int session_timeout;
+    int toget;
+    int chunk;
+    CCL_bibset ccl_filter;
+    yaz_marc_t yaz_marc;
+    ODR odr_out;
+    ODR odr_in;
+};
+
 struct hitsbytarget *hitsbytarget(struct session *s, int *count);
 int select_targets(struct session *se);
 struct session *new_session();
-void session_destroy(struct session *s);
+void destroy_session(struct session *s);
 int load_targets(struct session *s, const char *fn);
 void statistics(struct session *s, struct statistics *stat);
 char *search(struct session *s, char *query);