Skip to content

Commit

Permalink
Update hiredis to 0.9.2
Browse files Browse the repository at this point in the history
  • Loading branch information
pietern committed Dec 23, 2010
1 parent d3e5e28 commit a1e97d6
Show file tree
Hide file tree
Showing 16 changed files with 678 additions and 173 deletions.
46 changes: 28 additions & 18 deletions deps/hiredis/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,35 @@ OBJ = net.o hiredis.o sds.o async.o
BINS = hiredis-example hiredis-test

uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
OPTIMIZATION?=-O2
OPTIMIZATION?=-O3
ifeq ($(uname_S),SunOS)
CFLAGS?= -std=c99 -pedantic $(OPTIMIZATION) -fPIC -Wall -W -D__EXTENSIONS__ -D_XPG6
CCLINK?= -ldl -lnsl -lsocket -lm -lpthread
CFLAGS?=-std=c99 -pedantic $(OPTIMIZATION) -fPIC -Wall -W -D__EXTENSIONS__ -D_XPG6 $(ARCH) $(PROF)
CCLINK?=-ldl -lnsl -lsocket -lm -lpthread
LDFLAGS?=-L. -Wl,-R,.
DYLIBNAME?=libhiredis.so
DYLIB_MAKE_CMD?=gcc -shared -Wl,-soname,${DYLIBNAME} -o ${DYLIBNAME} ${OBJ}
DYLIB_MAKE_CMD?=$(CC) -G -o ${DYLIBNAME} ${OBJ}
STLIBNAME?=libhiredis.a
STLIB_MAKE_CMD?=ar rcs ${STLIBNAME} ${OBJ}
else ifeq ($(uname_S),Darwin)
CFLAGS?= -std=c99 -pedantic $(OPTIMIZATION) -fPIC -Wall -W -Wwrite-strings $(ARCH) $(PROF)
CCLINK?= -lm -pthread
OBJARCH?= -arch i386 -arch x86_64
CFLAGS?=-std=c99 -pedantic $(OPTIMIZATION) -fPIC -Wall -W -Wwrite-strings $(ARCH) $(PROF)
CCLINK?=-lm -pthread
LDFLAGS?=-L. -Wl,-rpath,.
OBJARCH?=-arch i386 -arch x86_64
DYLIBNAME?=libhiredis.dylib
DYLIB_MAKE_CMD?=libtool -dynamic -o ${DYLIBNAME} -lm ${DEBUG} - ${OBJ}
STLIBNAME?=libhiredis.a
STLIB_MAKE_CMD?=libtool -static -o ${STLIBNAME} - ${OBJ}
else
CFLAGS?= -std=c99 -pedantic $(OPTIMIZATION) -fPIC -Wall -W -Wwrite-strings $(ARCH) $(PROF)
CCLINK?= -lm -pthread
CFLAGS?=-std=c99 -pedantic $(OPTIMIZATION) -fPIC -Wall -W -Wwrite-strings $(ARCH) $(PROF)
CCLINK?=-lm -pthread
LDFLAGS?=-L. -Wl,-rpath,.
DYLIBNAME?=libhiredis.so
DYLIB_MAKE_CMD?=gcc -shared -Wl,-soname,${DYLIBNAME} -o ${DYLIBNAME} ${OBJ}
STLIBNAME?=libhiredis.a
STLIB_MAKE_CMD?=ar rcs ${STLIBNAME} ${OBJ}
endif
CCOPT= $(CFLAGS) $(CCLINK) $(ARCH) $(PROF)
DEBUG?= -g -ggdb
CCOPT= $(CFLAGS) $(CCLINK)
DEBUG?= -g -ggdb

PREFIX?= /usr/local
INSTALL_INC= $(PREFIX)/include/hiredis
Expand All @@ -43,8 +46,6 @@ all: ${DYLIBNAME} ${BINS}
# Deps (use make dep to generate this)
net.o: net.c fmacros.h net.h
async.o: async.c async.h hiredis.h sds.h util.h
example-libev.o: example-libev.c hiredis.h async.h adapters/libev.h
example-libevent.o: example-libevent.c hiredis.h async.h adapters/libevent.h
example.o: example.c hiredis.h
hiredis.o: hiredis.c hiredis.h net.h sds.h util.h
sds.o: sds.c sds.h
Expand All @@ -60,14 +61,23 @@ dynamic: ${DYLIBNAME}
static: ${STLIBNAME}

