kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

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:
includes/http.h | 2++
src/connection.c | 1+
src/http.c | 29++++++++++++++++++++++++++++-
src/pgsql.c | 10+++++-----
src/tasks.c | 6++++--
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); }