mirror of https://git.kore.io/kore.git
Add HTTP runlocks.
A way to serialize access to HTTP page handlers in case you are using some asynchronous api such as pgsql or libcurl stuff.
This commit is contained in:
parent
1686ec22e6
commit
a4d18ca276
|
@ -71,6 +71,16 @@ extern "C" {
|
||||||
#define HTTP_STATE_COMPLETE 2
|
#define HTTP_STATE_COMPLETE 2
|
||||||
#define HTTP_STATE_RETRY 3
|
#define HTTP_STATE_RETRY 3
|
||||||
|
|
||||||
|
struct http_runlock_queue {
|
||||||
|
struct http_request *req;
|
||||||
|
LIST_ENTRY(http_runlock_queue) list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct http_runlock {
|
||||||
|
struct http_request *owner;
|
||||||
|
LIST_HEAD(, http_runlock_queue) queue;
|
||||||
|
};
|
||||||
|
|
||||||
struct http_header {
|
struct http_header {
|
||||||
char *header;
|
char *header;
|
||||||
char *value;
|
char *value;
|
||||||
|
@ -249,6 +259,7 @@ struct http_request {
|
||||||
size_t state_len;
|
size_t state_len;
|
||||||
char *query_string;
|
char *query_string;
|
||||||
struct kore_module_handle *hdlr;
|
struct kore_module_handle *hdlr;
|
||||||
|
struct http_runlock_queue *runlock;
|
||||||
void (*onfree)(struct http_request *);
|
void (*onfree)(struct http_request *);
|
||||||
|
|
||||||
#if defined(KORE_USE_PYTHON)
|
#if defined(KORE_USE_PYTHON)
|
||||||
|
@ -345,6 +356,12 @@ void http_response_cookie(struct http_request *, const char *,
|
||||||
const char *, const char *, time_t, u_int32_t,
|
const char *, const char *, time_t, u_int32_t,
|
||||||
struct http_cookie **);
|
struct http_cookie **);
|
||||||
|
|
||||||
|
void http_runlock_init(struct http_runlock *);
|
||||||
|
void http_runlock_release(struct http_runlock *,
|
||||||
|
struct http_request *);
|
||||||
|
int http_runlock_acquire(struct http_runlock *,
|
||||||
|
struct http_request *);
|
||||||
|
|
||||||
const char *http_media_type(const char *);
|
const char *http_media_type(const char *);
|
||||||
void *http_state_get(struct http_request *);
|
void *http_state_get(struct http_request *);
|
||||||
int http_state_exists(struct http_request *);
|
int http_state_exists(struct http_request *);
|
||||||
|
|
58
src/http.c
58
src/http.c
|
@ -149,6 +149,7 @@ static LIST_HEAD(, http_media_type) http_media_types;
|
||||||
static struct kore_pool http_request_pool;
|
static struct kore_pool http_request_pool;
|
||||||
static struct kore_pool http_cookie_pool;
|
static struct kore_pool http_cookie_pool;
|
||||||
static struct kore_pool http_body_path;
|
static struct kore_pool http_body_path;
|
||||||
|
static struct kore_pool http_rlq_pool;
|
||||||
|
|
||||||
struct kore_pool http_header_pool;
|
struct kore_pool http_header_pool;
|
||||||
|
|
||||||
|
@ -196,6 +197,8 @@ http_init(void)
|
||||||
sizeof(struct http_header), prealloc * HTTP_REQ_HEADER_MAX);
|
sizeof(struct http_header), prealloc * HTTP_REQ_HEADER_MAX);
|
||||||
kore_pool_init(&http_cookie_pool, "http_cookie_pool",
|
kore_pool_init(&http_cookie_pool, "http_cookie_pool",
|
||||||
sizeof(struct http_cookie), prealloc * HTTP_MAX_COOKIES);
|
sizeof(struct http_cookie), prealloc * HTTP_MAX_COOKIES);
|
||||||
|
kore_pool_init(&http_rlq_pool, "http_rlq_pool",
|
||||||
|
sizeof(struct http_runlock_queue), http_request_limit);
|
||||||
|
|
||||||
kore_pool_init(&http_body_path,
|
kore_pool_init(&http_body_path,
|
||||||
"http_body_path", HTTP_BODY_PATH_MAX, prealloc);
|
"http_body_path", HTTP_BODY_PATH_MAX, prealloc);
|
||||||
|
@ -412,6 +415,11 @@ http_request_free(struct http_request *req)
|
||||||
if (req->onfree != NULL)
|
if (req->onfree != NULL)
|
||||||
req->onfree(req);
|
req->onfree(req);
|
||||||
|
|
||||||
|
if (req->runlock != NULL) {
|
||||||
|
LIST_REMOVE(req->runlock, list);
|
||||||
|
req->runlock = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(KORE_USE_TASKS)
|
#if defined(KORE_USE_TASKS)
|
||||||
pending_tasks = 0;
|
pending_tasks = 0;
|
||||||
for (t = LIST_FIRST(&(req->tasks)); t != NULL; t = nt) {
|
for (t = LIST_FIRST(&(req->tasks)); t != NULL; t = nt) {
|
||||||
|
@ -1420,6 +1428,55 @@ http_start_recv(struct connection *c)
|
||||||
(void)net_recv_flush(c);
|
(void)net_recv_flush(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
http_runlock_init(struct http_runlock *lock)
|
||||||
|
{
|
||||||
|
lock->owner = NULL;
|
||||||
|
LIST_INIT(&lock->queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
http_runlock_acquire(struct http_runlock *lock, struct http_request *req)
|
||||||
|
{
|
||||||
|
if (lock->owner != NULL) {
|
||||||
|
if (req->runlock != NULL)
|
||||||
|
fatal("%s: request already waiting on lock", __func__);
|
||||||
|
|
||||||
|
req->runlock = kore_pool_get(&http_rlq_pool);
|
||||||
|
req->runlock->req = req;
|
||||||
|
LIST_INSERT_HEAD(&lock->queue, req->runlock, list);
|
||||||
|
|
||||||
|
http_request_sleep(req);
|
||||||
|
return (KORE_RESULT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
lock->owner = req;
|
||||||
|
|
||||||
|
return (KORE_RESULT_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
http_runlock_release(struct http_runlock *lock, struct http_request *req)
|
||||||
|
{
|
||||||
|
struct http_runlock_queue *next;
|
||||||
|
struct http_request *nextreq;
|
||||||
|
|
||||||
|
if (lock->owner != req)
|
||||||
|
fatal("%s: calling request != owner of runlock", __func__);
|
||||||
|
|
||||||
|
lock->owner = NULL;
|
||||||
|
|
||||||
|
if ((next = LIST_FIRST(&lock->queue)) != NULL) {
|
||||||
|
LIST_REMOVE(next, list);
|
||||||
|
|
||||||
|
nextreq = next->req;
|
||||||
|
nextreq->runlock = NULL;
|
||||||
|
|
||||||
|
http_request_wakeup(nextreq);
|
||||||
|
kore_pool_put(&http_rlq_pool, next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct http_request *
|
static struct http_request *
|
||||||
http_request_new(struct connection *c, const char *host,
|
http_request_new(struct connection *c, const char *host,
|
||||||
const char *method, char *path, const char *version)
|
const char *method, char *path, const char *version)
|
||||||
|
@ -1549,6 +1606,7 @@ http_request_new(struct connection *c, const char *host,
|
||||||
req->agent = NULL;
|
req->agent = NULL;
|
||||||
req->onfree = NULL;
|
req->onfree = NULL;
|
||||||
req->referer = NULL;
|
req->referer = NULL;
|
||||||
|
req->runlock = NULL;
|
||||||
req->flags = flags;
|
req->flags = flags;
|
||||||
req->fsm_state = 0;
|
req->fsm_state = 0;
|
||||||
req->http_body = NULL;
|
req->http_body = NULL;
|
||||||
|
|
Loading…
Reference in New Issue