Introduce http_request_sleep() and http_request_wakeup().

These 2 functions can be used to move an HTTP request
from/to the active http_requests list. Effectively
putting them to "sleep" or "waking them up".

Sprinkle this through the pgsql and task code.

If used correctly greatly reduces overhead for
managing sleeping tasks.
This commit is contained in:
Joris Vink 2014-07-04 16:51:19 +02:00
parent 7b6c03ca5b
commit 19d146a09e
5 changed files with 40 additions and 8 deletions

View File

@ -163,6 +163,8 @@ void http_init(void);
void http_process(void);
time_t http_date_to_time(char *);
void http_request_free(struct http_request *);
void http_request_sleep(struct http_request *);
void http_request_wakeup(struct http_request *);
void http_process_request(struct http_request *, int);
void http_response(struct http_request *, int, void *, u_int32_t);
int http_request_header_get(struct http_request *, char *, char **);

View File

@ -252,6 +252,7 @@ kore_connection_remove(struct connection *c)
for (req = TAILQ_FIRST(&(c->http_requests)); req != NULL; req = rnext) {
rnext = TAILQ_NEXT(req, olist);
req->flags |= HTTP_REQUEST_DELETE;
http_request_wakeup(req);
TAILQ_REMOVE(&(c->http_requests), req, olist);
}

View File

@ -47,6 +47,7 @@ static void http_response_spdy(struct http_request *,
struct connection *, int, void *, u_int32_t);
static TAILQ_HEAD(, http_request) http_requests;
static TAILQ_HEAD(, http_request) http_requests_sleeping;
static struct kore_pool http_request_pool;
static struct kore_pool http_header_pool;
@ -61,6 +62,7 @@ http_init(void)
{
http_request_count = 0;
TAILQ_INIT(&http_requests);
TAILQ_INIT(&http_requests_sleeping);
kore_pool_init(&http_request_pool, "http_request_pool",
sizeof(struct http_request), worker_max_connections);
@ -155,6 +157,30 @@ http_request_new(struct connection *c, struct spdy_stream *s, char *host,
return (KORE_RESULT_OK);
}
void
http_request_sleep(struct http_request *req)
{
if (!(req->flags & HTTP_REQUEST_SLEEPING)) {
kore_debug("http_request_sleep: %p napping", req);
req->flags |= HTTP_REQUEST_SLEEPING;
TAILQ_REMOVE(&http_requests, req, list);
TAILQ_INSERT_TAIL(&http_requests_sleeping, req, list);
}
}
void
http_request_wakeup(struct http_request *req)
{
if (req->flags & HTTP_REQUEST_SLEEPING) {
kore_debug("http_request_wakeup: %p woke up", req);
req->flags &= ~HTTP_REQUEST_SLEEPING;
TAILQ_REMOVE(&http_requests_sleeping, req, list);
TAILQ_INSERT_TAIL(&http_requests, req, list);
}
}
void
http_process(void)
{
@ -168,8 +194,9 @@ http_process(void)
continue;
}
/* Sleeping requests should be in http_requests_sleeping. */
if (req->flags & HTTP_REQUEST_SLEEPING)
continue;
fatal("http_process: sleeping request on list");
if (!(req->flags & HTTP_REQUEST_COMPLETE))
continue;

View File

@ -89,7 +89,7 @@ kore_pgsql_query(struct http_request *req, char *query, int idx)
return (KORE_RESULT_ERROR);
}
req->flags |= HTTP_REQUEST_SLEEPING;
http_request_sleep(req);
conn = TAILQ_FIRST(&pgsql_conn_free);
if (!(conn->flags & PGSQL_CONN_FREE))
fatal("received a pgsql conn that was not free?");
@ -145,9 +145,9 @@ kore_pgsql_handle(void *c, int err)
}
if (req->pgsql[i]->state == KORE_PGSQL_STATE_WAIT) {
req->flags |= HTTP_REQUEST_SLEEPING;
http_request_sleep(req);
} else {
req->flags &= ~HTTP_REQUEST_SLEEPING;
http_request_wakeup(req);
http_process_request(req, 1);
}
}
@ -175,8 +175,8 @@ kore_pgsql_continue(struct http_request *req, int i)
case KORE_PGSQL_STATE_WAIT:
break;
case KORE_PGSQL_STATE_DONE:
http_request_wakeup(req);
req->pgsql[i]->conn = NULL;
req->flags &= ~HTTP_REQUEST_SLEEPING;
req->pgsql[i]->state = KORE_PGSQL_STATE_COMPLETE;
kore_mem_free(conn->job->query);
@ -292,11 +292,11 @@ pgsql_conn_cleanup(struct pgsql_conn *conn)
if (conn->job) {
i = conn->job->idx;
req = conn->job->req;
http_request_wakeup(req);
req->pgsql[i]->conn = NULL;
req->pgsql[i]->state = KORE_PGSQL_STATE_ERROR;
req->pgsql[i]->error = kore_strdup(PQerrorMessage(conn->db));
req->flags &= ~HTTP_REQUEST_SLEEPING;
kore_mem_free(conn->job->query);
kore_mem_free(conn->job);

View File

@ -102,8 +102,8 @@ kore_task_bind_request(struct kore_task *t, struct http_request *req)
t->req = req;
req->task = t;
req->flags |= HTTP_REQUEST_SLEEPING;
http_request_sleep(req);
kore_platform_schedule_read(t->fds[0], t);
}
@ -173,10 +173,12 @@ kore_task_handle(struct kore_task *t, int finished)
{
kore_debug("kore_task_handle: %p, %d", t, finished);
if (t->req != NULL)
http_request_wakeup(t->req);
if (finished) {
kore_task_set_state(t, KORE_TASK_STATE_FINISHED);
if (t->req != NULL) {
t->req->flags &= ~HTTP_REQUEST_SLEEPING;
if (t->req->flags & HTTP_REQUEST_DELETE)
kore_task_destroy(t);
}