Commit d9723325 authored by Karl Heyes's avatar Karl Heyes

Make fserve thread start up only when required. In most cases this thread is

just in a sleep loop which means most clients getting to it have to wait. We
now just start the thread when there is work to do.  There is also some small
cleanup for the off_t type usage as well.

svn path=/icecast/trunk/icecast/; revision=15124
parent 0bd5f9e7
...@@ -29,12 +29,14 @@ ...@@ -29,12 +29,14 @@
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/socket.h> #include <sys/socket.h>
#define SCN_OFF_T SCNdMAX
#define PRI_OFF_T PRIdMAX
#else #else
#include <winsock2.h> #include <winsock2.h>
#include <windows.h> #include <windows.h>
#define fseeko fseek #define fseeko fseek
#define PRIdMAX "ld" #define SCN_OFF_T "ld"
#define SCNdMAX "ld" #define PRI_OFF_T "ld"
#define snprintf _snprintf #define snprintf _snprintf
#define strncasecmp _strnicmp #define strncasecmp _strnicmp
#define S_ISREG(mode) ((mode) & _S_IFREG) #define S_ISREG(mode) ((mode) & _S_IFREG)
...@@ -70,8 +72,7 @@ static volatile fserve_t *pending_list = NULL; ...@@ -70,8 +72,7 @@ static volatile fserve_t *pending_list = NULL;
static mutex_t pending_lock; static mutex_t pending_lock;
static avl_tree *mimetypes = NULL; static avl_tree *mimetypes = NULL;
static thread_type *fserv_thread; static volatile int run_fserv = 0;
static int run_fserv = 0;
static unsigned int fserve_clients; static unsigned int fserve_clients;
static int client_tree_changed=0; static int client_tree_changed=0;
...@@ -101,23 +102,34 @@ void fserve_initialize(void) ...@@ -101,23 +102,34 @@ void fserve_initialize(void)
fserve_recheck_mime_types (config); fserve_recheck_mime_types (config);
config_release_config(); config_release_config();
run_fserv = 1;
stats_event (NULL, "file_connections", "0"); stats_event (NULL, "file_connections", "0");
INFO0("file serving started");
fserv_thread = thread_create("File Serving Thread",
fserv_thread_function, NULL, THREAD_ATTACHED);
} }
void fserve_shutdown(void) void fserve_shutdown(void)
{ {
if(!run_fserv) thread_mutex_lock (&pending_lock);
return;
run_fserv = 0; run_fserv = 0;
thread_join(fserv_thread); while (pending_list)
INFO0("file serving thread stopped"); {
fserve_t *to_go = (fserve_t *)pending_list;
pending_list = to_go->next;
fserve_client_destroy (to_go);
}
while (active_list)
{
fserve_t *to_go = active_list;
active_list = to_go->next;
fserve_client_destroy (to_go);
}
if (mimetypes) if (mimetypes)
avl_tree_free (mimetypes, _delete_mapping); avl_tree_free (mimetypes, _delete_mapping);
thread_mutex_unlock (&pending_lock);
thread_mutex_destroy (&pending_lock);
INFO0("file serving stopped");
} }
#ifdef HAVE_POLL #ifdef HAVE_POLL
...@@ -142,7 +154,12 @@ int fserve_client_waiting (void) ...@@ -142,7 +154,12 @@ int fserve_client_waiting (void)
} }
} }
if (!ufds) if (!ufds)
thread_sleep(200000); {
thread_mutex_lock (&pending_lock);
run_fserv = 0;
thread_mutex_unlock (&pending_lock);
return -1;
}
else if (poll(ufds, fserve_clients, 200) > 0) else if (poll(ufds, fserve_clients, 200) > 0)
{ {
/* mark any clients that are ready */ /* mark any clients that are ready */
...@@ -178,7 +195,12 @@ int fserve_client_waiting (void) ...@@ -178,7 +195,12 @@ int fserve_client_waiting (void)
} }
/* hack for windows, select needs at least 1 descriptor */ /* hack for windows, select needs at least 1 descriptor */
if (fd_max == SOCK_ERROR) if (fd_max == SOCK_ERROR)
thread_sleep (200000); {
thread_mutex_lock (&pending_lock);
run_fserv = 0;
thread_mutex_unlock (&pending_lock);
return -1;
}
else else
{ {
struct timeval tv; struct timeval tv;
...@@ -204,8 +226,10 @@ int fserve_client_waiting (void) ...@@ -204,8 +226,10 @@ int fserve_client_waiting (void)
} }
#endif #endif
static void wait_for_fds(void) { static int wait_for_fds(void)
{
fserve_t *fclient; fserve_t *fclient;
int ret;
while (run_fserv) while (run_fserv)
{ {
...@@ -228,9 +252,11 @@ static void wait_for_fds(void) { ...@@ -228,9 +252,11 @@ static void wait_for_fds(void) {
thread_mutex_unlock (&pending_lock); thread_mutex_unlock (&pending_lock);
} }
/* drop out of here if someone is ready */ /* drop out of here if someone is ready */
if (fserve_client_waiting()) ret = fserve_client_waiting();
break; if (ret)
return ret;
} }
return -1;
} }
static void *fserv_thread_function(void *arg) static void *fserv_thread_function(void *arg)
...@@ -238,9 +264,10 @@ static void *fserv_thread_function(void *arg) ...@@ -238,9 +264,10 @@ static void *fserv_thread_function(void *arg)
fserve_t *fclient, **trail; fserve_t *fclient, **trail;
size_t bytes; size_t bytes;
INFO0("file serving thread started"); while (1)
while (run_fserv) { {
wait_for_fds(); if (wait_for_fds() < 0)
break;
fclient = active_list; fclient = active_list;
trail = &active_list; trail = &active_list;
...@@ -515,7 +542,7 @@ int fserve_client_create (client_t *httpclient, const char *path) ...@@ -515,7 +542,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
if (range != NULL) { if (range != NULL) {
ret = 0; ret = 0;
if (strncasecmp (range, "bytes=", 6) == 0) if (strncasecmp (range, "bytes=", 6) == 0)
ret = sscanf (range+6, "%" SCNdMAX "-", &rangenumber); ret = sscanf (range+6, "%" SCN_OFF_T "-", &rangenumber);
if (ret != 1) { if (ret != 1) {
/* format not correct, so lets just assume /* format not correct, so lets just assume
...@@ -557,9 +584,9 @@ int fserve_client_create (client_t *httpclient, const char *path) ...@@ -557,9 +584,9 @@ int fserve_client_create (client_t *httpclient, const char *path)
"HTTP/1.1 206 Partial Content\r\n" "HTTP/1.1 206 Partial Content\r\n"
"Date: %s\r\n" "Date: %s\r\n"
"Accept-Ranges: bytes\r\n" "Accept-Ranges: bytes\r\n"
"Content-Length: %" PRIdMAX "\r\n" "Content-Length: %" PRI_OFF_T "\r\n"
"Content-Range: bytes %" PRIdMAX \ "Content-Range: bytes %" PRI_OFF_T \
"-%" PRIdMAX "/%" PRIdMAX "\r\n" "-%" PRI_OFF_T "/%" PRI_OFF_T "\r\n"
"Content-Type: %s\r\n\r\n", "Content-Type: %s\r\n\r\n",
currenttime, currenttime,
new_content_len, new_content_len,
...@@ -583,7 +610,7 @@ int fserve_client_create (client_t *httpclient, const char *path) ...@@ -583,7 +610,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
bytes = snprintf (httpclient->refbuf->data, BUFSIZE, bytes = snprintf (httpclient->refbuf->data, BUFSIZE,
"HTTP/1.0 200 OK\r\n" "HTTP/1.0 200 OK\r\n"
"Accept-Ranges: bytes\r\n" "Accept-Ranges: bytes\r\n"
"Content-Length: %" PRIdMAX "\r\n" "Content-Length: %" PRI_OFF_T "\r\n"
"Content-Type: %s\r\n\r\n", "Content-Type: %s\r\n\r\n",
content_length, content_length,
type); type);
...@@ -607,6 +634,24 @@ fail: ...@@ -607,6 +634,24 @@ fail:
} }
/* Routine to actually add pre-configured client structure to pending list and
* then to start off the file serving thread if it is not already running
*/
static void fserve_add_pending (fserve_t *fclient)
{
thread_mutex_lock (&pending_lock);
fclient->next = (fserve_t *)pending_list;
pending_list = fclient;
if (run_fserv == 0)
{
run_fserv = 1;
DEBUG0 ("fserve handler waking up");
thread_create("File Serving Thread", fserv_thread_function, NULL, THREAD_DETACHED);
}
thread_mutex_unlock (&pending_lock);
}
/* Add client to fserve thread, client needs to have refbuf set and filled /* Add client to fserve thread, client needs to have refbuf set and filled
* but may provide a NULL file if no data needs to be read * but may provide a NULL file if no data needs to be read
*/ */
...@@ -623,11 +668,7 @@ int fserve_add_client (client_t *client, FILE *file) ...@@ -623,11 +668,7 @@ int fserve_add_client (client_t *client, FILE *file)
fclient->file = file; fclient->file = file;
fclient->client = client; fclient->client = client;
fclient->ready = 0; fclient->ready = 0;
fserve_add_pending (fclient);
thread_mutex_lock (&pending_lock);
fclient->next = (fserve_t *)pending_list;
pending_list = fclient;
thread_mutex_unlock (&pending_lock);
return 0; return 0;
} }
...@@ -652,10 +693,7 @@ void fserve_add_client_callback (client_t *client, fserve_callback_t callback, v ...@@ -652,10 +693,7 @@ void fserve_add_client_callback (client_t *client, fserve_callback_t callback, v
fclient->callback = callback; fclient->callback = callback;
fclient->arg = arg; fclient->arg = arg;
thread_mutex_lock (&pending_lock); fserve_add_pending (fclient);
fclient->next = (fserve_t *)pending_list;
pending_list = fclient;
thread_mutex_unlock (&pending_lock);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment