commit 19d146a09e3452453a681141c2c1a6c638d3cb30
parent 7b6c03ca5b6d6cc47d87788efba7bf91151fe647
Author: Joris Vink <joris@coders.se>
Date: Fri, 4 Jul 2014 16:51:19 +0200
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.
Diffstat:
5 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/includes/http.h b/includes/http.h
@@ -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 **);
diff --git a/src/connection.c b/src/connection.c
@@ -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);
}
diff --git a/src/http.c b/src/http.c
@@ -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);
@@ -156,6 +158,30 @@ http_request_new(struct connection *c, struct spdy_stream *s, char *host,
}
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)
{
struct http_request *req, *next;
@@ -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;
diff --git a/src/pgsql.c b/src/pgsql.c
@@ -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);
diff --git a/src/tasks.c b/src/tasks.c
@@ -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);
}