# Binaries:
hiredis-example-libevent: example-libevent.o ${DYLIBNAME}
$(CC) -o $@ $(CCOPT) $(DEBUG) -L. -lhiredis -levent -Wl,-rpath,. example-libevent.c
hiredis-example-libevent: example-libevent.c adapters/libevent.h ${DYLIBNAME}
$(CC) -o $@ $(CCOPT) $(DEBUG) $(LDFLAGS) -lhiredis -levent example-libevent.c

hiredis-example-libev: example-libev.c adapters/libev.h ${DYLIBNAME}
$(CC) -o $@ $(CCOPT) $(DEBUG) $(LDFLAGS) -lhiredis -lev example-libev.c

hiredis-example-libev: example-libev.o ${DYLIBNAME}
$(CC) -o $@ $(CCOPT) $(DEBUG) -L. -lhiredis -lev -Wl,-rpath,. example-libev.c
ifndef AE_DIR
hiredis-example-ae:
@echo "Please specify AE_DIR (e.g. <redis repository>/src)"
@false
else
hiredis-example-ae: example-ae.c adapters/ae.h ${DYLIBNAME}
$(CC) -o $@ $(CCOPT) $(DEBUG) -I$(AE_DIR) $(LDFLAGS) -lhiredis example-ae.c $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o
endif

hiredis-%: %.o ${DYLIBNAME}
$(CC) -o $@ $(CCOPT) $(DEBUG) -L. -lhiredis -Wl,-rpath,. $<
$(CC) -o $@ $(CCOPT) $(DEBUG) $(LDFLAGS) -lhiredis $<

test: hiredis-test
./hiredis-test
Expand Down
63 changes: 45 additions & 18 deletions deps/hiredis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,18 @@ To consume the synchronous API, there are only a few function calls that need to

### Connecting

The function `redisConnect` is used to create a so-called `redisContext`. The context is where
Hiredis holds state for a connection. The `redisContext` struct has an `error` field that is
non-NULL when the connection is in an error state. It contains a string with a textual
representation of the error. After trying to connect to Redis using `redisConnect` you should
check the `error` field to see if establishing the connection was successful:
The function `redisConnect` is used to create a so-called `redisContext`. The
context is where Hiredis holds state for a connection. The `redisContext`
struct has an integer `err` field that is non-zero when an the connection is in
an error state. The field `errstr` will contain a string with a description of
the error. More information on errors can be found in the **Errors** section.
After trying to connect to Redis using `redisConnect` you should
check the `err` field to see if establishing the connection was successful:

