Use queue for raw show; to solve Bug #1644.
authorAdam Dickmeiss <adam@indexdata.dk>
Tue, 2 Oct 2007 12:11:14 +0000 (12:11 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Tue, 2 Oct 2007 12:11:14 +0000 (12:11 +0000)
The client system now makes a queue of requests to be carried out
(struct show_raw). Howevever, HTTP connection closing could be handled
more elegantly (to say the least).

src/client.c
src/client.h
src/http.c
src/http.h
src/http_command.c
src/logic.c

index dffb359..ca8b067 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: client.c,v 1.27 2007-10-02 10:32:03 adam Exp $
+/* $Id: client.c,v 1.28 2007-10-02 12:11:14 adam Exp $
    Copyright (c) 2006-2007, Index Data.
 
 This file is part of Pazpar2.
@@ -89,6 +89,7 @@ struct show_raw {
     void (*error_handler)(void *data, const char *addinfo);
     void (*record_handler)(void *data, const char *buf, size_t sz);
     void *data;
+    struct show_raw *next;
 };
 
 static const char *client_states[] = {
@@ -236,32 +237,35 @@ int client_show_raw_begin(struct client *cl, int position,
                           void *data,
                           void (*error_handler)(void *data, const char *addinfo),
                           void (*record_handler)(void *data, const char *buf,
-                                                 size_t sz))
+                                                 size_t sz),
+                          void **data2)
 {
-    if (cl->show_raw)
-    {   /* raw show already in progress */
-        return -1;
-    }
+    struct show_raw *rr, **rrp;
     if (!cl->connection)
     {   /* the client has no connection */
-        return -2;
+        return -1;
     }
-    cl->show_raw = xmalloc(sizeof(*cl->show_raw));
-    cl->show_raw->position = position;
-    cl->show_raw->active = 0;
-    cl->show_raw->data = data;
-    cl->show_raw->error_handler = error_handler;
-    cl->show_raw->record_handler = record_handler;
+    rr = xmalloc(sizeof(*rr));
+    *data2 = rr;
+    rr->position = position;
+    rr->active = 0;
+    rr->data = data;
+    rr->error_handler = error_handler;
+    rr->record_handler = record_handler;
     if (syntax)
-        cl->show_raw->syntax = xstrdup(syntax);
+        rr->syntax = xstrdup(syntax);
     else
-        cl->show_raw->syntax = 0;
+        rr->syntax = 0;
     if (esn)
-        cl->show_raw->esn = xstrdup(esn);
+        rr->esn = xstrdup(esn);
     else
-        cl->show_raw->esn = 0;
+        rr->esn = 0;
+    rr->next = 0;
+    
+    for (rrp = &cl->show_raw; *rrp; rrp = &(*rrp)->next)
+        ;
+    *rrp = rr;
     
-
     if (cl->state == Client_Failed)
     {
         client_show_raw_error(cl, "client failed");
@@ -277,27 +281,42 @@ int client_show_raw_begin(struct client *cl, int position,
     return 0;
 }
 
-void client_show_raw_reset(struct client *cl)
+void client_show_raw_remove(struct client *cl, void *data)
+{
+    struct show_raw *rr = data;
+    struct show_raw **rrp = &cl->show_raw;
+    while (*rrp != rr)
+        rrp = &(*rrp)->next;
+    if (*rrp)
+    {
+        *rrp = rr->next;
+        xfree(rr);
+    }
+}
+
+void client_show_raw_dequeue(struct client *cl)
 {
-    xfree(cl->show_raw);
-    cl->show_raw = 0;
+    struct show_raw *rr = cl->show_raw;
+
+    cl->show_raw = rr->next;
+    xfree(rr);
 }
 
 static void client_show_raw_error(struct client *cl, const char *addinfo)
 {
-    if (cl->show_raw)
+    while (cl->show_raw)
     {
         cl->show_raw->error_handler(cl->show_raw->data, addinfo);
-        client_show_raw_reset(cl);
+        client_show_raw_dequeue(cl);
     }
 }
 
 static void client_show_raw_cancel(struct client *cl)
 {
-    if (cl->show_raw)
+    while (cl->show_raw)
     {
         cl->show_raw->error_handler(cl->show_raw->data, "cancel");
-        client_show_raw_reset(cl);
+        client_show_raw_dequeue(cl);
     }
 }
 
@@ -555,12 +574,13 @@ static void ingest_raw_records(struct client *cl, Z_Records *r)
     xmlDocDumpMemory(doc, &buf_out, &len_out);
     xmlFreeDoc(doc);
 
-    cl->show_raw->record_handler(cl->show_raw->data,
-                                 (const char *) buf_out, len_out);
-    
+    if (cl->show_raw)
+    {
+        cl->show_raw->record_handler(cl->show_raw->data,
+                                     (const char *) buf_out, len_out);
+        client_show_raw_dequeue(cl);
+    }
     xmlFree(buf_out);
-    xfree(cl->show_raw);
-    cl->show_raw = 0;
 }
 
 static void ingest_records(struct client *cl, Z_Records *r)
