[xiph-commits] r7927 - icecast/branches/kh/icecast/src

karl at motherfish-iii.xiph.org karl at motherfish-iii.xiph.org
Thu Oct 7 11:49:04 PDT 2004


Author: karl
Date: 2004-10-07 11:49:04 -0700 (Thu, 07 Oct 2004)
New Revision: 7927

Modified:
   icecast/branches/kh/icecast/src/format_ogg.c
   icecast/branches/kh/icecast/src/slave.c
   icecast/branches/kh/icecast/src/source.c
   icecast/branches/kh/icecast/src/stats.c
   icecast/branches/kh/icecast/src/stats.h
Log:
update stats engine. The _inc/_dec routines never worked correctly in all
cases as they can race against each other, not taking account of unprocessed
events.  Here we push the actual calculation to the stats thread.  The rest
is for interacting with the changes


Modified: icecast/branches/kh/icecast/src/format_ogg.c
===================================================================
--- icecast/branches/kh/icecast/src/format_ogg.c	2004-10-07 15:58:14 UTC (rev 7926)
+++ icecast/branches/kh/icecast/src/format_ogg.c	2004-10-07 18:49:04 UTC (rev 7927)
@@ -137,10 +137,6 @@
 {
     vorbis_codec_t *vorbis = codec->specific;
 
-    stats_event (codec->feed->mount, "audio-samplerate", NULL);
-    stats_event (codec->feed->mount, "audio-channels", NULL);
-    stats_event (codec->feed->mount, "audio-bitrate", NULL);
-
     codec->feed->artist = NULL;
     codec->feed->title = NULL;
     vorbis_info_clear (&vorbis->vi);
@@ -373,10 +369,6 @@
 {
     theora_codec_t *theora = codec->specific;
 
-    stats_event (codec->feed->mount, "video_bitrate", NULL);
-    stats_event (codec->feed->mount, "frame_size", NULL);
-    stats_event (codec->feed->mount, "framerate", NULL);
-
     theora_info_clear (&theora->ti);
     theora_comment_clear (&theora->tc);
     ogg_stream_clear (&codec->os);

Modified: icecast/branches/kh/icecast/src/slave.c
===================================================================
--- icecast/branches/kh/icecast/src/slave.c	2004-10-07 15:58:14 UTC (rev 7926)
+++ icecast/branches/kh/icecast/src/slave.c	2004-10-07 18:49:04 UTC (rev 7927)
@@ -294,7 +294,6 @@
 
         if (relay->on_demand == 0)
         {
-            stats_event (relay->localmount, "listeners", NULL);
             source_recheck_mounts();
         }
         /* initiate an immediate relay cleanup run */
@@ -338,16 +337,15 @@
         if (relay->source)
         {
             DEBUG1("Adding relay source at mountpoint \"%s\"", relay->localmount);
+            relay->source->on_demand = relay->on_demand;
             if (relay->on_demand)
             {
                 ice_config_t *config = config_get_config ();
                 source_update_settings (config, relay->source);
                 config_release_config ();
-                stats_event (relay->localmount, NULL, NULL);
                 stats_event (relay->localmount, "listeners", "0");
                 DEBUG0 ("setting on_demand");
             }
-            relay->source->on_demand = relay->on_demand;
             /* on-demand relays can be used as fallback mounts so allow
              * for dependant mountpoints to show up on xsl pages*/
             source_recheck_mounts ();
@@ -388,11 +386,19 @@
     /* the relay thread may of close down */
     if (relay->cleanup && relay->thread)
     {
+        ice_config_t *config;
         DEBUG1 ("waiting for relay thread for \"%s\"", relay->localmount);
         thread_join (relay->thread);
         relay->thread = NULL;
         relay->cleanup = 0;
         relay->running = 0;
+        relay->source->on_demand = relay->on_demand;
+
+        config = config_get_config ();
+        source_update_settings (config, relay->source);
+        config_release_config ();
+        stats_event (relay->localmount, "listeners", "0");
+        source_recheck_mounts ();
     }
 }
 

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2004-10-07 15:58:14 UTC (rev 7926)
+++ icecast/branches/kh/icecast/src/source.c	2004-10-07 18:49:04 UTC (rev 7927)
@@ -282,6 +282,7 @@
     avl_delete (global.source_tree, source, NULL);
     avl_tree_unlock (global.source_tree);
 
+    stats_event (source->mount, NULL, NULL);
     free(source->fallback_mount);
     source->fallback_mount = NULL;
 
@@ -1043,8 +1044,6 @@
 
 static void source_shutdown (source_t *source)
 {
-    char *str;
-
     INFO1("Source \"%s\" exiting", source->mount);
     source->running = 0;
 
@@ -1077,27 +1076,12 @@
     /* delete this sources stats */
     stats_event_dec (NULL, "sources");
 
-    str = httpp_getvar(source->parser, "ice-audio-info");
-    if (str)
-    {
-        _parse_audio_info (source, str);
-        stats_event (source->mount, "audio_info", NULL);
-    }
-
     /* we don't remove the source from the tree here, it may be a relay and
        therefore reserved */
     source_clear_source (source);
 
-    /* remove main source stats */
-    stats_event (source->mount, "public", NULL);
-    stats_event (source->mount, "server_description", NULL);
-    stats_event (source->mount, "server_name", NULL);
-    stats_event (source->mount, "genre", NULL);
-    stats_event (source->mount, "type", NULL);
-    stats_event (source->mount, "artist", NULL);
-    stats_event (source->mount, "title", NULL);
-    stats_event (source->mount, "ice-bitrate", NULL);
-    stats_event (source->mount, "max_listeners", NULL);
+    /* remove source stats */
+    stats_event (source->mount, NULL, NULL);
 
     thread_mutex_unlock (&source->lock);
 
@@ -1174,8 +1158,6 @@
                     util_dict_set (source->audio_info, name, esc);
                     stats_event (source->mount, name, value);
                 }
-                else
-                    stats_event (source->mount, name, NULL);
                 free (esc);
             }
         }
