diff --git a/Makefile b/Makefile index 45b934d0..a44ea402 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ OUT=turnip HIREDIS_OBJ=hiredis/hiredis.o hiredis/sds.o hiredis/net.o hiredis/async.o JANSSON_OBJ=jansson/src/dump.o jansson/src/error.o jansson/src/hashtable.o jansson/src/load.o jansson/src/strbuffer.o jansson/src/utf.o jansson/src/value.o jansson/src/variadic.o -OBJS=turnip.o conf.o json.o cmd.o $(HIREDIS_OBJ) $(JANSSON_OBJ) +OBJS=turnip.o conf.o json.o cmd.o server.o $(HIREDIS_OBJ) $(JANSSON_OBJ) CFLAGS=-O0 -ggdb -Wall -Wextra -I. -Ijansson/src LDFLAGS=-levent diff --git a/server.c b/server.c new file mode 100644 index 00000000..6d4e90d2 --- /dev/null +++ b/server.c @@ -0,0 +1,68 @@ +#include "server.h" +#include "conf.h" +#include "cmd.h" + +#include +#include +#include + +static void +connectCallback(const redisAsyncContext *c) { + ((void)c); + printf("connected...\n"); +} + +static void +disconnectCallback(const redisAsyncContext *c, int status) { + struct server *s = c->data; + if (status != REDIS_OK) { + printf("Error: %s\n", c->errstr); + } + printf("disconnected, schedule reconnect.\n"); + s->ac = NULL; + + turnip_connect(s); +} + +static void +on_timer_reconnect(int fd, short event, void *ctx) { + + (void)fd; + (void)event; + struct server *s = ctx; + + if(s->ac) { + redisLibeventCleanup(s->ac->_adapter_data); + } + + /* TODO: free AC. */ + + if(s->cfg->redis_host[0] == '/') { /* unix socket */ + s->ac = redisAsyncConnectUnix(s->cfg->redis_host); + } else { + s->ac = redisAsyncConnect(s->cfg->redis_host, s->cfg->redis_port); + } + + s->ac->data = s; + + if(s->ac->err) { + /* Let *c leak for now... */ + printf("Error: %s\n", s->ac->errstr); + } + + + redisLibeventAttach(s->ac, s->base); + redisAsyncSetConnectCallback(s->ac, connectCallback); + redisAsyncSetDisconnectCallback(s->ac, disconnectCallback); +} + +void +turnip_connect(struct server *s) { + /* schedule reconnect */ + evtimer_set(&s->ev_reconnect, on_timer_reconnect, s); + event_base_set(s->base, &s->ev_reconnect); + s->tv_reconnect.tv_sec = 1; + s->tv_reconnect.tv_usec = 0; + evtimer_add(&s->ev_reconnect, &s->tv_reconnect); +} + diff --git a/server.h b/server.h new file mode 100644 index 00000000..031f9fdd --- /dev/null +++ b/server.h @@ -0,0 +1,23 @@ +#ifndef TURNIP_H +#define TURNIP_H + +#include +#include +#include +#include + +struct server { + + struct conf *cfg; + struct event_base *base; + redisAsyncContext *ac; + + struct event ev_reconnect; + struct timeval tv_reconnect; +}; + +void +turnip_connect(struct server *s); + +#endif + diff --git a/turnip.c b/turnip.c index 5cb4180c..50342ed0 100644 --- a/turnip.c +++ b/turnip.c @@ -8,100 +8,29 @@ #include #include -#include -#include +#include "server.h" #include "conf.h" #include "cmd.h" -#include "turnip.h" - -struct turnip *__t = NULL; - -static void -connectCallback(const redisAsyncContext *c); - -static void -disconnectCallback(const redisAsyncContext *c, int status); - - -static void -reconnect(); - -static void -on_timer_reconnect(int fd, short event, void *ctx) { - - (void)fd; - (void)event; - (void)ctx; - - if(__t->ac) { - redisLibeventCleanup(__t->ac->_adapter_data); - } - - /* TODO: free AC. */ - - if(__t->cfg->redis_host[0] == '/') { /* unix socket */ - __t->ac = redisAsyncConnectUnix(__t->cfg->redis_host); - } else { - __t->ac = redisAsyncConnect(__t->cfg->redis_host, __t->cfg->redis_port); - } - if(__t->ac->err) { - /* Let *c leak for now... */ - printf("Error: %s\n", __t->ac->errstr); - } - - - redisLibeventAttach(__t->ac, __t->base); - redisAsyncSetConnectCallback(__t->ac, connectCallback); - redisAsyncSetDisconnectCallback(__t->ac, disconnectCallback); - -} - -static void -connectCallback(const redisAsyncContext *c) { - ((void)c); - printf("connected...\n"); -} - -static void -disconnectCallback(const redisAsyncContext *c, int status) { - if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); - } - printf("disconnected, schedule reconnect.\n"); - __t->ac = NULL; - - reconnect(); -} - -static void -reconnect() { - /* schedule reconnect */ - evtimer_set(&__t->ev_reconnect, on_timer_reconnect, NULL); - event_base_set(__t->base, &__t->ev_reconnect); - __t->tv_reconnect.tv_sec = 1; - __t->tv_reconnect.tv_usec = 0; - evtimer_add(&__t->ev_reconnect, &__t->tv_reconnect); -} void on_request(struct evhttp_request *rq, void *ctx) { const char *uri = evhttp_request_uri(rq); - (void)ctx; + struct server *s = ctx; - if(!__t->ac) { /* redis is unavailable */ + if(!s->ac) { /* redis is unavailable */ evhttp_send_reply(rq, 503, "Service Unavailable", NULL); return; } switch(rq->type) { case EVHTTP_REQ_GET: - cmd_run(__t->ac, rq, 1+uri, strlen(uri)-1); + cmd_run(s->ac, rq, 1+uri, strlen(uri)-1); break; case EVHTTP_REQ_POST: - cmd_run(__t->ac, rq, + cmd_run(s->ac, rq, (const char*)EVBUFFER_DATA(rq->input_buffer), EVBUFFER_LENGTH(rq->input_buffer)); break; @@ -117,11 +46,11 @@ main(int argc, char *argv[]) { (void)argc; (void)argv; - __t = calloc(1, sizeof(struct turnip)); - __t->base = event_base_new(); - struct evhttp *http = evhttp_new(__t->base); + struct server *s = calloc(1, sizeof(struct server)); + s->base = event_base_new(); + struct evhttp *http = evhttp_new(s->base); - __t->cfg = conf_read("turnip.conf"); + s->cfg = conf_read("turnip.conf"); /* ignore sigpipe */ #ifdef SIGPIPE @@ -129,14 +58,14 @@ main(int argc, char *argv[]) { #endif /* start http server */ - evhttp_bind_socket(http, __t->cfg->http_host, __t->cfg->http_port); - evhttp_set_gencb(http, on_request, NULL); + evhttp_bind_socket(http, s->cfg->http_host, s->cfg->http_port); + evhttp_set_gencb(http, on_request, s); /* attach hiredis to libevent base */ - reconnect(); + turnip_connect(s); /* loop */ - event_base_dispatch(__t->base); + event_base_dispatch(s->base); return EXIT_SUCCESS; }