[xiph-cvs] cvs commit: icecast/src admin.c connection.c source.c source.h

Karl Heyes karl at xiph.org
Thu Jan 29 08:46:55 PST 2004



karl        04/01/29 11:46:55

  Modified:    src      admin.c connection.c source.c source.h
  Log:
  cleanup duplicate work, fix rare but potential deadlock, and
  fix silly bug introduced ealrier

Revision  Changes    Path
1.20      +14 -24    icecast/src/admin.c

Index: admin.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/admin.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- admin.c	29 Jan 2004 01:02:06 -0000	1.19
+++ admin.c	29 Jan 2004 16:46:54 -0000	1.20
@@ -438,8 +438,6 @@
 {
     char *dest_source;
     source_t *dest;
-    avl_node *client_node;
-    client_t *current;
     xmlDocPtr doc;
     xmlNodePtr node;
     char buf[255];
@@ -459,16 +457,23 @@
         return;
     }
 
+    dest = source_find_mount (dest_source);
+
+    if (dest == NULL)
+    {
+        client_send_400 (client, "No such destination");
+        return;
+    }
+
     if (strcmp (dest->mount, source->mount) == 0) 
     {
         client_send_400 (client, "supplied mountpoints are identical");
         return;
     }
 
-    dest = source_find_mount(dest_source);
-
-    if(dest == NULL) {
-        client_send_400(client, "No such source");
+    if (dest->running == 0)
+    {
+        client_send_400 (client, "Destination not running");
         return;
     }
 
@@ -476,26 +481,11 @@
     node = xmlNewDocNode(doc, NULL, "iceresponse", NULL);
     xmlDocSetRootElement(doc, node);
 
-    avl_tree_wlock(source->client_tree);
-    client_node = avl_get_first(source->client_tree);
-    while(client_node) {
-        current = (client_t *)client_node->key;
+    source_move_clients (source, dest);
 
-        avl_tree_wlock(dest->pending_tree);
-        avl_insert(dest->pending_tree, current);
-        avl_tree_unlock(dest->pending_tree);
-
-        client_node = avl_get_next(client_node);
-
-        avl_delete(source->client_tree, current, source_remove_client);
-        source->listeners--;
-    }
-
-    avl_tree_unlock(source->client_tree);
-        
     memset(buf, '\000', sizeof(buf));
-    snprintf(buf, sizeof(buf)-1, "Clients moved from %s to %s", dest_source, 
-        source->mount);
+    snprintf (buf, sizeof(buf), "Clients moved from %s to %s",
+            source->mount, dest_source);
     xmlNewChild(node, NULL, "message", buf);
     xmlNewChild(node, NULL, "return", "1");
 

<p><p>1.83      +2 -0      icecast/src/connection.c

Index: connection.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/connection.c,v
retrieving revision 1.82
retrieving revision 1.83
diff -u -r1.82 -r1.83
--- connection.c	29 Jan 2004 01:02:06 -0000	1.82
+++ connection.c	29 Jan 2004 16:46:54 -0000	1.83
@@ -95,6 +95,7 @@
     
     thread_mutex_create(&_connection_mutex);
     thread_mutex_create(&_queue_mutex);
+    thread_mutex_create(&move_clients_mutex);
     thread_rwlock_create(&_source_shutdown_rwlock);
     thread_cond_create(&_pool_cond);
     thread_cond_create(&global.shutdown_cond);
@@ -111,6 +112,7 @@
     thread_rwlock_destroy(&_source_shutdown_rwlock);
     thread_mutex_destroy(&_queue_mutex);
     thread_mutex_destroy(&_connection_mutex);
+    thread_mutex_destroy(&move_clients_mutex);
 
     _initialized = 0;
 }

<p><p>1.67      +68 -79    icecast/src/source.c

Index: source.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.c,v
retrieving revision 1.66
retrieving revision 1.67
diff -u -r1.66 -r1.67
--- source.c	29 Jan 2004 01:02:06 -0000	1.66
+++ source.c	29 Jan 2004 16:46:54 -0000	1.67
@@ -56,6 +56,8 @@
 
 #define MAX_FALLBACK_DEPTH 10
 
+mutex_t move_clients_mutex;
+
 /* avl tree helper */
 static int _compare_clients(void *compare_arg, void *a, void *b);
 static int _free_client(void *key);
@@ -113,11 +115,6 @@
     return src;
 }
 
-static int source_remove_source(void *key)
-{
-    return 1;
-}
-
 /* Find a mount with this raw name - ignoring fallbacks. You should have the
  * global source tree locked to call this.
  */
@@ -250,7 +247,63 @@
     avl_tree_unlock(source->client_tree);
     return NULL;
 }
