[xiph-commits] r17384 - in icecast/branches/kh/icecast: . src win32

karl at svn.xiph.org karl at svn.xiph.org
Sun Sep 12 14:21:21 PDT 2010


Author: karl
Date: 2010-09-12 14:21:21 -0700 (Sun, 12 Sep 2010)
New Revision: 17384

Modified:
   icecast/branches/kh/icecast/NEWS
   icecast/branches/kh/icecast/config.h.vc6
   icecast/branches/kh/icecast/configure.in
   icecast/branches/kh/icecast/src/auth.c
   icecast/branches/kh/icecast/src/cfgfile.c
   icecast/branches/kh/icecast/src/cfgfile.h
   icecast/branches/kh/icecast/src/client.c
   icecast/branches/kh/icecast/src/connection.c
   icecast/branches/kh/icecast/src/format_mp3.c
   icecast/branches/kh/icecast/src/fserve.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/win32/icecast2.iss
Log:
bump for kh27. mainly down to the non-ogg metadata fix, possible race with
worker wakeup and reducing contention on stats locking.



Modified: icecast/branches/kh/icecast/NEWS
===================================================================
--- icecast/branches/kh/icecast/NEWS	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/NEWS	2010-09-12 21:21:21 UTC (rev 17384)
@@ -17,6 +17,17 @@
 any extra tags are show in the conf/icecast.xml.dist file
 
 
+2.3.2-kh27
+. use the tree locks instead of stats lock, this should lessen contention with many
+  stats updates, typicaly of setups with many streams.
+. rework previous non-ogg metadata short-write fix, was not complete.
+. previous non-ogg metadata fix exposed problem if file fallback used.
+. remove possible race waking up a worker, could result in crash.
+. add <max-stream-duration> to <mount> (in seconds), could even be used to cycle
+  dump files on a relay.
+. leave public setting as-is when on-demand relay stops.
+. minor legacy code cleanup
+
 2.3.2-kh26
 . fix possible content corruption on shoutcast metadata inserted streams if a short
   send occurs during metadata sending.

Modified: icecast/branches/kh/icecast/config.h.vc6
===================================================================
--- icecast/branches/kh/icecast/config.h.vc6	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/config.h.vc6	2010-09-12 21:21:21 UTC (rev 17384)
@@ -95,7 +95,7 @@
 #define PACKAGE_NAME "Icecast"
 
 /* Version number of package */
-#define VERSION "2.3.2-kh26"
+#define VERSION "2.3.2-kh27"
 
 /* Define to the version of this package. */
 #define PACKAGE_VERSION VERSION

Modified: icecast/branches/kh/icecast/configure.in
===================================================================
--- icecast/branches/kh/icecast/configure.in	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/configure.in	2010-09-12 21:21:21 UTC (rev 17384)
@@ -1,4 +1,4 @@
-AC_INIT([Icecast], [2.3.2-kh26], [karl at xiph.org])
+AC_INIT([Icecast], [2.3.2-kh27], [karl at xiph.org])
 
 LT_INIT
 AC_PREREQ(2.59)

Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/src/auth.c	2010-09-12 21:21:21 UTC (rev 17384)
@@ -343,17 +343,7 @@
             auth_user->handler = handler->id;
 
             if (auth_user->process)
-            {
-                worker_t *worker = NULL;
-                if (auth_user->client)
-                    worker = auth_user->client->worker;
                 auth_user->process (auth_user);
-                if (worker)
-                {
-                    /* wakeup worker for new client */
-                    worker_wakeup (worker);
-                }
-            }
 
             auth_client_free (auth_user);
 

Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/src/cfgfile.c	2010-09-12 21:21:21 UTC (rev 17384)
@@ -797,6 +797,8 @@
         { "authentication",     auth_get_authenticator, &mount->auth },
         { "on-connect",         config_get_str,     &mount->on_connect },
         { "on-disconnect",      config_get_str,     &mount->on_disconnect },
+        { "max-stream-duration",
+                                config_get_int,     &mount->max_stream_duration },
         { "max-listener-duration",
                                 config_get_int,     &mount->max_listener_duration },
         { "accesslog",          _parse_accesslog,   &mount->access_log },

Modified: icecast/branches/kh/icecast/src/cfgfile.h
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.h	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/src/cfgfile.h	2010-09-12 21:21:21 UTC (rev 17384)
@@ -130,6 +130,7 @@
     config_options_t *auth_options; /* Options for this type */
     char *on_connect;
     char *on_disconnect;