redisContext *c = redisConnect("127.0.0.1", 6379);
if (c->error != NULL) {
printf("Error: %s\n", c->error);
// handle error
if (c->err) {
printf("Error: %s\n", c->errstr);
// handle error
}

### Sending commands
Expand Down Expand Up @@ -76,8 +78,8 @@ anywhere in an argument:
### Using replies

The return value of `redisCommand` holds a reply when the command was
successfully executed. When the return value is `NULL`, the `error` field
in the context can be used to find out what was the cause of failure.
successfully executed. When an error occurs, the return value is `NULL` and
the `err` field in the context will be set (see section on **Errors**).
Once an error is returned the context cannot be reused and you should set up
a new connection.

Expand Down Expand Up @@ -166,7 +168,7 @@ to the `redisCommand` family, apart from not returning a reply:
After calling either function one or more times, `redisGetReply` can be used to receive the
subsequent replies. The return value for this function is either `REDIS_OK` or `REDIS_ERR`, where
the latter means an error occurred while reading a reply. Just as with the other commands,
the `error` field in the context can be used to find out what the cause of this error is.
the `err` field in the context can be used to find out what the cause of this error is.

The following examples shows a simple pipeline (resulting in only a single call to `write(2)` and
a single call to `write(2)`):
Expand All @@ -184,10 +186,35 @@ This API can also be used to implement a blocking subscriber:
reply = redisCommand(context,"SUBSCRIBE foo");
freeReplyObject(reply);
while(redisGetReply(context,&reply) == REDIS_OK) {
// consume message
freeReplyObject(reply);
// consume message
freeReplyObject(reply);
}

### Errors

When a function call is not successful, depending on the function either `NULL` or `REDIS_ERR` is
returned. The `err` field inside the context will be non-zero and set to one of the
following constants:

* **`REDIS_ERR_IO`**:
There was an I/O error while creating the connection, trying to write
to the socket or read from the socket. If you included `errno.h` in your
application, you can use the global `errno` variable to find out what is
wrong.

* **`REDIS_ERR_EOF`**:
The server closed the connection which resulted in an empty read.

* **`REDIS_ERR_PROTOCOL`**:
There was an error while parsing the protocol.

* **`REDIS_ERR_OTHER`**:
Any other error. Currently, it is only used when a specified hostname to connect
to cannot be resolved.

In every case, the `errstr` field in the context will be set to hold a string representation
of the error.

## Asynchronous API

Hiredis comes with an asynchronous API that works easily with any event library.
Expand All @@ -197,15 +224,15 @@ and [libevent](http://monkey.org/~provos/libevent/).
### Connecting

The function `redisAsyncConnect` can be used to establish a non-blocking connection to
Redis. It returns a pointer to the newly created `redisAsyncContext` struct. The `error` field
Redis. It returns a pointer to the newly created `redisAsyncContext` struct. The `err` field
should be checked after creation to see if there were errors creating the connection.
Because the connection that will be created is non-blocking, the kernel is not able to
instantly return if the specified host and port is able to accept a connection.

redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
if (c->error != NULL) {
printf("Error: %s\n", c->error);
// handle error
if (c->err) {
printf("Error: %s\n", c->errstr);
// handle error
}

The asynchronous context can hold a disconnect callback function that is called when the
Expand All @@ -215,7 +242,7 @@ have the following prototype:
void(const redisAsyncContext *c, int status);

On a disconnect, the `status` argument is set to `REDIS_OK` when disconnection was initiated by the
user, or `REDIS_ERR` when the disconnection was caused by an error. When it is `REDIS_ERR`, the `error`
user, or `REDIS_ERR` when the disconnection was caused by an error. When it is `REDIS_ERR`, the `err`
field in the context can be accessed to find out the cause of the error.

The context object is always free'd after the disconnect callback fired. When a reconnect is needed,
Expand Down
95 changes: 95 additions & 0 deletions deps/hiredis/adapters/ae.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include <sys/types.h>
#include <ae.h>
#include "../hiredis.h"
#include "../async.h"

typedef struct redisAeEvents {
redisAsyncContext *context;
aeEventLoop *loop;
int fd;
int reading, writing;
} redisAeEvents;

void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
((void)el); ((void)fd); ((void)mask);

redisAeEvents *e = (redisAeEvents*)privdata;
redisAsyncHandleRead(e->context);
}

void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
((void)el); ((void)fd); ((void)mask);

redisAeEvents *e = (redisAeEvents*)privdata;
redisAsyncHandleWrite(e->context);
}

void redisAeAddRead(void *privdata) {
redisAeEvents *e = (redisAeEvents*)privdata;
aeEventLoop *loop = e->loop;
if (!e->reading) {
e->reading = 1;
aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e);
}
}

void redisAeDelRead(void *privdata) {
redisAeEvents *e = (redisAeEvents*)privdata;
aeEventLoop *loop = e->loop;
if (e->reading) {
e->reading = 0;
aeDeleteFileEvent(loop,e->fd,AE_READABLE);
}
}

void redisAeAddWrite(void *privdata) {
redisAeEvents *e = (redisAeEvents*)privdata;
aeEventLoop *loop = e->loop;
if (!e->writing) {
e->writing = 1;
aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e);
}
}

void redisAeDelWrite(void *privdata) {
redisAeEvents *e = (redisAeEvents*)privdata;
aeEventLoop *loop = e->loop;
if (e->writing) {
e->writing = 0;
aeDeleteFileEvent(loop,e->fd,AE_WRITABLE);
}
}

void redisAeCleanup(void *privdata) {
redisAeEvents *e = (redisAeEvents*)privdata;
redisAeDelRead(privdata);
redisAeDelWrite(privdata);
free(e);
}

int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {
redisContext *c = &(ac->c);
redisAeEvents *e;

/* Nothing should be attached when something is already attached */
if (ac->_adapter_data != NULL)
return REDIS_ERR;

/* Create container for context and r/w events */
e = (redisAeEvents*)malloc(sizeof(*e));
e->context = ac;
e->loop = loop;
e->fd = c->fd;
e->reading = e->writing = 0;

/* Register functions to start/stop listening for events */
ac->evAddRead = redisAeAddRead;
ac->evDelRead = redisAeDelRead;
ac->evAddWrite = redisAeAddWrite;
ac->evDelWrite = redisAeDelWrite;
ac->evCleanup = redisAeCleanup;
ac->_adapter_data = e;

return REDIS_OK;
}

Loading

0 comments on commit a1e97d6

Please sign in to comment.