(task_http) Disallow same-file concurrent downloads

This commit is contained in:
Higor Eurípedes 2015-11-30 11:36:53 -03:00
parent 4e0a4150b5
commit f84bea4302
5 changed files with 78 additions and 6 deletions

View File

@ -36,6 +36,8 @@ bool net_http_connection_done(struct http_connection_t *conn);
void net_http_connection_free(struct http_connection_t *conn);
const char *net_http_connection_url(struct http_connection_t *conn);
struct http_t *net_http_new(struct http_connection_t *conn);
/* You can use this to call net_http_update

View File

@ -260,6 +260,11 @@ void net_http_connection_free(struct http_connection_t *conn)
free(conn);
}
const char *net_http_connection_url(struct http_connection_t *conn)
{
return conn->urlcopy;
}
struct http_t *net_http_new(struct http_connection_t *conn)
{
bool error;

View File

@ -193,6 +193,18 @@ task_finished:
free(http);
}
static bool rarch_task_http_finder(rarch_task_t *task, void *user_data)
{
http_handle_t *http = (http_handle_t*)task->state;
const char *handle_url;
if (task->handler != rarch_task_http_transfer_handler)
return false;
handle_url = net_http_connection_url(http->connection.handle);
return strcmp(handle_url, (const char*)user_data) == 0;
}
bool rarch_task_push_http_transfer(const char *url, const char *type, rarch_task_callback_t cb, void *user_data)
{
rarch_task_t *t;
@ -203,6 +215,13 @@ bool rarch_task_push_http_transfer(const char *url, const char *type, rarch_task
if (!url || !*url)
return false;
/* Concurrent download of the same file is not allowed */
if (rarch_task_find(rarch_task_http_finder, (void*)url))
{
RARCH_LOG("%s is already being downloaded.\n", url);
return false;
}
conn = net_http_connection_new(url);
if (!conn)

View File

@ -17,9 +17,10 @@ typedef struct {
struct rarch_task_impl {
void (*push_running)(rarch_task_t *);
void (*cancel)(void);
void (*reset)(void);
void (*wait)(void);
void (*gather)(void);
bool (*find)(rarch_task_finder_t, void*);
void (*init)(void);
void (*deinit)(void);
};
@ -132,7 +133,7 @@ static void regular_wait(void)
regular_gather();
}
static void regular_cancel()
static void regular_reset()
{
rarch_task_t *task;
@ -148,11 +149,25 @@ static void regular_deinit(void)
{
}
static bool regular_find(rarch_task_finder_t func, void *user_data)
{
rarch_task_t *task;
for (task = tasks_running.front; task; task = task->next)
{
if (func(task, user_data))
return true;
}
return false;
}
static struct rarch_task_impl impl_regular = {
regular_push_running,
regular_cancel,
regular_reset,
regular_wait,
regular_gather,
regular_find,
regular_init,
regular_deinit
};
@ -199,7 +214,7 @@ static void threaded_wait(void)
} while (wait);
}
static void threaded_cancel(void)
static void threaded_reset(void)
{
rarch_task_t *task;
@ -262,6 +277,21 @@ static void threaded_worker(void *userdata)
slock_unlock(running_lock);
}
static bool threaded_find(rarch_task_finder_t func, void *user_data)
{
rarch_task_t *task;
slock_lock(running_lock);
for (task = tasks_running.front; task; task = task->next)
{
if (func(task, user_data))
return true;
}
slock_unlock(running_lock);
return false;
}
static void threaded_init(void)
{
running_lock = slock_new();
@ -296,9 +326,10 @@ static void threaded_deinit(void)
static struct rarch_task_impl impl_threaded = {
threaded_push_running,
threaded_cancel,
threaded_reset,
threaded_wait,
threaded_gather,
threaded_find,
threaded_init,
threaded_deinit
};
@ -358,5 +389,10 @@ void rarch_task_wait(void)
void rarch_task_reset(void)
{
impl_current->cancel();
impl_current->reset();
}
bool rarch_task_find(rarch_task_finder_t func, void *user_data)
{
return impl_current->find(func, user_data);
}

View File

@ -32,6 +32,7 @@ extern "C" {
typedef struct rarch_task rarch_task_t;
typedef void (*rarch_task_callback_t)(void *task_data, void *user_data, const char *error);
typedef void (*rarch_task_handler_t)(rarch_task_t *task);
typedef bool (*rarch_task_finder_t)(rarch_task_t *task, void *user_data);
struct rarch_task {
rarch_task_handler_t handler;
@ -107,6 +108,15 @@ void rarch_task_reset(void);
*/
void rarch_task_wait(void);
/**
* @brief Calls func for every running task until it returns true.
*
* @param func
* @param user_data
* @return a task or NULL if not found.
*/
bool rarch_task_find(rarch_task_finder_t func, void *user_data);
/**
* @brief Pushes a task
*