+    unsigned int max_stream_duration;
     unsigned int max_listener_duration;
 
     access_log      access_log;

Modified: icecast/branches/kh/icecast/src/client.c
===================================================================
--- icecast/branches/kh/icecast/src/client.c	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/src/client.c	2010-09-12 21:21:21 UTC (rev 17384)
@@ -416,7 +416,7 @@
     int ret, duration = (int)(worker->wakeup_ms - now);
     char ca[30];
 
-    if (duration > 60000) /* make duration between 5 and 60ms */
+    if (duration > 60000) /* make duration between 3ms and 60s */
         duration = 60000;
     if (duration < 3)
         duration = 3;

Modified: icecast/branches/kh/icecast/src/connection.c
===================================================================
--- icecast/branches/kh/icecast/src/connection.c	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/src/connection.c	2010-09-12 21:21:21 UTC (rev 17384)
@@ -380,8 +380,10 @@
 
 void connection_stats (void)
 {
+    long banned_IPs = 0;
     if (banned_ip.contents)
-        stats_event_args (NULL, "banned_IPs", "%ld", (long)banned_ip.contents->length);
+        banned_IPs = (long)banned_ip.contents->length;
+    stats_event_args (NULL, "banned_IPs", "%ld", banned_IPs);
 }
 
 /* function to handle the re-populating of the avl tree containing IP addresses
@@ -542,6 +544,7 @@
             free (ip);
         }
         memset (con, 0, sizeof (connection_t));
+        con->sock = SOCK_ERROR;
     }
     return -1;
 }

Modified: icecast/branches/kh/icecast/src/format_mp3.c
===================================================================
--- icecast/branches/kh/icecast/src/format_mp3.c	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/src/format_mp3.c	2010-09-12 21:21:21 UTC (rev 17384)
@@ -365,7 +365,8 @@
         }
         else
         {
-            if (associated) /* previously sent metadata does not need to be sent again */
+            /* previously sent metadata does not need to be sent again */
+            if (associated || client->flags & CLIENT_USING_BLANK_META)
             {
                 metadata = "\0";
                 meta_len = 1;
@@ -392,17 +393,20 @@
         ret = client_send_bytes (client, merge, remaining+meta_len);
         free (merge);
 
-        if (ret >= (int)remaining)
+        if (ret > (int)remaining)
         {
             /* did we write all of it? */
             if (ret < (int)remaining + meta_len)
             {
-                client_mp3->metadata_offset += (ret - remaining);
+                client_mp3->metadata_offset = (ret - remaining);
                 client->flags |= CLIENT_IN_METADATA;
                 client->schedule_ms += 200;
             }
             else
+            {
                 client->flags &= ~CLIENT_IN_METADATA;
+                client_mp3->metadata_offset = 0;
+            }
             client_mp3->since_meta_block = 0;
             client->pos += remaining;
             client->queue_pos += remaining;
@@ -415,7 +419,6 @@
             client->pos += ret;
             client->queue_pos += ret;
         }
-        client->flags |= CLIENT_IN_METADATA;
         return ret > 0 ? ret : 0;
     }
     ret = client_send_bytes (client, metadata, meta_len);
@@ -461,8 +464,8 @@
                 ret = send_stream_metadata (client, refbuf, remaining);
                 if (client->flags & CLIENT_IN_METADATA)
                     break;
-                buf += remaining;
-                len -= remaining;
+                buf = refbuf->data + client->pos;
+                len = refbuf->len - client->pos;
                 if (ret <= (int)remaining || len > client_mp3->interval)
                     break;
                 written += ret;
@@ -862,7 +865,9 @@
     else
         mpeg_cleanup (client_mp3->specific);
     free (client_mp3->specific);
-    refbuf_release (client_mp3->associated);
+    if ((client->flags & CLIENT_USING_BLANK_META) == 0)
+        refbuf_release (client_mp3->associated);
+    client_mp3->associated = NULL;
     free (client->format_data);
     client->format_data = NULL;
 }

Modified: icecast/branches/kh/icecast/src/fserve.c
===================================================================
--- icecast/branches/kh/icecast/src/fserve.c	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/src/fserve.c	2010-09-12 21:21:21 UTC (rev 17384)
@@ -929,8 +929,9 @@
         client->schedule_ms = client->worker->time_ms;
     else
     {
+        worker_t *worker = client->worker;
         client->flags |= CLIENT_ACTIVE;
-        worker_wakeup (client->worker);
+        worker_wakeup (worker); /* worker may of already processed client but make sure */
     }
     return 0;
 }
