Indented.
authorDennis Schafroth <dennis@indexdata.com>
Tue, 27 Apr 2010 14:19:11 +0000 (16:19 +0200)
committerDennis Schafroth <dennis@indexdata.com>
Tue, 27 Apr 2010 14:19:11 +0000 (16:19 +0200)
Fixed: Keeping the start of the channel list as invariant through the event loop, so we dont look at newly added IOCHANnels. This could be the cause of the messed-up http show call.

Started on the refactoring of moving to yaz_poll, but holding back to see if this fix works.

src/eventl.c

index 990dbfe..6b8f52f 100644 (file)
@@ -1,21 +1,21 @@
 /* This file is part of Pazpar2.
-   Copyright (C) 2006-2010 Index Data
+ Copyright (C) 2006-2010 Index Data
 
-Pazpar2 is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
+ Pazpar2 is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
 
-Pazpar2 is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
+ Pazpar2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-*/
+ */
 
 /*
  * Based on  ParaZ - a simple tool for harvesting performance data for
@@ -54,6 +54,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include <yaz/comstack.h>
 #include <yaz/xmalloc.h>
 #include <yaz/mutex.h>
+#include <yaz/poll.h>
 #include "eventl.h"
 #include "sel_thread.h"
 
@@ -68,12 +69,11 @@ struct iochan_man_s {
 
 struct iochan_man_iter {
     iochan_man_t man;
-    IOCHAN current; 
+    IOCHAN current;
     int first;
 };
 
-iochan_man_t iochan_man_create(int no_threads)
-{
+iochan_man_t iochan_man_create(int no_threads) {
     iochan_man_t man = xmalloc(sizeof(*man));
     man->channel_list = 0;
     man->sel_thread = 0; /* can't create sel_thread yet because we may fork */
@@ -85,17 +85,14 @@ iochan_man_t iochan_man_create(int no_threads)
     return man;
 }
 