@@ -1275,11 +1257,11 @@
         DEBUG0 ("on-demand set");
     if (source->hidden)
     {
-        stats_event (source->mount, NULL, "hidden");
+        stats_event_hidden (source->mount, NULL, 1);
         DEBUG0 ("hidden from xsl");
     }
     else
-        stats_event (source->mount, NULL, NULL);
+        stats_event_hidden (source->mount, NULL, 0);
 
     if (source->max_listeners == -1)
         stats_event (source->mount, "max_listeners", "unlimited");
@@ -1289,6 +1271,11 @@
         snprintf (buf, sizeof (buf), "%lu", source->max_listeners);
         stats_event (source->mount, "max_listeners", buf);
     }
+    if (source->on_demand)
+        stats_event (source->mount, "on-demand", "1");
+    else
+        stats_event (source->mount, "on-demand", NULL);
+
     DEBUG1 ("max listeners to %d", source->max_listeners);
     DEBUG1 ("queue size to %u", source->queue_size_limit);
     DEBUG1 ("burst size to %u", source->burst_size);
@@ -1341,7 +1328,6 @@
         stats_event_inc(NULL, "source_client_connections");
         stats_event (source->mount, "listeners", "0");
         source_main (source);
-        stats_event (source->mount, "listeners", NULL);
         source_recheck_mounts();
     }
     source_free_source (source);