index ba40fc1..7af4630 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: client.h,v 1.4 2007-09-20 08:13:27 adam Exp $
+/* $Id: client.h,v 1.5 2007-10-02 12:11:14 adam Exp $
    Copyright (c) 2006-2007, Index Data.
 
 This file is part of Pazpar2.
@@ -49,8 +49,9 @@ int client_show_raw_begin(struct client *cl, int position,
                           void *data,
                           void (*error_handler)(void *data, const char *addinfo),
                           void (*record_handler)(void *data, const char *buf,
-                                                 size_t sz));
-void client_show_raw_reset(struct client *cl);
+                                                 size_t sz),
+                          void **data2);
+void client_show_raw_remove(struct client *cl, void *rr);
 
 const char *client_get_state_str(struct client *cl);
 enum client_state client_get_state(struct client *cl);
index dfc4f38..9a142d7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: http.c,v 1.40 2007-09-26 09:09:15 adam Exp $
+/* $Id: http.c,v 1.41 2007-10-02 12:11:14 adam Exp $
    Copyright (c) 2006-2007, Index Data.
 
 This file is part of Pazpar2.
@@ -68,7 +68,8 @@ static struct http_channel *http_channel_freelist = 0;
 
 struct http_channel_observer_s {
     void *data;
-    void (*destroy)(void *data, struct http_channel *chan);
+    void *data2;
+    http_channel_destroy_t destroy;
     struct http_channel_observer_s *next;
     struct http_channel *chan;
 };
@@ -1227,7 +1228,7 @@ static void http_fire_observers(struct http_channel *c)
     http_channel_observer_t p = c->observers;
     while (p)
     {
-        p->destroy(p->data, c);
+        p->destroy(p->data, c, p->data2);
         p = p->next;
     }
 }
@@ -1248,6 +1249,7 @@ http_channel_observer_t http_add_observer(struct http_channel *c, void *data,
     http_channel_observer_t obs = xmalloc(sizeof(*obs));
     obs->chan = c;
     obs->data = data;
+    obs->data2 = 0;
     obs->destroy= des;
     obs->next = c->observers;
     c->observers = obs;
@@ -1271,6 +1273,12 @@ struct http_channel *http_channel_observer_chan(http_channel_observer_t obs)
     return obs->chan;
 }
 
+void http_observer_set_data2(http_channel_observer_t obs, void *data2)
+{
+    obs->data2 = data2;
+}
+
+
 /*
  * Local variables:
  * c-basic-offset: 4
index ba8f163..ffb1ca9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: http.h,v 1.11 2007-09-26 08:53:53 adam Exp $
+/* $Id: http.h,v 1.12 2007-10-02 12:11:14 adam Exp $
    Copyright (c) 2006-2007, Index Data.
 
 This file is part of Pazpar2.
@@ -114,10 +114,12 @@ struct http_response *http_create_response(struct http_channel *c);
 void http_send_response(struct http_channel *c);
 void urlencode(const char *i, char *o);
 
-typedef void (*http_channel_destroy_t)(void *data, struct http_channel *c);
+typedef void (*http_channel_destroy_t)(void *data, struct http_channel *c,
+                                       void *data2);
 
 http_channel_observer_t http_add_observer(struct http_channel *c, void *data,
                                           http_channel_destroy_t);
+void http_observer_set_data2(http_channel_observer_t obs, void *data2);
 
 void http_remove_observer(http_channel_observer_t obs);
 struct http_channel *http_channel_observer_chan(http_channel_observer_t obs);
index 447eb06..7be4e07 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: http_command.c,v 1.63 2007-10-02 10:11:56 adam Exp $
+/* $Id: http_command.c,v 1.64 2007-10-02 12:11:14 adam Exp $
    Copyright (c) 2006-2007, Index Data.
 
 This file is part of Pazpar2.
@@ -20,7 +20,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  */
 
 /*
- * $Id: http_command.c,v 1.63 2007-10-02 10:11:56 adam Exp $
+ * $Id: http_command.c,v 1.64 2007-10-02 12:11:14 adam Exp $
  */
 
 #include <stdio.h>
@@ -513,10 +513,10 @@ static void show_raw_record_ok(void *data, const char *buf, size_t sz)
     http_send_response(c);
 }
 
-void show_raw_reset(void *data, struct http_channel *c)
+void show_raw_reset(void *data, struct http_channel *c, void *data2)
 {
     struct client *client = data;
-    client_show_raw_reset(client);
+    client_show_raw_remove(client, data2);
 }
 
 static void cmd_record_ready(void *data);
@@ -566,22 +566,18 @@ static void cmd_record(struct http_channel *c)
         }
         else
         {
+            void *data2;
             http_channel_observer_t obs =
                 http_add_observer(c, r->client, show_raw_reset);
             int ret = 
                 client_show_raw_begin(r->client, r->position, syntax, esn, 
                                       obs /* data */,
                                       show_raw_record_error,
-                                      show_raw_record_ok);
+                                      show_raw_record_ok,
+                                      &data2);
             if (ret == -1)
             {
                 http_remove_observer(obs);
-                error(rs, PAZPAR2_RECORD_FAIL, "show already active");
-                return;
-            }
-            else if (ret == -2)
-            {
-                http_remove_observer(obs);
                 error(rs, PAZPAR2_NO_SESSION, 0);
                 return;
             }
index 2316945..625adc0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: logic.c,v 1.68 2007-10-02 10:08:39 adam Exp $
+/* $Id: logic.c,v 1.69 2007-10-02 12:11:14 adam Exp $
    Copyright (c) 2006-2007, Index Data.
 
    This file is part of Pazpar2.
@@ -525,7 +525,8 @@ static int prepare_session_database(struct session *se,
 }
 
 // called if watch should be removed because http_channel is to be destroyed
-static void session_watch_cancel(void *data, struct http_channel *c)
+static void session_watch_cancel(void *data, struct http_channel *c,
+                                 void *data2)
 {
     struct session_watchentry *ent = data;