summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Noordhuis <pcnoordhuis@gmail.com>2010-10-19 17:10:01 +0200
committerPieter Noordhuis <pcnoordhuis@gmail.com>2010-10-19 21:24:24 +0200
commite245ab48ec8f766e589771b976761a0a41b6442d (patch)
treea1412036f29a8d6fce9a0e1f08aa5c2c8ebd6596
parent206868de060bbfeb2745dad2f410691ad2fc62f8 (diff)
Added header file and example for usage from libev
-rw-r--r--.gitignore2
-rw-r--r--Makefile5
-rw-r--r--extra/hiredis/libev.h90
-rw-r--r--libev-example.c30
4 files changed, 125 insertions, 2 deletions
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 <sys/types.h>
+#include <ev.h>
+#include <hiredis.h>
+
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <hiredis/libev.h>
+#include <signal.h>
+
+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;
+}