[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