@@ -1396,11 +1382,10 @@
     while (mount)
     {
         int update_stats = 0;
-        const char *hidden = NULL;
+        int hidden;
         source_t *source = source_find_mount (mount->mountname);
 
-        if (mount->hidden)
-           hidden = "hidden";
+        hidden = mount->hidden;
         if (source)
         {
             /* something is active, maybe a fallback */
@@ -1415,11 +1400,21 @@
                 update_stats = 1;
         }
         else
-            stats_event (mount->mountname, "listeners", NULL);
+            stats_event (mount->mountname, NULL, NULL);
         if (update_stats)
         {
-            stats_event (mount->mountname, NULL, hidden);
-            stats_event (mount->mountname, "listeners", "0");
+            source = source_find_mount_raw (mount->mountname);
+            if (source)
+                source_update_settings (config, source);
+            else
+            {
+                stats_event_hidden (mount->mountname, NULL, hidden);
+                stats_event (mount->mountname, "listeners", "0");
+                if (mount->max_listeners < 0)
+                    stats_event (mount->mountname, "max_listeners", "unlimited");
+                else
+                    stats_event_args (mount->mountname, "max_listeners", "%d", mount->max_listeners);
+            }
         }
 
         mount = mount->next;

Modified: icecast/branches/kh/icecast/src/stats.c
===================================================================
--- icecast/branches/kh/icecast/src/stats.c	2004-10-07 15:58:14 UTC (rev 7926)
+++ icecast/branches/kh/icecast/src/stats.c	2004-10-07 18:49:04 UTC (rev 7927)
@@ -42,6 +42,13 @@
 #define vsnprintf _vsnprintf
 #endif
 
+#define STATS_EVENT_SET     0
+#define STATS_EVENT_INC     1
+#define STATS_EVENT_DEC     2
+#define STATS_EVENT_ADD     3
+#define STATS_EVENT_REMOVE  4
+#define STATS_EVENT_HIDDEN  5
+
 typedef struct _event_listener_tag
 {
     stats_event_t **queue;
@@ -50,22 +57,19 @@
     struct _event_listener_tag *next;
 } event_listener_t;
 
-int _stats_running = 0;
-thread_type *_stats_thread_id;
-int _stats_threads = 0;
+static volatile int _stats_running = 0;
+static thread_type *_stats_thread_id;
+static volatile int _stats_threads = 0;
 
-stats_t _stats;
-mutex_t _stats_mutex;
+static stats_t _stats;
+static mutex_t _stats_mutex;
 
-stats_event_t *_global_event_queue;
+static volatile stats_event_t *_global_event_queue;
 mutex_t _global_event_mutex;
 
-cond_t _event_signal_cond;
+static volatile event_listener_t *_event_listeners;
 
-event_listener_t *_event_listeners;
 
-
-
 static void *_stats_thread(void *arg);
 static int _compare_stats(void *a, void *b, void *arg);
 static int _compare_source_stats(void *a, void *b, void *arg);
@@ -76,6 +80,46 @@
 static stats_source_t *_find_source(avl_tree *tree, char *source);
 static void _free_event(stats_event_t *event);
 
+
+/* simple helper function for creating an event */
+static stats_event_t *build_event (const char *source, const char *name, const char *value)
+{
+    stats_event_t *event;
+
+    event = (stats_event_t *)calloc(1, sizeof(stats_event_t));
+    if (event)
+    {
+        if (source)
+            event->source = (char *)strdup(source);
+        if (name)
+            event->name = (char *)strdup(name);
+        if (value)
+            event->value = (char *)strdup(value);
+        else
+            event->action = STATS_EVENT_REMOVE;
+    }
+    return event;
+}
+
+static void queue_global_event (stats_event_t *event)
+{
+    thread_mutex_lock(&_global_event_mutex);
+    if (_global_event_queue == NULL)
+    {
+        _global_event_queue = event;
+    }
+    else
+    {
+        stats_event_t *node = (stats_event_t *)_global_event_queue;
+        while (node->next)
+            node = node->next;
+        node->next = event;
+    }
+    // DEBUG3("event added (%s, %s, %s)", event->source,
+        // event->name, event->value);
+    thread_mutex_unlock(&_global_event_mutex);
+}
+
 void stats_initialize()
 {
     _event_listeners = NULL;
@@ -87,9 +131,6 @@
     /* set up global mutex */
     thread_mutex_create("stats", &_stats_mutex);
 
-    /* set up event signaler */
-    thread_cond_create(&_event_signal_cond);
-
     /* set up stats queues */
     _global_event_queue = NULL;
     thread_mutex_create("stats_global_event", &_global_event_mutex);
@@ -118,19 +159,18 @@
         n = _stats_threads;
         thread_mutex_unlock(&_stats_mutex);
     } while (n > 0);
+    INFO0("stats thread finished");
 
     /* free the queues */
 
     /* destroy the queue mutexes */
     thread_mutex_destroy(&_global_event_mutex);
 
-    /* tear it all down */
-    thread_cond_destroy(&_event_signal_cond);
     thread_mutex_destroy(&_stats_mutex);
     avl_tree_free(_stats.source_tree, _free_source_stats);
     avl_tree_free(_stats.global_tree, _free_stats);
 
-    event = _global_event_queue;
+    event = (stats_event_t *)_global_event_queue;
     while(event) {
         if(event->source)
             free(event->source);
@@ -157,43 +197,51 @@
     return NULL;
 }
 
+/* simple name=tag stat create/update */
 void stats_event(const char *source, const char *name, const char *value)
 {
-    stats_event_t *node;
     stats_event_t *event;
 
-    /* build event */
-    event = (stats_event_t *)malloc(sizeof(stats_event_t));
-    event->source = NULL;
-    event->name = NULL;
-    if (source != NULL) event->source = (char *)strdup(source);
-    if (name) event->name = (char *)strdup(name);
-    event->value = NULL;
-    event->next = NULL;
-    if (value != NULL) event->value = (char *)strdup(value);
+    event = build_event (source, name, value);
+    if (event)
+        queue_global_event (event);
+}
 
-    /* queue event */
-    thread_mutex_lock(&_global_event_mutex);
-    if (_global_event_queue == NULL) {
-        _global_event_queue = event;
-    } else {
-        node = _global_event_queue;
-        while (node->next) node = node->next;
-        node->next = event;
+/* make stat hidden (non-zero). name can be NULL if it applies to a whole
+ * source stats tree. */
+void stats_event_hidden (const char *source, const char *name, int hidden)
+{
+    stats_event_t *event;
+    const char *str = NULL;
+
+    if (hidden)
+        str = "";
+    event = build_event (source, name, str);
+    if (event)
+    {
+        event->action = STATS_EVENT_HIDDEN;
+        queue_global_event (event);
     }
-    thread_mutex_unlock(&_global_event_mutex);
 }
 
+/* printf style formatting for stat create/update */
 void stats_event_args(const char *source, char *name, char *format, ...)
 {
     char buf[1024];
     va_list val;
-    
+    int ret;
+
+    if (name == NULL)
+        return;
     va_start(val, format);
-    vsnprintf(buf, 1024, format, val);
+    ret = vsnprintf(buf, 1024, format, val);
     va_end(val);
 
-    stats_event(source, name, buf);
+    if (ret < 0 || (unsigned int)ret >= sizeof (buf))
+        WARN2 ("problem with formatting %s stat %s",
+                source==NULL ? "global" : source, name);
+    else
+        stats_event(source, name, buf);
 }
 
 static char *_get_stats(char *source, char *name)
@@ -224,56 +272,42 @@
 {
     return(_get_stats(source, name));
 }
-void stats_event_inc(char *source, char *name)
+
+/* increase the value in the provided stat by 1 */
+void stats_event_inc(const char *source, const char *name)
 {
-    char *old_value;
-    int new_value;
-    
-    old_value = _get_stats(source, name);
-    if (old_value != NULL) {
-        new_value = atoi(old_value);
-        free(old_value);
-        new_value++;
-    } else {
-        new_value = 1;
+    stats_event_t *event = build_event (source, name, NULL);
+    /* DEBUG2("%s on %s", name, source==NULL?"global":source); */
+    if (event)
+    {
+        event->action = STATS_EVENT_INC;
+        queue_global_event (event);
     }
-
-    stats_event_args(source, name, "%d", new_value);
 }
 
-void stats_event_add(char *source, char *name, unsigned long value)
+void stats_event_add(const char *source, const char *name, unsigned long value)
 {
-    char *old_value;
-    unsigned long new_value;
-
-    old_value = _get_stats(source, name);
-    if (old_value != NULL) {
-        new_value = atol(old_value);
-        free(old_value);
-        new_value += value;
-    } else {
-        new_value = value;
+    stats_event_t *event = build_event (source, name, NULL);
+    /* DEBUG2("%s on %s", name, source==NULL?"global":source); */
+    if (event)
+    {
+        event->value = malloc (16);
+        snprintf (event->value, 16, "%ld", value);
+        event->action = STATS_EVENT_ADD;
+        queue_global_event (event);
     }
-
-    stats_event_args(source, name, "%ld", new_value);
 }
 
-void stats_event_dec(char *source, char *name)
+/* decrease the value in the provided stat by 1 */
+void stats_event_dec(const char *source, const char *name)
 {
-    char *old_value;
-    int new_value;
-
-    old_value = _get_stats(source, name);
-    if (old_value != NULL) {
-        new_value = atoi(old_value);
-        free(old_value);
-        new_value--;
-        if (new_value < 0) new_value = 0;
-    } else {
-        new_value = 0;
+    /* DEBUG2("%s on %s", name, source==NULL?"global":source); */
+    stats_event_t *event = build_event (source, name, NULL);
+    if (event)
+    {
+        event->action = STATS_EVENT_DEC;
+        queue_global_event (event);
     }
-
-    stats_event_args(source, name, "%d", new_value);
 }
 
 /* note: you must call this function only when you have exclusive access
@@ -348,139 +382,193 @@
     return copy;
 }
 
-static void  _mark_hidden (stats_source_t *snode, int hidden)
+
+/* helper to apply specialised changes to a stats node */
+static void modify_node_event (stats_node_t *node, stats_event_t *event)
 {
-    avl_node *node = avl_get_first (snode->stats_tree);
+    char *str;
+    if (event->action == STATS_EVENT_HIDDEN)
+    {
+        if (event->value)
+            node->hidden = 1;
+        else
+            node->hidden = 0;
+        return;
+    }
+    if (event->action != STATS_EVENT_SET)
+    {
+        int value = 0;
 
-    snode->hidden = hidden;
-    while (node)
+        switch (event->action)
+        {
+            case STATS_EVENT_INC:
+                value = atoi (node->value)+1;
+                break;
+            case STATS_EVENT_DEC:
+                value = atoi (node->value)-1;
+                break;
+            case STATS_EVENT_ADD:
+                value = atoi (node->value)+atoi (event->value);
+                break;
+            default:
+                break;
+        }
+        str = malloc (16);
+        snprintf (str, 16, "%d", value);
+    }
+    else
+        str = (char *)strdup (event->value);
+    free (node->value);
+    node->value = str;
+    // DEBUG3 ("update node %s \"%s\" (%d)", node->name, node->value, event->action);
+}
+
+
+static void process_global_event (stats_event_t *event)
+{
+    stats_node_t *node;
+
+    /* DEBUG3("global event %s %s %d", event->name, event->value, event->action); */
+    if (event->action == STATS_EVENT_REMOVE)
     {
-        stats_node_t *stats = (stats_node_t*)node->key;
-        stats->hidden = hidden;
-        node = avl_get_next (node);
+        /* we're deleting */
+        node = _find_node(_stats.global_tree, event->name);
+        if (node != NULL)
+            avl_delete(_stats.global_tree, (void *)node, _free_stats);
+        return;
     }
+    node = _find_node(_stats.global_tree, event->name);
+    if (node)
+    {
+        modify_node_event (node, event);
+    }
+    else
+    {
+        /* add node */
+        node = (stats_node_t *)calloc(1, sizeof(stats_node_t));
+        node->name = (char *)strdup(event->name);
+        node->value = (char *)strdup(event->value);
+
+        avl_insert(_stats.global_tree, (void *)node);
+    }
 }
 
+
+static void process_source_event (stats_event_t *event)
+{
+    stats_source_t *snode = _find_source(_stats.source_tree, event->source);
+    if (snode == NULL)
+    {
+        if (event->action == STATS_EVENT_REMOVE)
+            return;
+        snode = (stats_source_t *)calloc(1,sizeof(stats_source_t));
+        if (snode == NULL)
+            return;
+        DEBUG1 ("new source stat %s", event->source);
+        snode->source = (char *)strdup(event->source);
+        snode->stats_tree = avl_tree_new(_compare_stats, NULL);
+        if (event->action == STATS_EVENT_HIDDEN)
+            snode->hidden = 1;
+        else
+            snode->hidden = 0;
+
+        avl_insert(_stats.source_tree, (void *)snode);
+    }
+    if (event->name)
+    {
+        stats_node_t *node = _find_node(snode->stats_tree, event->name);
+        if (node == NULL)
+        {
+            if (event->action == STATS_EVENT_REMOVE)
+                return;
+            /* adding node */
+            if (event->value)
+            {
+                DEBUG2 ("new node %s (%s)", event->name, event->value);
+                node = (stats_node_t *)calloc(1,sizeof(stats_node_t));
+                node->name = (char *)strdup(event->name);
+                node->value = (char *)strdup(event->value);
+                node->hidden = snode->hidden;
+
+                avl_insert(snode->stats_tree, (void *)node);
+            }
+            return;
+        }
+        if (event->action == STATS_EVENT_REMOVE)
+        {
+            DEBUG1 ("delete node %s", event->name);
+            avl_delete(snode->stats_tree, (void *)node, _free_stats);
+            return;
+        }
+        modify_node_event (node, event);
+        return;
+    }
+    if (event->action == STATS_EVENT_HIDDEN)
+    {
+        avl_node *node = avl_get_first (snode->stats_tree);
+
+        if (event->value)
+            snode->hidden = 1;
+        else
+            snode->hidden = 0;
+        while (node)
+        {
+            stats_node_t *stats = (stats_node_t*)node->key;
+            stats->hidden = snode->hidden;
+            node = avl_get_next (node);
+        }
+        return;
+    }
+    if (event->action == STATS_EVENT_REMOVE)
+    {
+        DEBUG1 ("delete source node %s", event->source);
+        avl_delete(_stats.source_tree, (void *)snode, _free_source_stats);
+    }
+}
+
+
 static void *_stats_thread(void *arg)
 {
     stats_event_t *event;
     stats_event_t *copy;
-    stats_node_t *node;
-    stats_node_t *anode;
-    stats_source_t *snode;
-    stats_source_t *asnode;
     event_listener_t *listener;
-    avl_node *avlnode;
 
+    /* global currently active stats */
+    stats_event (NULL, "clients", "0");
+    stats_event (NULL, "connections", "0");
+    stats_event (NULL, "sources", "0");
+    stats_event (NULL, "stats", "0");
+
+    /* global accumulating stats */
+    stats_event (NULL, "client_connections", "0");
+    stats_event (NULL, "source_client_connections", "0");
+    stats_event (NULL, "source_relay_connections", "0");
+    stats_event (NULL, "source_total_connections", "0");
+    stats_event (NULL, "stats_connections", "0");
+
+    INFO0 ("stats thread started");
     while (_stats_running) {
-        thread_mutex_lock(&_global_event_mutex);
         if (_global_event_queue != NULL) {
             /* grab the next event from the queue */
-            event = _global_event_queue;
+            thread_mutex_lock(&_global_event_mutex);
+            event = (stats_event_t *)_global_event_queue;
             _global_event_queue = event->next;
+            thread_mutex_unlock(&_global_event_mutex);
+
             event->next = NULL;
             thread_mutex_unlock(&_global_event_mutex);
 
             thread_mutex_lock(&_stats_mutex);
-            if (event->source == NULL) {
-                /* we have a global event */
-                if (event->value != NULL) {
-                    /* adding/updating */
-                    node = _find_node(_stats.global_tree, event->name);
-                    if (node == NULL) {
-                        /* add node */
-                        anode = (stats_node_t *)malloc(sizeof(stats_node_t));
-                        anode->name = (char *)strdup(event->name);
-                        anode->value = (char *)strdup(event->value);
-                        anode->hidden = 0;
 
-                        avl_insert(_stats.global_tree, (void *)anode);
-                    } else {
-                        /* update node */
-                        free(node->value);
-                        node->value = (char *)strdup(event->value);
-                    }
-
-                } else {
-                    /* we're deleting */
-                    node = _find_node(_stats.global_tree, event->name);
-                    if (node != NULL)
-                        avl_delete(_stats.global_tree, (void *)node, _free_stats);
-                }
-            } else {
-                /* we have a source event */
-
-                snode = _find_source(_stats.source_tree, event->source);
-                if (snode != NULL) {
-                    /* this is a source we already have a tree for */
-                    if (event->name) {
-                        /* we're add/updating */
-                        node = _find_node(snode->stats_tree, event->name);
-                        if (node == NULL) {
-                            /* adding node */
-                            if (event->value)
-                            {
-                                DEBUG1 ("new node %s", event->name);
-                                anode = (stats_node_t *)malloc(sizeof(stats_node_t));
-                                anode->name = (char *)strdup(event->name);
-                                anode->value = (char *)strdup(event->value);
-                                anode->hidden = snode->hidden;
-
-                                avl_insert(snode->stats_tree, (void *)anode);
-                            }
-                        } else {
-                            if (event->value) {
-                                /* updating node */
-                                DEBUG1 ("update node %s", event->name);
-                                free(node->value);
-                                node->value = (char *)strdup(event->value);
-                            } else {
-                                /* we're deleting */
-                                node = _find_node(snode->stats_tree, event->name);
-                                if (node != NULL) {
-                                    DEBUG1 ("delete node %s", event->name);
-                                    avl_delete(snode->stats_tree, (void *)node, _free_stats);
-                                }
-                                avlnode = avl_get_first(snode->stats_tree);
-                                if (avlnode == NULL) {
-                                    DEBUG1 ("delete source node %s", event->source);
-                                    avl_delete(_stats.source_tree, (void *)snode, _free_source_stats);
-                                }
-                            }
-                        }
-                    }
-                    else
-                    {
-                        if (event->value)
-                            _mark_hidden (snode, 1);
-                        else
-                            _mark_hidden (snode, 0);
-                    }
-                } else {
-                    /* this is a new source */
-                    if (event->name)
-                    {
-                        DEBUG1 ("new source node %s needed before settings", event->source);
-                    }
-                    else
-                    {
-                        DEBUG1 ("new source stat %s", event->source);
-                        asnode = (stats_source_t *)malloc(sizeof(stats_source_t));
-                        asnode->source = (char *)strdup(event->source);
-                        asnode->stats_tree = avl_tree_new(_compare_stats, NULL);
-                        if (event->value)
-                            asnode->hidden = 1;
-                        else
-                            asnode->hidden = 0;
-
-                        avl_insert(_stats.source_tree, (void *)asnode);
-                    }
-                }
-            }
+            /* check if we are dealing with a global or source event */
+            if (event->source == NULL)
+                process_global_event (event);
+            else
+                process_source_event (event);
             
             /* now we have an event that's been processed into the running stats */
             /* this event should get copied to event listeners' queues */
-            listener = _event_listeners;
+            listener = (event_listener_t *)_event_listeners;
             while (listener) {
                 copy = _copy_event(event);
                 thread_mutex_lock(listener->mutex);
@@ -489,23 +577,17 @@
 
                 listener = listener->next;
             }
-            thread_cond_broadcast(&_event_signal_cond);
 
             /* now we need to destroy the event */
             _free_event(event);
 
             thread_mutex_unlock(&_stats_mutex);
             continue;
-        } else {
-            thread_mutex_unlock(&_global_event_mutex);
         }
 
         thread_sleep(300000);
     }
 
-    /* wake the other threads so they can shut down cleanly */
-    thread_cond_broadcast(&_event_signal_cond);
-
     return NULL;
 }
 
@@ -522,7 +604,7 @@
     if (_event_listeners == NULL) {
         _event_listeners = evli;
     } else {
-        node = _event_listeners;
+        node = (event_listener_t *)_event_listeners;
         while (node->next) node = node->next;
         node->next = evli;
     }
@@ -539,6 +621,7 @@
     event->name = (char *)strdup(node->name);
     event->value = (char *)strdup(node->value);
     event->hidden = node->hidden;
+    event->action = STATS_EVENT_SET;
     event->next = NULL;
 
     return event;

Modified: icecast/branches/kh/icecast/src/stats.h
===================================================================
--- icecast/branches/kh/icecast/src/stats.h	2004-10-07 15:58:14 UTC (rev 7926)
+++ icecast/branches/kh/icecast/src/stats.h	2004-10-07 18:49:04 UTC (rev 7927)
@@ -40,6 +40,7 @@
     char *name;
     char *value;
     int  hidden;
+    int  action;
 
     struct _stats_event_tag *next;
 } stats_event_t;
@@ -82,9 +83,10 @@
 
 void stats_event(const char *source, const char *name, const char *value);
 void stats_event_args(const char *source, char *name, char *format, ...);
-void stats_event_inc(char *source, char *name);
-void stats_event_add(char *source, char *name, unsigned long value);
-void stats_event_dec(char *source, char *name);
+void stats_event_inc(const char *source, const char *name);
+void stats_event_add(const char *source, const char *name, unsigned long value);
+void stats_event_dec(const char *source, const char *name);
+void stats_event_hidden (const char *source, const char *name, int hidden);
 
 void *stats_connection(void *arg);
 void *stats_callback(void *arg);



More information about the commits mailing list