Skip to content

Commit

Permalink
Merge remote branch 'pietern/benchmark'
Browse files Browse the repository at this point in the history
  • Loading branch information
antirez committed Nov 5, 2010
2 parents 4d7e125 + feecb60 commit 56fce7c
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 297 deletions.
98 changes: 64 additions & 34 deletions deps/hiredis/hiredis.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,20 @@ static char *readBytes(redisReader *r, unsigned int bytes) {
return NULL;
}

static char *seekNewline(char *s) {
/* Find pointer to \r\n without strstr */
while(s != NULL && s[0] != '\r' && s[1] != '\n')
s = strchr(s,'\r');
return s;
}

static char *readLine(redisReader *r, int *_len) {
char *p, *s = strstr(r->buf+r->pos,"\r\n");
char *p, *s;
int len;

p = r->buf+r->pos;
s = seekNewline(p);
if (s != NULL) {
p = r->buf+r->pos;
len = s-(r->buf+r->pos);
r->pos += len+2; /* skip \r\n */
if (_len) *_len = len;
Expand All @@ -177,26 +186,26 @@ static char *readLine(redisReader *r, int *_len) {

static void moveToNextTask(redisReader *r) {
redisReadTask *cur, *prv;
assert(r->ridx >= 0);

/* Return a.s.a.p. when the stack is now empty. */
if (r->ridx == 0) {
r->ridx--;
return;
}
while (r->ridx >= 0) {
/* Return a.s.a.p. when the stack is now empty. */
if (r->ridx == 0) {
r->ridx--;
return;
}

cur = &(r->rstack[r->ridx]);
prv = &(r->rstack[r->ridx-1]);
assert(prv->type == REDIS_REPLY_ARRAY);
if (cur->idx == prv->elements-1) {
r->ridx--;
moveToNextTask(r);
} else {
/* Reset the type because the next item can be anything */
assert(cur->idx < prv->elements);
cur->type = -1;
cur->elements = -1;
cur->idx++;
cur = &(r->rstack[r->ridx]);
prv = &(r->rstack[r->ridx-1]);
assert(prv->type == REDIS_REPLY_ARRAY);
if (cur->idx == prv->elements-1) {
r->ridx--;
} else {
/* Reset the type because the next item can be anything */
assert(cur->idx < prv->elements);
cur->type = -1;
cur->elements = -1;
cur->idx++;
return;
}
}
}

Expand All @@ -207,10 +216,14 @@ static int processLineItem(redisReader *r) {
int len;

if ((p = readLine(r,&len)) != NULL) {
if (cur->type == REDIS_REPLY_INTEGER) {
obj = r->fn->createInteger(cur,strtoll(p,NULL,10));
if (r->fn) {
if (cur->type == REDIS_REPLY_INTEGER) {
obj = r->fn->createInteger(cur,strtoll(p,NULL,10));
} else {
obj = r->fn->createString(cur,p,len);
}
} else {
obj = r->fn->createString(cur,p,len);
obj = (void*)(size_t)(cur->type);
}

/* If there is no root yet, register this object as root. */
Expand All @@ -230,20 +243,22 @@ static int processBulkItem(redisReader *r) {
unsigned long bytelen;

p = r->buf+r->pos;
s = strstr(p,"\r\n");
s = seekNewline(p);
if (s != NULL) {
p = r->buf+r->pos;
bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
len = strtol(p,NULL,10);

if (len < 0) {
/* The nil object can always be created. */
obj = r->fn->createNil(cur);
obj = r->fn ? r->fn->createNil(cur) :
(void*)REDIS_REPLY_NIL;
} else {
/* Only continue when the buffer contains the entire bulk item. */
bytelen += len+2; /* include \r\n */
if (r->pos+bytelen <= sdslen(r->buf)) {
obj = r->fn->createString(cur,s+2,len);
obj = r->fn ? r->fn->createString(cur,s+2,len) :
(void*)REDIS_REPLY_STRING;
}
}

Expand All @@ -268,10 +283,12 @@ static int processMultiBulkItem(redisReader *r) {
if ((p = readLine(r,NULL)) != NULL) {
elements = strtol(p,NULL,10);
if (elements == -1) {
obj = r->fn->createNil(cur);
obj = r->fn ? r->fn->createNil(cur) :
(void*)REDIS_REPLY_NIL;
moveToNextTask(r);
} else {
obj = r->fn->createArray(cur,elements);
obj = r->fn ? r->fn->createArray(cur,elements) :
(void*)REDIS_REPLY_ARRAY;

/* Modify task stack when there are more than 0 elements. */
if (elements > 0) {
Expand Down Expand Up @@ -348,15 +365,26 @@ static int processItem(redisReader *r) {
}
}

void *redisReplyReaderCreate(redisReplyObjectFunctions *fn) {
void *redisReplyReaderCreate() {
redisReader *r = calloc(sizeof(redisReader),1);
r->error = NULL;
r->fn = fn == NULL ? &defaultFunctions : fn;
r->fn = &defaultFunctions;
r->buf = sdsempty();
r->ridx = -1;
return r;
}

/* Set the function set to build the reply. Returns REDIS_OK when there
* is no temporary object and it can be set, REDIS_ERR otherwise. */
int redisReplyReaderSetReplyObjectFunctions(void *reader, redisReplyObjectFunctions *fn) {
redisReader *r = reader;
if (r->reply == NULL) {
r->fn = fn;
return REDIS_OK;
}
return REDIS_ERR;
}

/* External libraries wrapping hiredis might need access to the temporary
* variable while the reply is built up. When the reader contains an
* object in between receiving some bytes to parse, this object might
Expand All @@ -370,7 +398,7 @@ void redisReplyReaderFree(void *reader) {
redisReader *r = reader;
if (r->error != NULL)
sdsfree(r->error);
if (r->reply != NULL)
if (r->reply != NULL && r->fn)
r->fn->freeObject(r->reply);
if (r->buf != NULL)
sdsfree(r->buf);
Expand Down Expand Up @@ -695,8 +723,10 @@ int redisSetReplyObjectFunctions(redisContext *c, redisReplyObjectFunctions *fn)

/* Helper function to lazily create a reply reader. */
static void __redisCreateReplyReader(redisContext *c) {
if (c->reader == NULL)
c->reader = redisReplyReaderCreate(c->fn);
if (c->reader == NULL) {
c->reader = redisReplyReaderCreate();
assert(redisReplyReaderSetReplyObjectFunctions(c->reader,c->fn) == REDIS_OK);
}
}

/* Use this function to handle a read event on the descriptor. It will try
Expand Down
3 changes: 2 additions & 1 deletion deps/hiredis/hiredis.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ typedef struct redisContext {
} redisContext;

void freeReplyObject(void *reply);
void *redisReplyReaderCreate(redisReplyObjectFunctions *fn);
void *redisReplyReaderCreate();
int redisReplyReaderSetReplyObjectFunctions(void *reader, redisReplyObjectFunctions *fn);
void *redisReplyReaderGetObject(void *reader);
char *redisReplyReaderGetError(void *reader);
void redisReplyReaderFree(void *ptr);
Expand Down
13 changes: 11 additions & 2 deletions deps/hiredis/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,12 @@ static void test_blocking_connection() {

static void test_reply_reader() {
void *reader;
void *reply;
char *err;
int ret;

test("Error handling in reply parser: ");
reader = redisReplyReaderCreate(NULL);
reader = redisReplyReaderCreate();
redisReplyReaderFeed(reader,(char*)"@foo\r\n",6);
ret = redisReplyReaderGetReply(reader,NULL);
err = redisReplyReaderGetError(reader);
Expand All @@ -201,7 +202,7 @@ static void test_reply_reader() {
/* when the reply already contains multiple items, they must be free'd
* on an error. valgrind will bark when this doesn't happen. */
test("Memory cleanup in reply parser: ");
reader = redisReplyReaderCreate(NULL);
reader = redisReplyReaderCreate();
redisReplyReaderFeed(reader,(char*)"*2\r\n",4);
redisReplyReaderFeed(reader,(char*)"$5\r\nhello\r\n",11);
redisReplyReaderFeed(reader,(char*)"@foo\r\n",6);
Expand All @@ -210,6 +211,14 @@ static void test_reply_reader() {
test_cond(ret == REDIS_ERR &&
strcasecmp(err,"protocol error, got \"@\" as reply type byte") == 0);
redisReplyReaderFree(reader);

test("Works with NULL functions for reply: ");
reader = redisReplyReaderCreate();
redisReplyReaderSetReplyObjectFunctions(reader,NULL);
redisReplyReaderFeed(reader,(char*)"+OK\r\n",5);
ret = redisReplyReaderGetReply(reader,&reply);
test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
redisReplyReaderFree(reader);
}

static void test_throughput() {
Expand Down
6 changes: 5 additions & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@ redis-server: $(OBJ)
@echo ""

redis-benchmark: $(BENCHOBJ)
$(CC) -o $(BENCHPRGNAME) $(CCOPT) $(DEBUG) $(BENCHOBJ)
cd ../deps/hiredis && make static
$(CC) -o $(BENCHPRGNAME) $(CCOPT) $(DEBUG) $(BENCHOBJ) ../deps/hiredis/libhiredis.a

redis-benchmark.o:
$(CC) -c $(CFLAGS) -I../deps/hiredis $(DEBUG) $(COMPILE_TIME) $<

redis-cli: $(CLIOBJ)
cd ../deps/hiredis && make static
Expand Down
Loading

0 comments on commit 56fce7c

Please sign in to comment.