1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2025-02-02 15:07:36 -05:00

When starting relay threads, have the relay thread do the connection not the

slave thread.  Also improve cleanup handling and log messages as well

svn path=/icecast/trunk/icecast/; revision=8068
This commit is contained in:
Karl Heyes 2004-10-23 00:44:29 +00:00
parent 02471ae68d
commit 17537d2457
2 changed files with 135 additions and 94 deletions

View File

@ -62,7 +62,8 @@
static void *_slave_thread(void *arg);
thread_type *_slave_thread_id;
static int slave_running = 0;
static int max_interval = 0;
static unsigned int max_interval = 0;
static int rescan_relays = 0;
relay_server *relay_free (relay_server *relay)
{
@ -73,7 +74,7 @@ relay_server *relay_free (relay_server *relay)
xmlFree (relay->server);
xmlFree (relay->mount);
xmlFree (relay->localmount);
xmlFree (relay);
free (relay);
return next;
}
@ -94,28 +95,22 @@ relay_server *relay_copy (relay_server *r)
}
static void *_relay_thread (void *arg)
{
relay_server *relay = arg;
relay->running = 1;
stats_event_inc(NULL, "source_relay_connections");
source_main (relay->source);
relay->running = 0;
if (relay->cleanup)
relay_free (relay);
return NULL;
}
/* force a recheck of the relays. This will recheck the master server if
* a this is a slave.
*/
void slave_recheck (void)
{
max_interval = 0;
}
/* rescan the current relays to see if any need starting or if any
* relay threads have terminated
*/
void slave_rescan (void)
{
rescan_relays = 1;
}
void slave_initialize(void)
{
@ -129,36 +124,27 @@ void slave_initialize(void)
void slave_shutdown(void)
{
relay_server *relay;
if (!slave_running)
return;
slave_running = 0;
DEBUG0 ("waiting for slave thread");
thread_join (_slave_thread_id);
relay = global.relays;
while (relay)
relay = relay_free (relay);
global.relays = NULL;
relay = global.master_relays;
while (relay)
relay = relay_free (relay);
global.master_relays = NULL;
}
/* This does the actual connection for a relay. A thread is
* started off if a connection can be acquired
*/
static void start_relay_stream (relay_server *relay)
static void *start_relay_stream (void *arg)
{
relay_server *relay = arg;
sock_t streamsock = SOCK_ERROR;
source_t *src = relay->source;
http_parser_t *parser = NULL;
connection_t *con=NULL;
char header[4096];
relay->running = 1;
INFO1("Starting relayed source at mountpoint \"%s\"", relay->localmount);
do
{
@ -206,9 +192,15 @@ static void start_relay_stream (relay_server *relay)
DEBUG0("Failed to complete source initialisation");
break;
}
thread_create ("Relay Thread", _relay_thread, relay, THREAD_DETACHED);
stats_event_inc(NULL, "source_relay_connections");
return;
source_main (relay->source);
/* initiate an immediate relay cleanup run */
relay->cleanup = 1;
slave_rescan();
return NULL;
} while (0);
if (con == NULL && streamsock != SOCK_ERROR)
@ -220,6 +212,12 @@ static void start_relay_stream (relay_server *relay)
httpp_destroy (parser);
src->parser = NULL;
source_clear_source (relay->source);
/* initiate an immediate relay cleanup run */
relay->cleanup = 1;
slave_rescan();
return NULL;
}
@ -228,13 +226,33 @@ static void check_relay_stream (relay_server *relay)
{
if (relay->source == NULL)
{
if (relay->localmount[0] != '/')
{
WARN1 ("relay mountpoint \"%s\" does not start with /, skipping",
relay->localmount);
return;
}
/* new relay, reserve the name */
DEBUG1("Adding relay source at mountpoint \"%s\"", relay->localmount);
relay->source = source_reserve (relay->localmount);
if (relay->source)
DEBUG1("Adding relay source at mountpoint \"%s\"", relay->localmount);
else
WARN1 ("new relay but source \"%s\" already exists", relay->localmount);
}
if (relay->source && !relay->running)
{
start_relay_stream (relay);
relay->thread = thread_create ("Relay Thread", start_relay_stream,
relay, THREAD_ATTACHED);
return;
}
/* the relay thread may of close down */
if (relay->cleanup && relay->thread)
{
DEBUG1 ("waiting for relay thread for \"%s\"", relay->localmount);
thread_join (relay->thread);
relay->thread = NULL;
relay->cleanup = 0;
relay->running = 0;
}
}
@ -257,6 +275,7 @@ update_relay_set (relay_server **current, relay_server *updated)
while (existing_relay)
{
/* break out if keeping relay */
if (strcmp (relay->localmount, existing_relay->localmount) == 0)
break;
existing_p = &existing_relay->next;
@ -281,33 +300,44 @@ update_relay_set (relay_server **current, relay_server *updated)
/* update the relay_list with entries from new_relay_list. Any new relays
* are added to the list, and any not listed in the provided new_relay_list
* get marked for shutting down, just in case they are not shutting down by
* themselves
* are separated and returned in a separate list
*/
static void
static relay_server *
update_relays (relay_server **relay_list, relay_server *new_relay_list)
{
relay_server *relay, *current;
relay_server *active_relays, *cleanup_relays;
current = update_relay_set (relay_list, new_relay_list);
active_relays = update_relay_set (relay_list, new_relay_list);
/* ok whats left, lets make sure they shut down */
relay = *relay_list;
cleanup_relays = *relay_list;
/* re-assign new set */
*relay_list = active_relays;
return cleanup_relays;
}
static void relay_check_streams (relay_server *to_start, relay_server *to_free)
{
relay_server *relay;
while (to_free)
{
if (to_free->running && to_free->source)
{
DEBUG1 ("source shutdown request on \"%s\"", to_free->localmount);
to_free->source->running = 0;
thread_join (to_free->thread);
}
to_free = relay_free (to_free);
}
relay = to_start;
while (relay)
{
relay->cleanup = 1;
if (relay->source)
{
if (relay->source->running)
DEBUG1 ("requested %s to shut down", relay->source->mount);
relay->source->running = 0;
relay = relay->next;
}
else
relay = relay_free (relay);
check_relay_stream (relay);
relay = relay->next;
}
/* re-assign new set */
*relay_list = current;
}
@ -321,7 +351,7 @@ static int update_from_master(ice_config_t *config)
do
{
char *authheader, *data;
relay_server *relays = NULL, *relay;
relay_server *new_relays = NULL, *cleanup_relays;
int len, count = 1;
username = strdup ("relay");
@ -345,11 +375,9 @@ static int update_from_master(ice_config_t *config)
break;
}
len = strlen(username) + strlen(password) + 1;
authheader = malloc(len+1);
strcpy(authheader, username);
strcat(authheader, ":");
strcat(authheader, password);
len = strlen(username) + strlen(password) + 2;
authheader = malloc(len);
snprintf (authheader, len, "%s:%s", username, password);
data = util_base64_encode(authheader);
sock_write (mastersock,
"GET /admin/streamlist.txt HTTP/1.0\r\n"
@ -385,23 +413,20 @@ static int update_from_master(ice_config_t *config)
r->mount = xmlStrdup (buf);
r->localmount = xmlStrdup (buf);
r->mp3metadata = 1;
r->next = relays;
relays = r;
r->next = new_relays;
new_relays = r;
}
}
sock_close (mastersock);
update_relays (&global.master_relays, relays);
/* start any inactive relays */
relay = global.master_relays;
while (relay)
{
check_relay_stream (relay);
relay = relay->next;
}
relay = relays;
while (relay)
relay = relay_free (relay);
thread_mutex_lock (&(config_locks()->relay_lock));
cleanup_relays = update_relays (&global.master_relays, new_relays);
relay_check_streams (global.master_relays, cleanup_relays);
relay_check_streams (NULL, new_relays);
thread_mutex_unlock (&(config_locks()->relay_lock));
} while(0);
if (master)
@ -418,39 +443,52 @@ static int update_from_master(ice_config_t *config)
static void *_slave_thread(void *arg)
{
ice_config_t *config;
relay_server *relay;
unsigned interval = 0;
unsigned int interval = 0;
while (slave_running)
{
relay_server *cleanup_relays;
thread_sleep (1000000);
if (max_interval > ++interval)
if (rescan_relays == 0 && max_interval > ++interval)
continue;
interval = 0;
config = config_get_config();
max_interval = config->master_update_interval;
/* the connection could time some time, so the lock can drop */
if (update_from_master (config))
/* only update relays lists when required */
if (max_interval <= interval)
{
DEBUG0 ("checking master stream list");
config = config_get_config();
thread_mutex_lock (&(config_locks()->relay_lock));
interval = 0;
max_interval = config->master_update_interval;
update_relays (&global.relays, config->relay);
/* the connection could take some time, so the lock can drop */
if (update_from_master (config))
config = config_get_config();
config_release_config();
thread_mutex_lock (&(config_locks()->relay_lock));
/* start any inactive relays */
relay = global.relays;
while (relay)
{
check_relay_stream (relay);
relay = relay->next;
cleanup_relays = update_relays (&global.relays, config->relay);
config_release_config();
relay_check_streams (global.relays, cleanup_relays);
thread_mutex_unlock (&(config_locks()->relay_lock));
}
thread_mutex_unlock (&(config_locks()->relay_lock));
else
{
DEBUG0 ("rescanning relay lists");
thread_mutex_lock (&(config_locks()->relay_lock));
relay_check_streams (global.master_relays, NULL);
relay_check_streams (global.relays, NULL);
thread_mutex_unlock (&(config_locks()->relay_lock));
}
rescan_relays = 0;
}
DEBUG0 ("shutting down current relays");
relay_check_streams (NULL, global.relays);
relay_check_streams (NULL, global.master_relays);
INFO0 ("Slave thread shutdown complete");
return NULL;

View File

@ -13,6 +13,8 @@
#ifndef __SLAVE_H__
#define __SLAVE_H__
#include <thread/thread.h>
typedef struct _relay_server {
char *server;
int port;
@ -22,6 +24,7 @@ typedef struct _relay_server {
int mp3metadata;
int running;
int cleanup;
thread_type *thread;
struct _relay_server *next;
} relay_server;