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

Michael Smith msmith at xiph.org
Thu Mar 13 23:59:58 PST 2003



msmith      03/03/14 02:59:58

  Modified:    src      admin.c source.c source.h
  Log:
  Bugfix: source shutdown did things in the wrong order, could lead to clients
  ending up connecting to a source which didn't exist.
  
  Add 'moveclients' admin command to move all clients from one source to
  another (without shutting the old source down)

Revision  Changes    Path
1.5       +44 -0     icecast/src/admin.c

Index: admin.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/admin.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- admin.c	10 Mar 2003 22:20:16 -0000	1.4
+++ admin.c	14 Mar 2003 07:59:58 -0000	1.5
@@ -25,6 +25,7 @@
 #define COMMAND_FALLBACK            1
 #define COMMAND_METADATA_UPDATE     2
 #define COMMAND_SHOW_LISTENERS      3
+#define COMMAND_MOVE_CLIENTS        4
 
 /* Global commands */
 #define COMMAND_LIST_MOUNTS       101
@@ -47,6 +48,8 @@
         return COMMAND_LIST_MOUNTS;
     else if(!strcmp(command, "streamlist"))
         return COMMAND_RAW_LISTSTREAM;
+    else if(!strcmp(command, "moveclients"))
+        return COMMAND_MOVE_CLIENTS;
     else
         return COMMAND_ERROR;
 }
@@ -54,6 +57,7 @@
 static void command_fallback(client_t *client, source_t *source);
 static void command_metadata(client_t *client, source_t *source);
 static void command_show_listeners(client_t *client, source_t *source);
+static void command_move_clients(client_t *client, source_t *source);
 
 static void command_raw_stats(client_t *client);
 static void command_list_mounts(client_t *client, int formatted);
@@ -160,6 +164,9 @@
         case COMMAND_SHOW_LISTENERS:
             command_show_listeners(client, source);
             break;
+        case COMMAND_MOVE_CLIENTS:
+            command_move_clients(client, source);
+            break;
         default:
             WARN0("Mount request not recognised");
             client_send_400(client, "Mount request unknown");
@@ -212,6 +219,43 @@
     bytes = sock_write_fmt(client->con->sock, fmt, ap);
     va_end(ap);
     if(bytes > 0) client->con->sent_bytes = bytes;
+}
+
+static void command_move_clients(client_t *client, source_t *source)
+{
+    char *dest_source;
+    source_t *dest;
+    avl_node *client_node;
+    client_t *current;
+
+    COMMAND_REQUIRE(client, "destination", dest_source);
+    
+    avl_tree_rlock(global.source_tree);
+    dest = source_find_mount(dest_source);
+    avl_tree_unlock(global.source_tree);
+
+    if(dest == NULL) {
+        client_send_400(client, "No such source");
+        return;
+    }
+
+    avl_tree_wlock(source->client_tree);
+    client_node = avl_get_first(source->client_tree);
+    while(client_node) {
+        current = (client_t *)client_node->key;
+
+        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);
+    }
+
+    avl_tree_unlock(source->client_tree);
+        
+    html_success(client, "Clients moved");
 }
 
 static void command_show_listeners(client_t *client, source_t *source)

<p><p>1.43      +20 -10    icecast/src/source.c

Index: source.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -r1.42 -r1.43
--- source.c	6 Mar 2003 14:17:33 -0000	1.42
+++ source.c	14 Mar 2003 07:59:58 -0000	1.43
@@ -49,7 +49,6 @@
 
 /* avl tree helper */
 static int _compare_clients(void *compare_arg, void *a, void *b);
-static int _remove_client(void *key);
 static int _free_client(void *key);
 static int _parse_audio_info(source_t *source, char *s);
 static void _add_yp_info(source_t *source, char *stat_name, 
@@ -96,6 +95,11 @@
         return src;
 }
 
+static int source_remove_source(void *key)
+{
+    return 1;
+}
+
 /* you must already have a read lock on the global source tree
 ** to call this function
 */
@@ -136,7 +140,7 @@
 
 int source_free_source(void *key)
 {
-	source_t *source = (source_t *)key;
+    source_t *source = key;
         int i=0;
 
         free(source->mount);
@@ -552,7 +556,7 @@
 
                 /** clear pending tree **/
                 while (avl_get_first(source->pending_tree)) {
-			avl_delete(source->pending_tree, avl_get_first(source->pending_tree)->key, _remove_client);
+			avl_delete(source->pending_tree, avl_get_first(source->pending_tree)->key, source_remove_client);
                 }
 
                 /* release write lock on pending_tree */
@@ -573,13 +577,21 @@
     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);
+
         /* 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, _remove_client);
+            avl_delete(source->pending_tree, client, source_remove_client);
 
             /* TODO: reset client local format data?  */
             avl_tree_wlock(fallback_source->pending_tree);
@@ -597,7 +609,7 @@
         client_t *client = (client_t *)avl_get_first(source->client_tree)->key;
 
         if(fallback_source) {
-            avl_delete(source->client_tree, client, _remove_client);
+            avl_delete(source->client_tree, client, source_remove_client);
 
             /* TODO: reset client local format data?  */
             avl_tree_wlock(fallback_source->pending_tree);
@@ -621,13 +633,11 @@
     if(source->dumpfile)
         fclose(source->dumpfile);
 
+    source_free_source(source);
+
         /* release our hold on the lock so the main thread can continue cleaning up */
         thread_rwlock_unlock(source->shutdown_rwlock);
 
-	avl_tree_wlock(global.source_tree);
-	avl_delete(global.source_tree, source, source_free_source);
-	avl_tree_unlock(global.source_tree);
-
         thread_exit(0);
       
         return NULL;
@@ -644,7 +654,7 @@
         return 0;
 }
 
-static int _remove_client(void *key)
+int source_remove_client(void *key)
 {
         return 1;
 }

<p><p>1.11      +1 -0      icecast/src/source.h

Index: source.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- source.h	2 Mar 2003 10:13:59 -0000	1.10
+++ source.h	14 Mar 2003 07:59:58 -0000	1.11
@@ -47,6 +47,7 @@
 source_t *source_find_mount(const char *mount);
 int source_compare_sources(void *arg, void *a, void *b);
 int source_free_source(void *key);
+int source_remove_client(void *key);
 void *source_main(void *arg);
 
 #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