@@ -938,13 +939,8 @@
 
 void fserve_setup_client (client_t *client, const char *mount)
 {
-    fbinfo finfo;
-    finfo.flags = 0;
-    finfo.mount = (char *)mount;
-    finfo.fallback = NULL;
-    finfo.limit = 0;
     client->check_buffer = format_generic_write_to_client;
-    fserve_setup_client_fb (client, &finfo);
+    fserve_setup_client_fb (client, NULL);
 }
 
 

Modified: icecast/branches/kh/icecast/src/slave.c
===================================================================
--- icecast/branches/kh/icecast/src/slave.c	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/src/slave.c	2010-09-12 21:21:21 UTC (rev 17384)
@@ -693,8 +693,9 @@
                     {
                         /* wakeup client to change relay details */
                         client_t *client = source->client;
+                        worker_t *worker = client->worker;
                         client->schedule_ms = 0;
-                        worker_wakeup (client->worker);
+                        worker_wakeup (worker);
                     }
                 }
                 *existing_p = existing_relay->next; /* leave client to free structure */

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/src/source.c	2010-09-12 21:21:21 UTC (rev 17384)
@@ -1025,6 +1025,8 @@
     mountinfo = config_find_mount (config_get_config(), source->mount);
     if (mountinfo)
     {
+        if (mountinfo->max_stream_duration)
+            source->client->connection.discon_time = source->client->worker->current_time.tv_sec + mountinfo->max_stream_duration;
         if (mountinfo->on_connect)
             source_run_script (mountinfo->on_connect, source->mount);
         auth_stream_start (mountinfo, source->mount);
@@ -1188,7 +1190,7 @@
             /* handle header from icecast v2 release */
             str = httpp_getvar (parser, "icy-public");
             if (str) break;
-            str = "0";
+            str = source->yp_public > 0 ? "1" : "0";
         } while (0);
         val = atoi (str);
     }
@@ -1565,7 +1567,7 @@
 
     node = avl_get_first (source->clients);
     while (node)
-    {   
+    {
         client_t *existing_client = (client_t *)node->key;
         if (existing_client->username && 
                 strcmp (existing_client->username, client->username) == 0)

Modified: icecast/branches/kh/icecast/src/stats.c
===================================================================
--- icecast/branches/kh/icecast/src/stats.c	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/src/stats.c	2010-09-12 21:21:21 UTC (rev 17384)
@@ -121,7 +121,6 @@
 static void process_event (stats_event_t *event);
 static void _add_stats_to_stats_client (client_t *client, const char *fmt, va_list ap);
 static void stats_listener_send (int flags, const char *fmt, ...);
-static void process_event_unlocked (stats_event_t *event);
 
 unsigned int throttle_sends;
 
@@ -450,6 +449,7 @@
 {
     stats_node_t *node = NULL;
 
+    avl_tree_wlock (_stats.global_tree);
     /* DEBUG3("global event %s %s %d", event->name, event->value, event->action); */
     if (event->action == STATS_EVENT_REMOVE)
     {
@@ -460,6 +460,7 @@
             stats_listener_send (node->flags, "DELETE global %s\n", event->name);
             avl_delete(_stats.global_tree, (void *)node, _free_stats);
         }
+        avl_tree_unlock (_stats.global_tree);
         return;
     }
     node = _find_node(_stats.global_tree, event->name);
@@ -480,6 +481,7 @@
         avl_insert(_stats.global_tree, (void *)node);
         stats_listener_send (node->flags, "EVENT global %s %s\n", event->name, event->value);
     }
+    avl_tree_unlock (_stats.global_tree);
 }
 
 
@@ -488,13 +490,18 @@
     stats_source_t *snode = _find_source(_stats.source_tree, event->source);
     stats_node_t *node = NULL;
 
+    avl_tree_wlock (_stats.source_tree);
+    snode = _find_source(_stats.source_tree, event->source);
     if (snode == NULL)
     {
         if (event->action == STATS_EVENT_REMOVE)
+        {
+            avl_tree_unlock (_stats.source_tree);
             return;
+        }
         snode = (stats_source_t *)calloc(1,sizeof(stats_source_t));
         if (snode == NULL)
-            return;
+            abort();
         DEBUG1 ("new source stat %s", event->source);
         snode->source = (char *)strdup(event->source);
         snode->stats_tree = avl_tree_new(_compare_stats, NULL);
@@ -502,15 +509,21 @@
 
         avl_insert(_stats.source_tree, (void *)snode);
     }
+    if (event->action == STATS_EVENT_REMOVE)
+    {
+        avl_delete(_stats.source_tree, (void *)snode, _free_source_stats);
+        avl_tree_unlock (_stats.source_tree);
+        return;
+    }
+    avl_tree_wlock (snode->stats_tree);
+    avl_tree_unlock (_stats.source_tree);
     if (event->name)
     {
         node = _find_node (snode->stats_tree, event->name);
         if (node == NULL)
         {
-            if (event->action == STATS_EVENT_REMOVE)
-                return;
             /* adding node */
-            if (event->value)
+            if (event->action != STATS_EVENT_REMOVE && event->value)
             {
                 DEBUG3 ("new node on %s \"%s\" (%s)", event->source, event->name, event->value);
                 node = (stats_node_t *)calloc(1,sizeof(stats_node_t));
@@ -522,6 +535,7 @@
                 stats_listener_send (node->flags, "EVENT %s %s %s\n", event->source, event->name, event->value);
                 avl_insert(snode->stats_tree, (void *)node);
             }
+            avl_tree_unlock (snode->stats_tree);
             return;
         }
         if (event->action == STATS_EVENT_REMOVE)
@@ -529,10 +543,12 @@
             DEBUG1 ("delete node %s", event->name);
             stats_listener_send (node->flags, "DELETE %s %s\n", event->source, event->name);
             avl_delete(snode->stats_tree, (void *)node, _free_stats);
+            avl_tree_unlock (snode->stats_tree);
             return;
         }
         modify_node_event (node, event);
         stats_listener_send (node->flags, "EVENT %s %s %s\n", event->source, node->name, node->value);
+        avl_tree_unlock (snode->stats_tree);
         return;
     }
     /* change source flags status */
@@ -542,7 +558,10 @@
         int visible = 0;
 
         if ((event->flags&STATS_HIDDEN) == (snode->flags&STATS_HIDDEN))
+        {
+            avl_tree_unlock (snode->stats_tree);
             return;
+        }
         if (snode->flags & STATS_HIDDEN)
         {
             snode->flags &= ~STATS_HIDDEN;
@@ -566,10 +585,10 @@
                 stats->flags |= STATS_HIDDEN;
             node = avl_get_next (node);
         }
+        avl_tree_unlock (snode->stats_tree);
         return;
     }
-    if (event->action == STATS_EVENT_REMOVE)
-        avl_delete(_stats.source_tree, (void *)snode, _free_source_stats);
+    avl_tree_unlock (snode->stats_tree);
 }
 
 
@@ -702,8 +721,10 @@
 #endif
 }
 
-static void process_event_unlocked (stats_event_t *event)
+static void process_event (stats_event_t *event)
 {
+    if (event == NULL)
+        return;
     /* check if we are dealing with a global or source event */
     if (event->source == NULL)
         process_global_event (event);
@@ -711,16 +732,7 @@
         process_source_event (event);
 }
 
-static void process_event (stats_event_t *event)
-{
-    if (event == NULL)
-        return;
-    thread_mutex_lock (&_stats_mutex);
-    process_event_unlocked (event);
-    thread_mutex_unlock (&_stats_mutex);
-}
 
-
 static int _append_to_bufferv (refbuf_t *refbuf, int max_len, const char *fmt, va_list ap)
 {
     char *buf = (char*)refbuf->data + refbuf->len;
@@ -806,8 +818,8 @@
     avl_node *avlnode;
     xmlNodePtr ret = NULL;
 
-    thread_mutex_lock(&_stats_mutex);
     /* general stats first */
+    avl_tree_rlock (_stats.global_tree);
     avlnode = avl_get_first(_stats.global_tree);
     while (avlnode)
     {
@@ -816,7 +828,9 @@
             xmlNewTextChild (root, NULL, XMLSTR(stat->name), XMLSTR(stat->value));
         avlnode = avl_get_next (avlnode);
     }
+    avl_tree_unlock (_stats.global_tree);
     /* now per mount stats */
+    avl_tree_rlock (_stats.source_tree);
     avlnode = avl_get_first(_stats.source_tree);
     while (avlnode)
     {
@@ -824,8 +838,10 @@
         if (((flags&STATS_HIDDEN) || (source->flags&STATS_HIDDEN) == (flags&STATS_HIDDEN)) &&
                 (show_mount == NULL || strcmp (show_mount, source->source) == 0))
         {
-            avl_node *avlnode2 = avl_get_first (source->stats_tree);
+            avl_node *avlnode2;
             xmlNodePtr xmlnode = xmlNewTextChild (root, NULL, XMLSTR("source"), NULL);
+            avl_tree_rlock (source->stats_tree);
+            avlnode2 = avl_get_first (source->stats_tree);
 
             xmlSetProp (xmlnode, XMLSTR("mount"), XMLSTR(source->source));
             if (ret == NULL)
@@ -837,10 +853,11 @@
                     xmlNewTextChild (xmlnode, NULL, XMLSTR(stat->name), XMLSTR(stat->value));
                 avlnode2 = avl_get_next (avlnode2);
             }
+            avl_tree_unlock (source->stats_tree);
         }
         avlnode = avl_get_next (avlnode);
     }
