|
@@ -71,8 +71,9 @@ static gearman_server_con_st * _server_con_create(gearman_server_thread_st *thre
|
|
|
return NULL;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
assert(con);
|
|
|
- if (!con)
|
|
|
+ if (con == NULL)
|
|
|
{
|
|
|
gearmand_error("Neigther an allocated gearman_server_con_st() or free listed could be found");
|
|
|
*ret= GEARMAN_MEMORY_ALLOCATION_FAILURE;
|
|
@@ -112,6 +113,7 @@ static gearman_server_con_st * _server_con_create(gearman_server_thread_st *thre
|
|
|
con->_host= dcon->host;
|
|
|
con->_port= dcon->port;
|
|
|
strcpy(con->id, "-");
|
|
|
+ con->timeout_event= NULL;
|
|
|
|
|
|
con->protocol.context= NULL;
|
|
|
con->protocol.context_free_fn= NULL;
|
|
@@ -203,6 +205,11 @@ void gearman_server_con_free(gearman_server_con_st *con)
|
|
|
gearman_server_client_free(con->client_list);
|
|
|
}
|
|
|
|
|
|
+ if (con->timeout_event != NULL)
|
|
|
+ {
|
|
|
+ event_del(con->timeout_event);
|
|
|
+ }
|
|
|
+
|
|
|
(void) pthread_mutex_lock(&thread->lock);
|
|
|
GEARMAN_LIST_DEL(con->thread->con, con,)
|
|
|
(void) pthread_mutex_unlock(&thread->lock);
|
|
@@ -237,7 +244,9 @@ void gearman_server_con_set_id(gearman_server_con_st *con, char *id,
|
|
|
size_t size)
|
|
|
{
|
|
|
if (size >= GEARMAN_SERVER_CON_ID_SIZE)
|
|
|
+ {
|
|
|
size= GEARMAN_SERVER_CON_ID_SIZE - 1;
|
|
|
+ }
|
|
|
|
|
|
memcpy(con->id, id, size);
|
|
|
con->id[size]= 0;
|
|
@@ -260,9 +269,13 @@ void gearman_server_con_free_worker(gearman_server_con_st *con,
|
|
|
|
|
|
/* Set worker to the last kept worker, or the beginning of the list. */
|
|
|
if (prev_worker == NULL)
|
|
|
+ {
|
|
|
worker= con->worker_list;
|
|
|
+ }
|
|
|
else
|
|
|
+ {
|
|
|
worker= prev_worker;
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -276,13 +289,17 @@ void gearman_server_con_free_worker(gearman_server_con_st *con,
|
|
|
void gearman_server_con_free_workers(gearman_server_con_st *con)
|
|
|
{
|
|
|
while (con->worker_list != NULL)
|
|
|
+ {
|
|
|
gearman_server_worker_free(con->worker_list);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void gearman_server_con_io_add(gearman_server_con_st *con)
|
|
|
{
|
|
|
if (con->io_list)
|
|
|
+ {
|
|
|
return;
|
|
|
+ }
|
|
|
|
|
|
(void) pthread_mutex_lock(&con->thread->lock);
|
|
|
|
|
@@ -318,7 +335,9 @@ gearman_server_con_io_next(gearman_server_thread_st *thread)
|
|
|
gearman_server_con_st *con= thread->io_list;
|
|
|
|
|
|
if (con == NULL)
|
|
|
+ {
|
|
|
return NULL;
|
|
|
+ }
|
|
|
|
|
|
gearman_server_con_io_remove(con);
|
|
|
|
|
@@ -328,7 +347,9 @@ gearman_server_con_io_next(gearman_server_thread_st *thread)
|
|
|
void gearman_server_con_proc_add(gearman_server_con_st *con)
|
|
|
{
|
|
|
if (con->proc_list)
|
|
|
+ {
|
|
|
return;
|
|
|
+ }
|
|
|
|
|
|
(void) pthread_mutex_lock(&con->thread->lock);
|
|
|
GEARMAN_LIST_ADD(con->thread->proc, con, proc_)
|
|
@@ -359,20 +380,22 @@ void gearman_server_con_proc_remove(gearman_server_con_st *con)
|
|
|
gearman_server_con_st *
|
|
|
gearman_server_con_proc_next(gearman_server_thread_st *thread)
|
|
|
{
|
|
|
- gearman_server_con_st *con;
|
|
|
-
|
|
|
if (thread->proc_list == NULL)
|
|
|
+ {
|
|
|
return NULL;
|
|
|
+ }
|
|
|
|
|
|
(void) pthread_mutex_lock(&thread->lock);
|
|
|
|
|
|
- con= thread->proc_list;
|
|
|
+ gearman_server_con_st *con= thread->proc_list;
|
|
|
while (con != NULL)
|
|
|
{
|
|
|
GEARMAN_LIST_DEL(thread->proc, con, proc_)
|
|
|
con->proc_list= false;
|
|
|
if (!(con->proc_removed))
|
|
|
+ {
|
|
|
break;
|
|
|
+ }
|
|
|
con= thread->proc_list;
|
|
|
}
|
|
|
|
|
@@ -397,5 +420,78 @@ void *gearmand_connection_protocol_context(const gearman_server_con_st *connecti
|
|
|
return connection->protocol.context;
|
|
|
}
|
|
|
|
|
|
+static void _server_job_timeout(int fd, short event, void *arg)
|
|
|
+{
|
|
|
+ gearman_server_job_st *job= (gearman_server_job_st *)arg;
|
|
|
+
|
|
|
+ fd= fd;
|
|
|
+ event= event;
|
|
|
+
|
|
|
+ /* A timeout has ocurred on a job, re-queue it */
|
|
|
+ gearmand_log_debug(GEARMAN_DEFAULT_LOG_PARAM,
|
|
|
+ "Worker timeout reached on job, requeueing: %s %s",
|
|
|
+ job->job_handle, job->unique);
|
|
|
|
|
|
+ gearmand_error_t ret= gearman_server_job_queue(job);
|
|
|
+ if (ret != GEARMAN_SUCCESS)
|
|
|
+ {
|
|
|
+ gearmand_log_error(GEARMAN_DEFAULT_LOG_PARAM,
|
|
|
+ "Failed trying to requeue job after timeout, job lost: %s %s",
|
|
|
+ job->job_handle, job->unique);
|
|
|
+ gearman_server_job_free(job);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+gearmand_error_t gearman_server_con_add_job_timeout(gearman_server_con_st *con, gearman_server_job_st *job)
|
|
|
+{
|
|
|
+ if (job)
|
|
|
+ {
|
|
|
+ gearman_server_worker_st *worker= con->worker_list;
|
|
|
+ for (worker= con->worker_list; worker != NULL; worker= worker->con_next)
|
|
|
+ {
|
|
|
+ /* Assumes the functions are always fetched from the same server structure */
|
|
|
+ if (worker->function == job->function)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ /* It makes no sense to add a timeout to a connection that has no workers for a job */
|
|
|
+ assert(worker);
|
|
|
+
|
|
|
+ if (worker && worker->timeout)
|
|
|
+ {
|
|
|
+ if (! con->timeout_event)
|
|
|
+ {
|
|
|
+ gearmand_con_st *dcon;
|
|
|
+ dcon= (gearmand_con_st *)con->con.context;
|
|
|
+ con->timeout_event= (struct event *)malloc(sizeof(struct event));
|
|
|
+ if (con->timeout_event == NULL)
|
|
|
+ {
|
|
|
+ return GEARMAN_MEMORY_ALLOCATION_FAILURE;
|
|
|
+ }
|
|
|
+ timeout_set(con->timeout_event, _server_job_timeout, job);
|
|
|
+ event_base_set(dcon->thread->base, con->timeout_event);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* XXX Right now, if a worker has diff timeouts for functions I think
|
|
|
+ this will overwrite any existing timeouts on that event. One
|
|
|
+ solution to that would be to record the timeout from last time,
|
|
|
+ and only set this one if it is longer than that one. */
|
|
|
+
|
|
|
+ struct timeval timeout_tv = { 0 , 0 };
|
|
|
+ timeout_tv.tv_sec= worker->timeout;
|
|
|
+ timeout_add(con->timeout_event, &timeout_tv);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return GEARMAN_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+void gearman_server_con_delete_timeout(gearman_server_con_st *con)
|
|
|
+{
|
|
|
+ if (con->timeout_event)
|
|
|
+ {
|
|
|
+ timeout_del(con->timeout_event);
|
|
|
+ con->timeout_event= NULL;
|
|
|
+ }
|
|
|
+}
|