mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-02-08 08:51:50 +00:00
add prefetch API to mod_http_cache
This commit is contained in:
parent
5783078401
commit
b55a6b158f
@ -40,6 +40,7 @@ SWITCH_STANDARD_API(http_cache_get);
|
|||||||
SWITCH_STANDARD_API(http_cache_put);
|
SWITCH_STANDARD_API(http_cache_put);
|
||||||
SWITCH_STANDARD_API(http_cache_tryget);
|
SWITCH_STANDARD_API(http_cache_tryget);
|
||||||
SWITCH_STANDARD_API(http_cache_clear);
|
SWITCH_STANDARD_API(http_cache_clear);
|
||||||
|
SWITCH_STANDARD_API(http_cache_prefetch);
|
||||||
|
|
||||||
#define DOWNLOAD_NEEDED "download"
|
#define DOWNLOAD_NEEDED "download"
|
||||||
|
|
||||||
@ -148,6 +149,16 @@ struct url_cache {
|
|||||||
int misses;
|
int misses;
|
||||||
/** Number of cache errors */
|
/** Number of cache errors */
|
||||||
int errors;
|
int errors;
|
||||||
|
/** The prefetch queue */
|
||||||
|
switch_queue_t *prefetch_queue;
|
||||||
|
/** Max size of prefetch queue */
|
||||||
|
int prefetch_queue_size;
|
||||||
|
/** Size of prefetch thread pool */
|
||||||
|
int prefetch_thread_count;
|
||||||
|
/** Shutdown flag */
|
||||||
|
int shutdown;
|
||||||
|
/** Synchronizes shutdown of cache */
|
||||||
|
switch_thread_rwlock_t *shutdown_lock;
|
||||||
};
|
};
|
||||||
static url_cache_t gcache;
|
static url_cache_t gcache;
|
||||||
|
|
||||||
@ -778,6 +789,48 @@ static void setup_dir(url_cache_t *cache)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int isUrl(const char *filename)
|
||||||
|
{
|
||||||
|
return !zstr(filename) && !strncmp("http://", filename, strlen("http://"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HTTP_PREFETCH_SYNTAX "<url>"
|
||||||
|
SWITCH_STANDARD_API(http_cache_prefetch)
|
||||||
|
{
|
||||||
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||||
|
switch_memory_pool_t *lpool = NULL;
|
||||||
|
switch_memory_pool_t *pool = NULL;
|
||||||
|
char *url;
|
||||||
|
|
||||||
|
if (!isUrl(cmd)) {
|
||||||
|
stream->write_function(stream, "USAGE: %s\n", HTTP_PREFETCH_SYNTAX);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
pool = switch_core_session_get_pool(session);
|
||||||
|
} else {
|
||||||
|
switch_core_new_memory_pool(&lpool);
|
||||||
|
pool = lpool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send to thread pool */
|
||||||
|
url = strdup(cmd);
|
||||||
|
if (switch_queue_trypush(gcache.prefetch_queue, url) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_safe_free(url);
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to queue prefetch request\n");
|
||||||
|
stream->write_function(stream, "-ERR\n");
|
||||||
|
} else {
|
||||||
|
stream->write_function(stream, "+OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lpool) {
|
||||||
|
switch_core_destroy_memory_pool(&lpool);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
#define HTTP_GET_SYNTAX "<url>"
|
#define HTTP_GET_SYNTAX "<url>"
|
||||||
/**
|
/**
|
||||||
* Get a file from the cache, download if it isn't cached
|
* Get a file from the cache, download if it isn't cached
|
||||||
@ -789,7 +842,7 @@ SWITCH_STANDARD_API(http_cache_get)
|
|||||||
switch_memory_pool_t *pool = NULL;
|
switch_memory_pool_t *pool = NULL;
|
||||||
char *filename;
|
char *filename;
|
||||||
|
|
||||||
if (zstr(cmd) || strncmp("http://", cmd, strlen("http://"))) {
|
if (!isUrl(cmd)) {
|
||||||
stream->write_function(stream, "USAGE: %s\n", HTTP_GET_SYNTAX);
|
stream->write_function(stream, "USAGE: %s\n", HTTP_GET_SYNTAX);
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -911,6 +964,44 @@ SWITCH_STANDARD_API(http_cache_clear)
|
|||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread to prefetch URLs
|
||||||
|
* @param thread the thread
|
||||||
|
* @param obj started flag
|
||||||
|
* @return NULL
|
||||||
|
*/
|
||||||
|
static void *SWITCH_THREAD_FUNC prefetch_thread(switch_thread_t *thread, void *obj)
|
||||||
|
{
|
||||||
|
int *started = obj;
|
||||||
|
void *url = NULL;
|
||||||
|
|
||||||
|
switch_thread_rwlock_rdlock(gcache.shutdown_lock);
|
||||||
|
*started = 1;
|
||||||
|
|
||||||
|
// process prefetch requests
|
||||||
|
while (!gcache.shutdown) {
|
||||||
|
if (switch_queue_pop(gcache.prefetch_queue, &url) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_stream_handle_t stream = { 0 };
|
||||||
|
SWITCH_STANDARD_STREAM(stream);
|
||||||
|
switch_api_execute("http_get", url, NULL, &stream);
|
||||||
|
switch_safe_free(stream.data);
|
||||||
|
switch_safe_free(url);
|
||||||
|
}
|
||||||
|
url = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// shutting down- clear the queue
|
||||||
|
while (switch_queue_trypop(gcache.prefetch_queue, &url) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_safe_free(url);
|
||||||
|
url = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_thread_rwlock_unlock(gcache.shutdown_lock);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the module
|
* Configure the module
|
||||||
* @param cache to configure
|
* @param cache to configure
|
||||||
@ -933,6 +1024,8 @@ static switch_status_t do_config(url_cache_t *cache)
|
|||||||
max_urls = 4000;
|
max_urls = 4000;
|
||||||
default_max_age_sec = 86400;
|
default_max_age_sec = 86400;
|
||||||
cache->location = SWITCH_PREFIX_DIR "/http_cache";
|
cache->location = SWITCH_PREFIX_DIR "/http_cache";
|
||||||
|
cache->prefetch_queue_size = 100;
|
||||||
|
cache->prefetch_thread_count = 8;
|
||||||
|
|
||||||
/* get params */
|
/* get params */
|
||||||
settings = switch_xml_child(cfg, "settings");
|
settings = switch_xml_child(cfg, "settings");
|
||||||
@ -949,6 +1042,12 @@ static switch_status_t do_config(url_cache_t *cache)
|
|||||||
} else if (!strcasecmp(var, "default-max-age")) {
|
} else if (!strcasecmp(var, "default-max-age")) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting default-max-age to %s\n", val);
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting default-max-age to %s\n", val);
|
||||||
default_max_age_sec = atoi(val);
|
default_max_age_sec = atoi(val);
|
||||||
|
} else if (!strcasecmp(var, "prefetch-queue-size")) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting prefetch-queue-size to %s\n", val);
|
||||||
|
cache->prefetch_queue_size = atoi(val);
|
||||||
|
} else if (!strcasecmp(var, "prefetch-thread-count")) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting prefetch-thread-count to %s\n", val);
|
||||||
|
cache->prefetch_thread_count = atoi(val);
|
||||||
} else {
|
} else {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported param: %s\n", var);
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported param: %s\n", var);
|
||||||
}
|
}
|
||||||
@ -971,6 +1070,16 @@ static switch_status_t do_config(url_cache_t *cache)
|
|||||||
status = SWITCH_STATUS_TERM;
|
status = SWITCH_STATUS_TERM;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (cache->prefetch_queue_size <= 0) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "prefetch-queue-size must be > 0\n");
|
||||||
|
status = SWITCH_STATUS_TERM;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (cache->prefetch_thread_count <= 0) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "prefetch-thread-count must be > 0\n");
|
||||||
|
status = SWITCH_STATUS_TERM;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
cache->max_url = max_urls;
|
cache->max_url = max_urls;
|
||||||
cache->default_max_age = (default_max_age_sec * 1000 * 1000); /* convert from seconds to nanoseconds */
|
cache->default_max_age = (default_max_age_sec * 1000 * 1000); /* convert from seconds to nanoseconds */
|
||||||
@ -992,6 +1101,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
|
|||||||
SWITCH_ADD_API(api, "http_tryget", "HTTP GET from cache only", http_cache_tryget, HTTP_GET_SYNTAX);
|
SWITCH_ADD_API(api, "http_tryget", "HTTP GET from cache only", http_cache_tryget, HTTP_GET_SYNTAX);
|
||||||
SWITCH_ADD_API(api, "http_put", "HTTP PUT", http_cache_put, HTTP_PUT_SYNTAX);
|
SWITCH_ADD_API(api, "http_put", "HTTP PUT", http_cache_put, HTTP_PUT_SYNTAX);
|
||||||
SWITCH_ADD_API(api, "http_clear_cache", "Clear the cache", http_cache_clear, HTTP_CACHE_CLEAR_SYNTAX);
|
SWITCH_ADD_API(api, "http_clear_cache", "Clear the cache", http_cache_clear, HTTP_CACHE_CLEAR_SYNTAX);
|
||||||
|
SWITCH_ADD_API(api, "http_prefetch", "Prefetch document in a background thread. Use http_get to get the prefetched document", http_cache_prefetch, HTTP_PREFETCH_SYNTAX);
|
||||||
|
|
||||||
memset(&gcache, 0, sizeof(url_cache_t));
|
memset(&gcache, 0, sizeof(url_cache_t));
|
||||||
gcache.pool = pool;
|
gcache.pool = pool;
|
||||||
@ -1002,6 +1112,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
|
|||||||
|
|
||||||
switch_core_hash_init(&gcache.map, gcache.pool);
|
switch_core_hash_init(&gcache.map, gcache.pool);
|
||||||
switch_mutex_init(&gcache.mutex, SWITCH_MUTEX_UNNESTED, gcache.pool);
|
switch_mutex_init(&gcache.mutex, SWITCH_MUTEX_UNNESTED, gcache.pool);
|
||||||
|
switch_thread_rwlock_create(&gcache.shutdown_lock, gcache.pool);
|
||||||
|
|
||||||
/* create the queue */
|
/* create the queue */
|
||||||
gcache.queue.max_size = gcache.max_url;
|
gcache.queue.max_size = gcache.max_url;
|
||||||
@ -1011,6 +1122,21 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
|
|||||||
|
|
||||||
setup_dir(&gcache);
|
setup_dir(&gcache);
|
||||||
|
|
||||||
|
/* Start the prefetch threads */
|
||||||
|
switch_queue_create(&gcache.prefetch_queue, gcache.prefetch_queue_size, gcache.pool);
|
||||||
|
for (int i = 0; i < gcache.prefetch_thread_count; i++) {
|
||||||
|
int started = 0;
|
||||||
|
switch_thread_t *thread;
|
||||||
|
switch_threadattr_t *thd_attr = NULL;
|
||||||
|
switch_threadattr_create(&thd_attr, gcache.pool);
|
||||||
|
switch_threadattr_detach_set(thd_attr, 1);
|
||||||
|
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
||||||
|
switch_thread_create(&thread, thd_attr, prefetch_thread, &started, gcache.pool);
|
||||||
|
while (!started) {
|
||||||
|
switch_sleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* indicate that the module should continue to be loaded */
|
/* indicate that the module should continue to be loaded */
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1020,6 +1146,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
|
|||||||
*/
|
*/
|
||||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_http_cache_shutdown)
|
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_http_cache_shutdown)
|
||||||
{
|
{
|
||||||
|
gcache.shutdown = 1;
|
||||||
|
switch_queue_interrupt_all(gcache.prefetch_queue);
|
||||||
|
switch_thread_rwlock_wrlock(gcache.shutdown_lock);
|
||||||
|
|
||||||
url_cache_clear(&gcache, NULL);
|
url_cache_clear(&gcache, NULL);
|
||||||
switch_core_hash_destroy(&gcache.map);
|
switch_core_hash_destroy(&gcache.map);
|
||||||
switch_mutex_destroy(gcache.mutex);
|
switch_mutex_destroy(gcache.mutex);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user