-    thread_mutex_unlock(&_stats_mutex);
+    avl_tree_unlock (_stats.source_tree);
     return ret;
 }
 
@@ -859,7 +876,7 @@
 
     build_event (&stats_count, NULL, "stats_connections", buffer);
     stats_count.action = STATS_EVENT_INC;
-    process_event_unlocked (&stats_count);
+    process_event (&stats_count);
 
     /* first we fill our queue with the current stats */
     refbuf = refbuf_new (size);
@@ -943,7 +960,7 @@
             client_destroy (client);
             build_event (&stats_count, NULL, "stats_connections", buffer);
             stats_count.action = STATS_EVENT_DEC;
-            process_event_unlocked (&stats_count);
+            process_event (&stats_count);
             return;
         }
         trail = &listener->next;
@@ -1096,7 +1113,7 @@
     prelen = strlen (pre);
 
     /* now the stats for each source */
-    thread_mutex_lock (&_stats_mutex);
+    avl_tree_rlock (_stats.source_tree);
     node = avl_get_first(_stats.source_tree);
     while (node)
     {
@@ -1122,7 +1139,7 @@
         }
         node = avl_get_next(node);
     }
-    thread_mutex_unlock (&_stats_mutex);
+    avl_tree_unlock (_stats.source_tree);
     cur->len = STREAMLIST_BLKSIZE - remaining;
     return start;
 }
@@ -1137,7 +1154,7 @@
 {
     avl_node *snode;
 
-    thread_mutex_lock (&_stats_mutex);
+    avl_tree_wlock (_stats.source_tree);
     snode = avl_get_first(_stats.source_tree);
     while (snode)
     {
@@ -1158,7 +1175,7 @@
 
         snode = avl_get_next (snode);
     }
-    thread_mutex_unlock (&_stats_mutex);
+    avl_tree_unlock (_stats.source_tree);
 }
 
 
@@ -1182,12 +1199,12 @@
     build_event (&event, NULL, "outgoing_kbitrate", buffer);
     event.flags = STATS_COUNTERS|STATS_HIDDEN;
 
-    thread_mutex_lock (&_stats_mutex);
     snprintf (buffer, sizeof(buffer), "%" PRIu64,
             (int64_t)global_getrate_avg (global.out_bitrate) * 8 / 1024);
-    process_event_unlocked (&event);
+    process_event (&event);
 
     /* retrieve the list of closing down clients */
+    thread_mutex_lock (&_stats_mutex);
     listener = _stats.listeners_removed;
     _stats.listeners_removed = NULL;
     thread_mutex_unlock (&_stats_mutex);

Modified: icecast/branches/kh/icecast/win32/icecast2.iss
===================================================================
--- icecast/branches/kh/icecast/win32/icecast2.iss	2010-09-12 03:26:30 UTC (rev 17383)
+++ icecast/branches/kh/icecast/win32/icecast2.iss	2010-09-12 21:21:21 UTC (rev 17384)
@@ -3,7 +3,7 @@
 
 [Setup]
 AppName=Icecast2-KH
-AppVerName=Icecast v2.3.2-kh26
+AppVerName=Icecast v2.3.2-kh27
 AppPublisherURL=http://www.icecast.org
 AppSupportURL=http://www.icecast.org
 AppUpdatesURL=http://www.icecast.org
@@ -13,7 +13,7 @@
 LicenseFile=..\COPYING
 InfoAfterFile=..\README
 OutputDir=.
-OutputBaseFilename=icecast2_win32_v2.3.2-kh26
+OutputBaseFilename=icecast2_win32_v2.3.2-kh27_setup
 WizardImageFile=icecast2logo2.bmp
 WizardImageStretch=no
 VersionInfoVersion=2.3.2



More information about the commits mailing list