From e245ab48ec8f766e589771b976761a0a41b6442d Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Tue, 19 Oct 2010 17:10:01 +0200 Subject: [PATCH] Added header file and example for usage from libev --- .gitignore | 2 +- Makefile | 5 ++- extra/hiredis/libev.h | 90 +++++++++++++++++++++++++++++++++++++++++++ libev-example.c | 30 +++++++++++++++ 4 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 extra/hiredis/libev.h create mode 100644 libev-example.c diff --git a/.gitignore b/.gitignore index 30e67d9..14bd58c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /hiredis-test /hiredis-example -/libevent-example +/*-example /*.o /*.so /*.dylib diff --git a/Makefile b/Makefile index d3d4f28..3c1b651 100644 --- a/Makefile +++ b/Makefile @@ -61,11 +61,14 @@ test: hiredis-test libevent-example: extra/hiredis/libevent.h libevent-example.c ${DYLIBNAME} $(CC) -o $@ $(CCOPT) $(DEBUG) -I. -Iextra -L. -lhiredis -levent libevent-example.c +libev-example: extra/hiredis/libev.h libev-example.c ${DYLIBNAME} + $(CC) -o $@ $(CCOPT) $(DEBUG) -I. -Iextra -L. -lhiredis -lev libev-example.c + .c.o: $(CC) -c $(CFLAGS) $(DEBUG) $(COMPILE_TIME) $< clean: - rm -rf ${DYLIBNAME} ${STLIBNAME} $(BINS) libevent-example *.o *.gcda *.gcno *.gcov + rm -rf ${DYLIBNAME} ${STLIBNAME} $(BINS) *-example *.o *.gcda *.gcno *.gcov dep: $(CC) -MM *.c diff --git a/extra/hiredis/libev.h b/extra/hiredis/libev.h new file mode 100644 index 0000000..79dde42 --- /dev/null +++ b/extra/hiredis/libev.h @@ -0,0 +1,90 @@ +#include +#include +#include + +/* Prototype for the error callback. */ +typedef void (redisErrorCallback)(const redisContext*); + +typedef struct libevRedisEvents { + redisContext *context; + redisErrorCallback *err; + struct ev_loop *loop; + ev_io rev, wev; +} libevRedisEvents; + +void libevRedisReadEvent(struct ev_loop *loop, ev_io *watcher, int revents) { + ((void)loop); ((void)revents); + libevRedisEvents *e = watcher->data; + + if (redisBufferRead(e->context) == REDIS_ERR) { + e->err(e->context); + } else { + if (redisProcessCallbacks(e->context) == REDIS_ERR) { + e->err(e->context); + } + } +} + +void libevRedisWriteEvent(struct ev_loop *loop, ev_io *watcher, int revents) { + ((void)loop); ((void)revents); + libevRedisEvents *e = watcher->data; + int done = 0; + + if (redisBufferWrite(e->context, &done) == REDIS_ERR) { + ev_io_stop(e->loop,&e->wev); + e->err(e->context); + } else { + /* Stop firing the write event when done */ + if (done) { + ev_io_stop(e->loop,&e->wev); + ev_io_start(e->loop,&e->rev); + } + } +} + +void libevRedisCommandCallback(redisContext *c, void *privdata) { + ((void)c); + libevRedisEvents *e = privdata; + ev_io_start(e->loop,&e->wev); +} + +void libevRedisDisconnectCallback(redisContext *c, void *privdata) { + ((void)c); + libevRedisEvents *e = privdata; + ev_io_stop(e->loop,&e->rev); + ev_io_stop(e->loop,&e->wev); +} + +void libevRedisFreeCallback(redisContext *c, void *privdata) { + ((void)c); + libevRedisEvents *e = privdata; + free(e); +} + +redisContext *libevRedisConnect(struct ev_loop *loop, redisErrorCallback *err, const char *ip, int port) { + libevRedisEvents *e; + redisContext *c = redisConnectNonBlock(ip, port, NULL); + if (c->error != NULL) { + err(c); + redisFree(c); + return NULL; + } + + /* Create container for context and r/w events */ + e = malloc(sizeof(*e)); + e->loop = loop; + e->context = c; + e->err = err; + e->rev.data = e; + e->wev.data = e; + + /* Register callbacks */ + redisSetDisconnectCallback(c,libevRedisDisconnectCallback,e); + redisSetCommandCallback(c,libevRedisCommandCallback,e); + redisSetFreeCallback(c,libevRedisFreeCallback,e); + + /* Initialize read/write events */ + ev_io_init(&e->rev,libevRedisReadEvent,c->fd,EV_READ); + ev_io_init(&e->wev,libevRedisWriteEvent,c->fd,EV_WRITE); + return c; +} diff --git a/libev-example.c b/libev-example.c new file mode 100644 index 0000000..8c48121 --- /dev/null +++ b/libev-example.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include + +void getCallback(redisContext *c, redisReply *reply, const void *privdata) { + printf("argv[%s]: %s\n", (const char*)privdata, reply->reply); + + /* Disconnect after receiving the reply to GET */ + redisDisconnect(c); +} + +void errorCallback(const redisContext *c) { + printf("Error: %s\n", c->error); +} + +int main (int argc, char **argv) { + signal(SIGPIPE, SIG_IGN); + struct ev_loop *loop = ev_default_loop(0); + + redisContext *c = libevRedisConnect(loop, errorCallback, "127.0.0.1", 6379); + if (c == NULL) return 1; + + redisCommand(c, "SET key %b", argv[argc-1], strlen(argv[argc-1])); + redisCommandWithCallback(c, getCallback, "end-1", "GET key"); + ev_loop(loop, 0); + redisFree(c); + return 0; +}