[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