-void iochan_man_destroy(iochan_man_t *mp)
-{
-    if (*mp)
-    {
+void iochan_man_destroy(iochan_man_t *mp) {
+    if (*mp) {
         IOCHAN c;
         if ((*mp)->sel_thread)
             sel_thread_destroy((*mp)->sel_thread);
-        
+
         c = (*mp)->channel_list;
-        while (c)
-        {
+        while (c) {
             IOCHAN c_next = c->next;
             xfree(c->name);
             xfree(c);
@@ -106,23 +103,21 @@ void iochan_man_destroy(iochan_man_t *mp)
     }
 }
 
-void iochan_add(iochan_man_t man, IOCHAN chan)
-{
+void iochan_add(iochan_man_t man, IOCHAN chan) {
     chan->man = man;
     yaz_mutex_enter(man->iochan_mutex);
-    yaz_log(man->log_level, "iochan_add : chan=%p channel list=%p", chan, man->channel_list);
+    yaz_log(man->log_level, "iochan_add : chan=%p channel list=%p", chan,
+            man->channel_list);
     chan->next = man->channel_list;
     man->channel_list = chan;
     yaz_mutex_leave(man->iochan_mutex);
 }
 
-IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags,
-                     const char *name)
-{
+IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags, const char *name) {
     IOCHAN new_iochan;
 
-    if (!(new_iochan = (IOCHAN)xmalloc(sizeof(*new_iochan))))
-       return 0;
+    if (!(new_iochan = (IOCHAN) xmalloc(sizeof(*new_iochan))))
+        return 0;
     new_iochan->destroyed = 0;
     new_iochan->fd = fd;
     new_iochan->flags = flags;
@@ -135,13 +130,12 @@ IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags,
     return new_iochan;
 }
 
-static void work_handler(void *work_data)
-{
+static void work_handler(void *work_data) {
     IOCHAN p = work_data;
 
     yaz_log(p->man->log_level, "eventl: work begin chan=%p name=%s event=%d",
             p, p->name ? p->name : "", p->this_event);
-    
+
     if (!p->destroyed && (p->this_event & EVENT_TIMEOUT))
         (*p->fun)(p, EVENT_TIMEOUT);
     if (!p->destroyed && (p->this_event & EVENT_INPUT))
@@ -151,27 +145,25 @@ static void work_handler(void *work_data)
     if (!p->destroyed && (p->this_event & EVENT_EXCEPT))
         (*p->fun)(p, EVENT_EXCEPT);
 
-    yaz_log(p->man->log_level, "eventl: work end chan=%p name=%s event=%d",
-            p, p->name ? p->name : "", p->this_event);
+    yaz_log(p->man->log_level, "eventl: work end chan=%p name=%s event=%d", p,
+            p->name ? p->name : "", p->this_event);
 }
 
-static void run_fun(iochan_man_t man, IOCHAN p)
-{
-    if (p->this_event)
-    {
-        if (man->sel_thread)
-        {
-            yaz_log(man->log_level, "eventl: work add chan=%p name=%s event=%d",
-                    p, p->name ? p->name : "", p->this_event);
+static void run_fun(iochan_man_t man, IOCHAN p) {
+    if (p->this_event) {
+        if (man->sel_thread) {
+            yaz_log(man->log_level,
+                    "eventl: work add chan=%p name=%s event=%d", p,
+                    p->name ? p->name : "", p->this_event);
             p->thread_users++;
             sel_thread_add(man->sel_thread, p);
-        }
-        else
+        } else
             work_handler(p);
     }
 }
 
-static IOCHAN iochan_man_get_first(struct iochan_man_iter *iter, iochan_man_t man) {
+static IOCHAN iochan_man_get_first(struct iochan_man_iter *iter,
+        iochan_man_t man) {
     iter->man = man;
     iter->first = 1;
     yaz_mutex_enter(man->iochan_mutex);
@@ -190,7 +182,8 @@ static IOCHAN iochan_man_get_next(struct iochan_man_iter *iter) {
         next = current->next;
         iter->current = iter->current->next;
         if (iter->first) {
-            yaz_log(iter->man->log_level, "iochan_man_get_next : chan=%p next=%p", current, next);
+            yaz_log(iter->man->log_level,
+                    "iochan_man_get_next : chan=%p next=%p", current, next);
             iter->first = 0;
             yaz_mutex_leave(iter->man->iochan_mutex);
         }
@@ -198,45 +191,55 @@ static IOCHAN iochan_man_get_next(struct iochan_man_iter *iter) {
     return iter->current;
 }
 
-static int event_loop(iochan_man_t man, IOCHAN *iochans)
-{
+static int event_loop(iochan_man_t man, IOCHAN *iochans) {
     do /* loop as long as there are active associations to process */
     {
-       IOCHAN p, *nextp;
-       fd_set in, out, except;
-       int res, max;
+        IOCHAN p, *nextp;
+        IOCHAN start;
+        fd_set in, out, except;
+        int res, max;
         static struct timeval to;
         struct timeval *timeout;
-        static struct iochan_man_iter iter; 
-
-       FD_ZERO(&in);
-       FD_ZERO(&out);
-       FD_ZERO(&except);
-       timeout = &to; /* hang on select */
-       to.tv_sec = 300;
-       to.tv_usec = 0;
-       max = 0;
-       for (p = iochan_man_get_first(&iter, man); p; p = iochan_man_get_next(&iter) )
-       {
+        static struct iochan_man_iter iter;
+
+//        struct yaz_poll_fd *fds;
+        int no_fds = 0;
+        FD_ZERO(&in);
+        FD_ZERO(&out);
+        FD_ZERO(&except);
+        timeout = &to; /* hang on select */
+        to.tv_sec = 300;
+        to.tv_usec = 0;
+
+        // INV: Start must no change through the loop
+
+        start = iochan_man_get_first(&iter, man);
+        IOCHAN inv_start = start;
+        for (p = start; p; p = iochan_man_get_next(&iter)) {
+            no_fds++;
+        }
+//        fds = (struct yaz_poll_fd *) xmalloc(no_fds * sizeof(*fds));
+
+        max = 0;
+        for (p = start; p; p = p->next) {
             if (p->thread_users > 0)
                 continue;
             if (p->max_idle && p->max_idle < to.tv_sec)
                 to.tv_sec = p->max_idle;
             if (p->fd < 0)
                 continue;
-           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 (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;
+        }
         yaz_log(man->log_level, "max=%d nofds=%d", max, man->sel_fd);
-        
-        if (man->sel_fd != -1)
-        {
+
+        if (man->sel_fd != -1) {
             if (man->sel_fd > max)
                 max = man->sel_fd;
             FD_SET(man->sel_fd, &in);
@@ -244,114 +247,100 @@ static int event_loop(iochan_man_t man, IOCHAN *iochans)
         yaz_log(man->log_level, "select begin nofds=%d", max);
         res = select(max + 1, &in, &out, &except, timeout);
         yaz_log(man->log_level, "select returned res=%d", res);
-        if (res < 0)
-       {
-           if (errno == EINTR)
-               continue;
-            else
-            {
-                yaz_log(YLOG_ERRNO|YLOG_WARN, "select");
+        if (res < 0) {
+            if (errno == EINTR)
+                continue;
+            else {
+                yaz_log(YLOG_ERRNO | YLOG_WARN, "select");
                 return 0;
             }
-       }
-        if (man->sel_fd != -1)
-        {
-            if (FD_ISSET(man->sel_fd, &in))
-            {
+        }
+        if (man->sel_fd != -1) {
+            if (FD_ISSET(man->sel_fd, &in)) {
                 IOCHAN chan;
 
                 yaz_log(man->log_level, "eventl: sel input on sel_fd=%d",
                         man->sel_fd);
-                while ((chan = sel_thread_result(man->sel_thread)))
-                {
-                    yaz_log(man->log_level, "eventl: got thread result chan=%p name=%s",
-                            chan, chan->name ? chan->name : "");
+                while ((chan = sel_thread_result(man->sel_thread))) {
+                    yaz_log(man->log_level,
+                            "eventl: got thread result chan=%p name=%s", chan,
+                            chan->name ? chan->name : "");
                     chan->thread_users--;
                 }
             }
         }
-        if (man->log_level)
-        {
+        if (man->log_level) {
             int no = 0;
-            for (p = iochan_man_get_first(&iter, man); p; p = iochan_man_get_next(&iter)) {
+            for (p = iochan_man_get_first(&iter, man); p; p
+                    = iochan_man_get_next(&iter)) {
                 no++;
             }
             yaz_log(man->log_level, "%d channels", no);
         }
-        for (p = iochan_man_get_first(&iter, man); p; p = iochan_man_get_next(&iter))
-        {
+        for (p = start; p; p = p->next) {
             time_t now = time(0);
-            
-            if (p->destroyed)
-            {
-                yaz_log(man->log_level, "eventl: skip destroyed chan=%p name=%s", p, p->name ? p->name : "");
+
+            if (p->destroyed) {
+                yaz_log(man->log_level,
+                        "eventl: skip destroyed chan=%p name=%s", p,
+                        p->name ? p->name : "");
                 continue;
             }
-            if (p->thread_users > 0)
-            {
-                yaz_log(man->log_level, "eventl: skip chan=%p name=%s users=%d", p, p->name ? p->name : "", p->thread_users);
+            if (p->thread_users > 0) {
+                yaz_log(man->log_level,
+                        "eventl: skip chan=%p name=%s users=%d", p,
+                        p->name ? p->name : "", p->thread_users);
                 continue;
             }
             p->this_event = 0;
 
-            if (p->max_idle && now - p->last_event > p->max_idle)
-            {
+            if (p->max_idle && now - p->last_event > p->max_idle) {
                 p->last_event = now;
                 p->this_event |= EVENT_TIMEOUT;
             }
-            if (p->fd >= 0)
-            {
-                if (FD_ISSET(p->fd, &in))
-                {
+            if (p->fd >= 0) {
+                if (FD_ISSET(p->fd, &in)) {
                     p->last_event = now;
                     p->this_event |= EVENT_INPUT;
                 }
-                if (FD_ISSET(p->fd, &out))
-                {
+                if (FD_ISSET(p->fd, &out)) {
                     p->last_event = now;
                     p->this_event |= EVENT_OUTPUT;
                 }
-                if (FD_ISSET(p->fd, &except))
-                {
+                if (FD_ISSET(p->fd, &except)) {
                     p->last_event = now;
                     p->this_event |= EVENT_EXCEPT;
                 }
             }
             run_fun(man, p);
-       }
+        }
+        assert(inv_start == start);
         yaz_mutex_enter(man->iochan_mutex);
-        for (nextp = iochans; *nextp; )
-        {
+        for (nextp = iochans; *nextp;) {
             IOCHAN p = *nextp;
-           if (p->destroyed && p->thread_users == 0)
-           {
+            if (p->destroyed && p->thread_users == 0) {
                 *nextp = p->next;
                 xfree(p->name);
                 xfree(p);
-           }
-            else
+            } else
                 nextp = &p->next;
         }
         yaz_mutex_leave(man->iochan_mutex);
-    }
-    while (*iochans);
+    } while (*iochans);
     return 0;
 }
 
-void iochan_man_events(iochan_man_t man)
-{
-    if (man->no_threads > 0 && !man->sel_thread)
-    {
-        man->sel_thread = sel_thread_create(
-            work_handler, 0 /*work_destroy */, &man->sel_fd, man->no_threads);
+void iochan_man_events(iochan_man_t man) {
+    if (man->no_threads > 0 && !man->sel_thread) {
+        man->sel_thread = sel_thread_create(work_handler, 0 /*work_destroy */,
+                &man->sel_fd, man->no_threads);
         yaz_log(man->log_level, "iochan_man_events. Using %d threads",
                 man->no_threads);
     }
     event_loop(man, &man->channel_list);
 }
 
-void pazpar2_sleep(double d)
-{
+void pazpar2_sleep(double d) {
 #ifdef WIN32
     Sleep( (DWORD) (d * 1000));
 #else