+
+void source_move_clients (source_t *source, source_t *dest)
+{
+    client_t *client;
+    avl_node *node;
+
+    if (source->format->type != dest->format->type)
+    {
+        WARN2 ("stream %s and %s are of different types, ignored", source->mount, dest->mount);
+        return;
+    }
+    if (dest->running == 0)
+    {
+        WARN1 ("source %s not running, unable to move clients ", dest->mount);
+        return;
+    }
     
+    /* we don't want the two write locks to deadlock in here */
+    thread_mutex_lock (&move_clients_mutex);
+
+    /* we need to move the client and pending trees */
+    avl_tree_wlock (dest->pending_tree);
+    avl_tree_wlock (source->pending_tree);
+
+    while (1)
+    {
+        node = avl_get_first (source->pending_tree);
+        if (node == NULL)
+            break;
+        client = (client_t *)(node->key);
+        avl_delete (source->pending_tree, client, NULL);
+
+        /* TODO: reset client local format data?  */
+        avl_insert (dest->pending_tree, (void *)client);
+    }
+    avl_tree_unlock (source->pending_tree);
+
+    avl_tree_wlock (source->client_tree);
+    while (1)
+    {
+        node = avl_get_first (source->client_tree);
+        if (node == NULL)
+            break;
+
+        client = (client_t *)(node->key);
+        avl_delete (source->client_tree, client, NULL);
+
+        /* TODO: reset client local format data?  */
+        avl_insert (dest->pending_tree, (void *)client);
+    }
+    source->listeners = 0;
+    stats_event(source->mount, "listeners", "0");
+    avl_tree_unlock (source->client_tree);
+    avl_tree_unlock (dest->pending_tree);
+    thread_mutex_unlock (&move_clients_mutex);
+}
+
 
 void *source_main(void *arg)
 {
@@ -450,39 +503,11 @@
     if(source->fallback_override && source->fallback_mount) {
         avl_tree_rlock(global.source_tree);
         fallback_source = source_find_mount(source->fallback_mount);
-        avl_tree_unlock(global.source_tree);
 
-        if(fallback_source) {
-            /* we need to move the client and pending trees */
-            avl_tree_wlock(fallback_source->pending_tree);
-            while (avl_get_first(fallback_source->pending_tree)) {
-                client_t *client = (client_t *)avl_get_first(
-                        fallback_source->pending_tree)->key;
-                avl_delete(fallback_source->pending_tree, client, 
-                        source_remove_client);
-
-                /* TODO: reset client local format data?  */
-                avl_tree_wlock(source->pending_tree);
-                avl_insert(source->pending_tree, (void *)client);
-                avl_tree_unlock(source->pending_tree);
-            }
-            avl_tree_unlock(fallback_source->pending_tree);
-
-            avl_tree_wlock(fallback_source->client_tree);
-            while (avl_get_first(fallback_source->client_tree)) {
-                client_t *client = (client_t *)avl_get_first(
-                        fallback_source->client_tree)->key;
-
-                avl_delete(fallback_source->client_tree, client, 
-                        source_remove_client);
-
-                /* TODO: reset client local format data?  */
-                avl_tree_wlock(source->pending_tree);
-                avl_insert(source->pending_tree, (void *)client);
-                avl_tree_unlock(source->pending_tree);
-            }
-            avl_tree_unlock(fallback_source->client_tree);
-        }
+        if (fallback_source)
+            source_move_clients (fallback_source, source);
+
+        avl_tree_unlock(global.source_tree);
     }
 
     while (global.running == ICE_RUNNING && source->running) {
@@ -732,54 +757,18 @@
     }
 #endif
     
-    avl_tree_rlock(global.source_tree);
-    fallback_source = source_find_mount(source->fallback_mount);
-    avl_tree_unlock(global.source_tree);
-
     /* Now, we must remove this source from the source tree before
      * removing the clients, otherwise new clients can sneak into the pending
      * tree after we've cleared it
      */
     avl_tree_wlock(global.source_tree);
-    avl_delete(global.source_tree, source, source_remove_source);
-    avl_tree_unlock(global.source_tree);
+    fallback_source = source_find_mount (source->fallback_mount);
+    avl_delete (global.source_tree, source, NULL);
 
-    /* we need to empty the client and pending trees */
-    avl_tree_wlock(source->pending_tree);
-    while (avl_get_first(source->pending_tree)) {
-        client_t *client = (client_t *)avl_get_first(
-                source->pending_tree)->key;
-        if(fallback_source) {
-            avl_delete(source->pending_tree, client, source_remove_client);
-
-            /* TODO: reset client local format data?  */
-            avl_tree_wlock(fallback_source->pending_tree);
-            avl_insert(fallback_source->pending_tree, (void *)client);
-            avl_tree_unlock(fallback_source->pending_tree);
-        }
-        else {
-            avl_delete(source->pending_tree, client, _free_client);
-        }
-    }
-    avl_tree_unlock(source->pending_tree);
-
-    avl_tree_wlock(source->client_tree);
-    while (avl_get_first(source->client_tree)) {
-        client_t *client = (client_t *)avl_get_first(source->client_tree)->key;
-
-        if(fallback_source) {
-            avl_delete(source->client_tree, client, source_remove_client);
-
-            /* TODO: reset client local format data?  */
-            avl_tree_wlock(fallback_source->pending_tree);
-            avl_insert(fallback_source->pending_tree, (void *)client);
-            avl_tree_unlock(fallback_source->pending_tree);
-        }
-        else {
-            avl_delete(source->client_tree, client, _free_client);
-        }
-    }
-    avl_tree_unlock(source->client_tree);
+    if (fallback_source != NULL)
+        source_move_clients (source, fallback_source);
+
+    avl_tree_unlock (global.source_tree);
 
     /* delete this sources stats */
     stats_event_dec(NULL, "sources");

<p><p>1.18      +3 -0      icecast/src/source.h

Index: source.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- source.h	29 Jan 2004 01:02:07 -0000	1.17
+++ source.h	29 Jan 2004 16:46:54 -0000	1.18
@@ -67,9 +67,12 @@
 client_t *source_find_client(source_t *source, int id);
 int source_compare_sources(void *arg, void *a, void *b);
 int source_free_source(void *key);
+void source_move_clients (source_t *source, source_t *dest);
 int source_remove_client(void *key);
 void *source_main(void *arg);
 
+extern mutex_t move_clients_mutex;
+
 #endif
 
 

<p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list