hiredis 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -0
- data/ext/hiredis_ext/connection.c +1 -1
- data/ext/hiredis_ext/extconf.rb +9 -13
- data/ext/hiredis_ext/reader.c +12 -15
- data/lib/hiredis/version.rb +1 -1
- data/vendor/hiredis/COPYING +25 -6
- data/vendor/hiredis/Makefile +60 -48
- data/vendor/hiredis/async.c +4 -11
- data/vendor/hiredis/async.h +2 -3
- data/vendor/hiredis/fmacros.h +4 -5
- data/vendor/hiredis/hiredis.c +417 -255
- data/vendor/hiredis/hiredis.h +52 -32
- data/vendor/hiredis/net.c +29 -25
- data/vendor/hiredis/net.h +2 -2
- data/vendor/hiredis/sds.c +24 -23
- data/vendor/hiredis/sds.h +10 -0
- data/vendor/hiredis/test.c +83 -52
- metadata +14 -27
- data/vendor/hiredis/util.h +0 -40
data/vendor/hiredis/hiredis.h
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c) 2009-
|
3
|
-
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
2
|
+
* Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
3
|
+
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
4
4
|
*
|
5
5
|
* All rights reserved.
|
6
6
|
*
|
@@ -36,8 +36,8 @@
|
|
36
36
|
#include <sys/time.h> /* for struct timeval */
|
37
37
|
|
38
38
|
#define HIREDIS_MAJOR 0
|
39
|
-
#define HIREDIS_MINOR
|
40
|
-
#define HIREDIS_PATCH
|
39
|
+
#define HIREDIS_MINOR 10
|
40
|
+
#define HIREDIS_PATCH 0
|
41
41
|
|
42
42
|
#define REDIS_ERR -1
|
43
43
|
#define REDIS_OK 0
|
@@ -46,10 +46,11 @@
|
|
46
46
|
* error that occured. REDIS_ERR_IO means there was an I/O error and you
|
47
47
|
* should use the "errno" variable to find out what is wrong.
|
48
48
|
* For other values, the "errstr" field will hold a description. */
|
49
|
-
#define REDIS_ERR_IO 1 /*
|
50
|
-
#define REDIS_ERR_EOF 3 /*
|
51
|
-
#define REDIS_ERR_PROTOCOL 4 /*
|
52
|
-
#define
|
49
|
+
#define REDIS_ERR_IO 1 /* Error in read or write */
|
50
|
+
#define REDIS_ERR_EOF 3 /* End of file */
|
51
|
+
#define REDIS_ERR_PROTOCOL 4 /* Protocol error */
|
52
|
+
#define REDIS_ERR_OOM 5 /* Out of memory */
|
53
|
+
#define REDIS_ERR_OTHER 2 /* Everything else... */
|
53
54
|
|
54
55
|
/* Connection type can be blocking or non-blocking and is set in the
|
55
56
|
* least significant bit of the flags field in redisContext. */
|
@@ -113,36 +114,56 @@ typedef struct redisReplyObjectFunctions {
|
|
113
114
|
void (*freeObject)(void*);
|
114
115
|
} redisReplyObjectFunctions;
|
115
116
|
|
116
|
-
|
117
|
-
|
118
|
-
/* Context for a connection to Redis */
|
119
|
-
typedef struct redisContext {
|
120
|
-
int fd;
|
121
|
-
int flags;
|
122
|
-
char *obuf; /* Write buffer */
|
117
|
+
/* State for the protocol parser */
|
118
|
+
typedef struct redisReader {
|
123
119
|
int err; /* Error flags, 0 when there is no error */
|
124
|
-
char
|
120
|
+
char errstr[128]; /* String representation of error when applicable */
|
125
121
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
122
|
+
char *buf; /* Read buffer */
|
123
|
+
size_t pos; /* Buffer cursor */
|
124
|
+
size_t len; /* Buffer length */
|
125
|
+
|
126
|
+
redisReadTask rstack[3];
|
127
|
+
int ridx; /* Index of current read task */
|
128
|
+
void *reply; /* Temporary reply pointer */
|
130
129
|
|
130
|
+
redisReplyObjectFunctions *fn;
|
131
|
+
void *privdata;
|
132
|
+
} redisReader;
|
133
|
+
|
134
|
+
/* Public API for the protocol parser. */
|
135
|
+
redisReader *redisReaderCreate(void);
|
136
|
+
void redisReaderFree(redisReader *r);
|
137
|
+
int redisReaderFeed(redisReader *r, const char *buf, size_t len);
|
138
|
+
int redisReaderGetReply(redisReader *r, void **reply);
|
139
|
+
|
140
|
+
/* Backwards compatibility, can be removed on big version bump. */
|
141
|
+
#define redisReplyReaderCreate redisReaderCreate
|
142
|
+
#define redisReplyReaderFree redisReaderFree
|
143
|
+
#define redisReplyReaderFeed redisReaderFeed
|
144
|
+
#define redisReplyReaderGetReply redisReaderGetReply
|
145
|
+
#define redisReplyReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p))
|
146
|
+
#define redisReplyReaderGetObject(_r) (((redisReader*)(_r))->reply)
|
147
|
+
#define redisReplyReaderGetError(_r) (((redisReader*)(_r))->errstr)
|
148
|
+
|
149
|
+
/* Function to free the reply objects hiredis returns by default. */
|
131
150
|
void freeReplyObject(void *reply);
|
132
|
-
void *redisReplyReaderCreate(void);
|
133
|
-
int redisReplyReaderSetReplyObjectFunctions(void *reader, redisReplyObjectFunctions *fn);
|
134
|
-
int redisReplyReaderSetPrivdata(void *reader, void *privdata);
|
135
|
-
void *redisReplyReaderGetObject(void *reader);
|
136
|
-
char *redisReplyReaderGetError(void *reader);
|
137
|
-
void redisReplyReaderFree(void *ptr);
|
138
|
-
void redisReplyReaderFeed(void *reader, const char *buf, size_t len);
|
139
|
-
int redisReplyReaderGetReply(void *reader, void **reply);
|
140
151
|
|
141
152
|
/* Functions to format a command according to the protocol. */
|
142
153
|
int redisvFormatCommand(char **target, const char *format, va_list ap);
|
143
154
|
int redisFormatCommand(char **target, const char *format, ...);
|
144
155
|
int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);
|
145
156
|
|
157
|
+
/* Context for a connection to Redis */
|
158
|
+
typedef struct redisContext {
|
159
|
+
int err; /* Error flags, 0 when there is no error */
|
160
|
+
char errstr[128]; /* String representation of error when applicable */
|
161
|
+
int fd;
|
162
|
+
int flags;
|
163
|
+
char *obuf; /* Write buffer */
|
164
|
+
redisReader *reader; /* Protocol reader */
|
165
|
+
} redisContext;
|
166
|
+
|
146
167
|
redisContext *redisConnect(const char *ip, int port);
|
147
168
|
redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv);
|
148
169
|
redisContext *redisConnectNonBlock(const char *ip, int port);
|
@@ -150,7 +171,6 @@ redisContext *redisConnectUnix(const char *path);
|
|
150
171
|
redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv);
|
151
172
|
redisContext *redisConnectUnixNonBlock(const char *path);
|
152
173
|
int redisSetTimeout(redisContext *c, struct timeval tv);
|
153
|
-
int redisSetReplyObjectFunctions(redisContext *c, redisReplyObjectFunctions *fn);
|
154
174
|
void redisFree(redisContext *c);
|
155
175
|
int redisBufferRead(redisContext *c);
|
156
176
|
int redisBufferWrite(redisContext *c, int *done);
|
@@ -164,9 +184,9 @@ int redisGetReplyFromReader(redisContext *c, void **reply);
|
|
164
184
|
|
165
185
|
/* Write a command to the output buffer. Use these functions in blocking mode
|
166
186
|
* to get a pipeline of commands. */
|
167
|
-
|
168
|
-
|
169
|
-
|
187
|
+
int redisvAppendCommand(redisContext *c, const char *format, va_list ap);
|
188
|
+
int redisAppendCommand(redisContext *c, const char *format, ...);
|
189
|
+
int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
|
170
190
|
|
171
191
|
/* Issue a command to Redis. In a blocking context, it is identical to calling
|
172
192
|
* redisAppendCommand, followed by redisGetReply. The function will return
|
data/vendor/hiredis/net.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/* Extracted from anet.c to work properly with Hiredis error reporting.
|
2
2
|
*
|
3
|
-
* Copyright (c) 2006-
|
4
|
-
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
3
|
+
* Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
4
|
+
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
5
5
|
*
|
6
6
|
* All rights reserved.
|
7
7
|
*
|
@@ -49,18 +49,28 @@
|
|
49
49
|
#include "net.h"
|
50
50
|
#include "sds.h"
|
51
51
|
|
52
|
-
/*
|
53
|
-
void __redisSetError(redisContext *c, int type,
|
52
|
+
/* Defined in hiredis.c */
|
53
|
+
void __redisSetError(redisContext *c, int type, const char *str);
|
54
|
+
|
55
|
+
static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {
|
56
|
+
char buf[128];
|
57
|
+
size_t len = 0;
|
58
|
+
|
59
|
+
if (prefix != NULL)
|
60
|
+
len = snprintf(buf,sizeof(buf),"%s: ",prefix);
|
61
|
+
strerror_r(errno,buf+len,sizeof(buf)-len);
|
62
|
+
__redisSetError(c,type,buf);
|
63
|
+
}
|
54
64
|
|
55
65
|
static int redisCreateSocket(redisContext *c, int type) {
|
56
66
|
int s, on = 1;
|
57
67
|
if ((s = socket(type, SOCK_STREAM, 0)) == -1) {
|
58
|
-
|
68
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
59
69
|
return REDIS_ERR;
|
60
70
|
}
|
61
71
|
if (type == AF_INET) {
|
62
72
|
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
|
63
|
-
|
73
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
64
74
|
close(s);
|
65
75
|
return REDIS_ERR;
|
66
76
|
}
|
@@ -75,8 +85,7 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
|
|
75
85
|
* Note that fcntl(2) for F_GETFL and F_SETFL can't be
|
76
86
|
* interrupted by a signal. */
|
77
87
|
if ((flags = fcntl(fd, F_GETFL)) == -1) {
|
78
|
-
|
79
|
-
sdscatprintf(sdsempty(), "fcntl(F_GETFL): %s", strerror(errno)));
|
88
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)");
|
80
89
|
close(fd);
|
81
90
|
return REDIS_ERR;
|
82
91
|
}
|
@@ -87,8 +96,7 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
|
|
87
96
|
flags |= O_NONBLOCK;
|
88
97
|
|
89
98
|
if (fcntl(fd, F_SETFL, flags) == -1) {
|
90
|
-
|
91
|
-
sdscatprintf(sdsempty(), "fcntl(F_SETFL): %s", strerror(errno)));
|
99
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)");
|
92
100
|
close(fd);
|
93
101
|
return REDIS_ERR;
|
94
102
|
}
|
@@ -98,8 +106,7 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
|
|
98
106
|
static int redisSetTcpNoDelay(redisContext *c, int fd) {
|
99
107
|
int yes = 1;
|
100
108
|
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
|
101
|
-
|
102
|
-
sdscatprintf(sdsempty(), "setsockopt(TCP_NODELAY): %s", strerror(errno)));
|
109
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)");
|
103
110
|
close(fd);
|
104
111
|
return REDIS_ERR;
|
105
112
|
}
|
@@ -124,15 +131,14 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *
|
|
124
131
|
FD_SET(fd, &wfd);
|
125
132
|
|
126
133
|
if (select(FD_SETSIZE, NULL, &wfd, NULL, toptr) == -1) {
|
127
|
-
|
128
|
-
sdscatprintf(sdsempty(), "select(2): %s", strerror(errno)));
|
134
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"select(2)");
|
129
135
|
close(fd);
|
130
136
|
return REDIS_ERR;
|
131
137
|
}
|
132
138
|
|
133
139
|
if (!FD_ISSET(fd, &wfd)) {
|
134
140
|
errno = ETIMEDOUT;
|
135
|
-
|
141
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
136
142
|
close(fd);
|
137
143
|
return REDIS_ERR;
|
138
144
|
}
|
@@ -140,15 +146,14 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *
|
|
140
146
|
err = 0;
|
141
147
|
errlen = sizeof(err);
|
142
148
|
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
|
143
|
-
|
144
|
-
sdscatprintf(sdsempty(), "getsockopt(SO_ERROR): %s", strerror(errno)));
|
149
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)");
|
145
150
|
close(fd);
|
146
151
|
return REDIS_ERR;
|
147
152
|
}
|
148
153
|
|
149
154
|
if (err) {
|
150
155
|
errno = err;
|
151
|
-
|
156
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
152
157
|
close(fd);
|
153
158
|
return REDIS_ERR;
|
154
159
|
}
|
@@ -156,20 +161,18 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *
|
|
156
161
|
return REDIS_OK;
|
157
162
|
}
|
158
163
|
|
159
|
-
|
164
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
160
165
|
close(fd);
|
161
166
|
return REDIS_ERR;
|
162
167
|
}
|
163
168
|
|
164
169
|
int redisContextSetTimeout(redisContext *c, struct timeval tv) {
|
165
170
|
if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {
|
166
|
-
|
167
|
-
sdscatprintf(sdsempty(), "setsockopt(SO_RCVTIMEO): %s", strerror(errno)));
|
171
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)");
|
168
172
|
return REDIS_ERR;
|
169
173
|
}
|
170
174
|
if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) {
|
171
|
-
|
172
|
-
sdscatprintf(sdsempty(), "setsockopt(SO_SNDTIMEO): %s", strerror(errno)));
|
175
|
+
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)");
|
173
176
|
return REDIS_ERR;
|
174
177
|
}
|
175
178
|
return REDIS_OK;
|
@@ -192,8 +195,9 @@ int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct t
|
|
192
195
|
|
193
196
|
he = gethostbyname(addr);
|
194
197
|
if (he == NULL) {
|
195
|
-
|
196
|
-
|
198
|
+
char buf[128];
|
199
|
+
snprintf(buf,sizeof(buf),"Can't resolve: %s", addr);
|
200
|
+
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
197
201
|
close(s);
|
198
202
|
return REDIS_ERR;
|
199
203
|
}
|
data/vendor/hiredis/net.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/* Extracted from anet.c to work properly with Hiredis error reporting.
|
2
2
|
*
|
3
|
-
* Copyright (c) 2006-
|
4
|
-
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
3
|
+
* Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
4
|
+
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
5
5
|
*
|
6
6
|
* All rights reserved.
|
7
7
|
*
|
data/vendor/hiredis/sds.c
CHANGED
@@ -28,18 +28,18 @@
|
|
28
28
|
* POSSIBILITY OF SUCH DAMAGE.
|
29
29
|
*/
|
30
30
|
|
31
|
-
#define SDS_ABORT_ON_OOM
|
32
|
-
|
33
|
-
#include "sds.h"
|
34
31
|
#include <stdio.h>
|
35
32
|
#include <stdlib.h>
|
36
33
|
#include <string.h>
|
37
34
|
#include <ctype.h>
|
35
|
+
#include "sds.h"
|
38
36
|
|
37
|
+
#ifdef SDS_ABORT_ON_OOM
|
39
38
|
static void sdsOomAbort(void) {
|
40
39
|
fprintf(stderr,"SDS: Out Of Memory (SDS_ABORT_ON_OOM defined)\n");
|
41
40
|
abort();
|
42
41
|
}
|
42
|
+
#endif
|
43
43
|
|
44
44
|
sds sdsnewlen(const void *init, size_t initlen) {
|
45
45
|
struct sdshdr *sh;
|
@@ -69,11 +69,6 @@ sds sdsnew(const char *init) {
|
|
69
69
|
return sdsnewlen(init, initlen);
|
70
70
|
}
|
71
71
|
|
72
|
-
size_t sdslen(const sds s) {
|
73
|
-
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
|
74
|
-
return sh->len;
|
75
|
-
}
|
76
|
-
|
77
72
|
sds sdsdup(const sds s) {
|
78
73
|
return sdsnewlen(s, sdslen(s));
|
79
74
|
}
|
@@ -83,11 +78,6 @@ void sdsfree(sds s) {
|
|
83
78
|
free(s-sizeof(struct sdshdr));
|
84
79
|
}
|
85
80
|
|
86
|
-
size_t sdsavail(sds s) {
|
87
|
-
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
|
88
|
-
return sh->free;
|
89
|
-
}
|
90
|
-
|
91
81
|
void sdsupdatelen(sds s) {
|
92
82
|
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
|
93
83
|
int reallen = strlen(s);
|
@@ -388,17 +378,19 @@ sds sdsfromlonglong(long long value) {
|
|
388
378
|
|
389
379
|
sds sdscatrepr(sds s, char *p, size_t len) {
|
390
380
|
s = sdscatlen(s,"\"",1);
|
381
|
+
if (s == NULL) return NULL;
|
382
|
+
|
391
383
|
while(len--) {
|
392
384
|
switch(*p) {
|
393
385
|
case '\\':
|
394
386
|
case '"':
|
395
387
|
s = sdscatprintf(s,"\\%c",*p);
|
396
388
|
break;
|
397
|
-
case '\n': s = sdscatlen(s,"\\n",
|
398
|
-
case '\r': s = sdscatlen(s,"\\r",
|
399
|
-
case '\t': s = sdscatlen(s,"\\t",
|
400
|
-
case '\a': s = sdscatlen(s,"\\a",
|
401
|
-
case '\b': s = sdscatlen(s,"\\b",
|
389
|
+
case '\n': s = sdscatlen(s,"\\n",2); break;
|
390
|
+
case '\r': s = sdscatlen(s,"\\r",2); break;
|
391
|
+
case '\t': s = sdscatlen(s,"\\t",2); break;
|
392
|
+
case '\a': s = sdscatlen(s,"\\a",2); break;
|
393
|
+
case '\b': s = sdscatlen(s,"\\b",2); break;
|
402
394
|
default:
|
403
395
|
if (isprint(*p))
|
404
396
|
s = sdscatprintf(s,"%c",*p);
|
@@ -407,6 +399,7 @@ sds sdscatrepr(sds s, char *p, size_t len) {
|
|
407
399
|
break;
|
408
400
|
}
|
409
401
|
p++;
|
402
|
+
if (s == NULL) return NULL;
|
410
403
|
}
|
411
404
|
return sdscatlen(s,"\"",1);
|
412
405
|
}
|
@@ -426,7 +419,7 @@ sds sdscatrepr(sds s, char *p, size_t len) {
|
|
426
419
|
sds *sdssplitargs(char *line, int *argc) {
|
427
420
|
char *p = line;
|
428
421
|
char *current = NULL;
|
429
|
-
char **vector = NULL;
|
422
|
+
char **vector = NULL, **_vector = NULL;
|
430
423
|
|
431
424
|
*argc = 0;
|
432
425
|
while(1) {
|
@@ -437,7 +430,11 @@ sds *sdssplitargs(char *line, int *argc) {
|
|
437
430
|
int inq=0; /* set to 1 if we are in "quotes" */
|
438
431
|
int done=0;
|
439
432
|
|
440
|
-
if (current == NULL)
|
433
|
+
if (current == NULL) {
|
434
|
+
current = sdsempty();
|
435
|
+
if (current == NULL) goto err;
|
436
|
+
}
|
437
|
+
|
441
438
|
while(!done) {
|
442
439
|
if (inq) {
|
443
440
|
if (*p == '\\' && *(p+1)) {
|
@@ -481,9 +478,13 @@ sds *sdssplitargs(char *line, int *argc) {
|
|
481
478
|
}
|
482
479
|
}
|
483
480
|
if (*p) p++;
|
481
|
+
if (current == NULL) goto err;
|
484
482
|
}
|
485
483
|
/* add the token to the vector */
|
486
|
-
|
484
|
+
_vector = realloc(vector,((*argc)+1)*sizeof(char*));
|
485
|
+
if (_vector == NULL) goto err;
|
486
|
+
|
487
|
+
vector = _vector;
|
487
488
|
vector[*argc] = current;
|
488
489
|
(*argc)++;
|
489
490
|
current = NULL;
|
@@ -495,8 +496,8 @@ sds *sdssplitargs(char *line, int *argc) {
|
|
495
496
|
err:
|
496
497
|
while((*argc)--)
|
497
498
|
sdsfree(vector[*argc]);
|
498
|
-
free(vector);
|
499
|
-
if (current) sdsfree(current);
|
499
|
+
if (vector != NULL) free(vector);
|
500
|
+
if (current != NULL) sdsfree(current);
|
500
501
|
return NULL;
|
501
502
|
}
|
502
503
|
|
data/vendor/hiredis/sds.h
CHANGED
@@ -42,6 +42,16 @@ struct sdshdr {
|
|
42
42
|
char buf[];
|
43
43
|
};
|
44
44
|
|
45
|
+
static inline size_t sdslen(const sds s) {
|
46
|
+
struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
|
47
|
+
return sh->len;
|
48
|
+
}
|
49
|
+
|
50
|
+
static inline size_t sdsavail(const sds s) {
|
51
|
+
struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
|
52
|
+
return sh->free;
|
53
|
+
}
|
54
|
+
|
45
55
|
sds sdsnewlen(const void *init, size_t initlen);
|
46
56
|
sds sdsnew(const char *init);
|
47
57
|
sds sdsempty(void);
|
data/vendor/hiredis/test.c
CHANGED
@@ -54,6 +54,12 @@ static void test_format_commands(void) {
|
|
54
54
|
len == 4+4+(3+2)+4+(3+2)+4+(0+2));
|
55
55
|
free(cmd);
|
56
56
|
|
57
|
+
test("Format command with an empty string in between proper interpolations: ");
|
58
|
+
len = redisFormatCommand(&cmd,"SET %s %s","","foo");
|
59
|
+
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$0\r\n\r\n$3\r\nfoo\r\n",len) == 0 &&
|
60
|
+
len == 4+4+(3+2)+4+(0+2)+4+(3+2));
|
61
|
+
free(cmd);
|
62
|
+
|
57
63
|
test("Format command with %%b string interpolation: ");
|
58
64
|
len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3);
|
59
65
|
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 &&
|
@@ -262,75 +268,71 @@ static void test_blocking_connection(void) {
|
|
262
268
|
}
|
263
269
|
|
264
270
|
static void test_reply_reader(void) {
|
265
|
-
|
271
|
+
redisReader *reader;
|
266
272
|
void *reply;
|
267
|
-
char *err;
|
268
273
|
int ret;
|
269
274
|
|
270
275
|
test("Error handling in reply parser: ");
|
271
|
-
reader =
|
272
|
-
|
273
|
-
ret =
|
274
|
-
err = redisReplyReaderGetError(reader);
|
276
|
+
reader = redisReaderCreate();
|
277
|
+
redisReaderFeed(reader,(char*)"@foo\r\n",6);
|
278
|
+
ret = redisReaderGetReply(reader,NULL);
|
275
279
|
test_cond(ret == REDIS_ERR &&
|
276
|
-
strcasecmp(
|
277
|
-
|
280
|
+
strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0);
|
281
|
+
redisReaderFree(reader);
|
278
282
|
|
279
283
|
/* when the reply already contains multiple items, they must be free'd
|
280
284
|
* on an error. valgrind will bark when this doesn't happen. */
|
281
285
|
test("Memory cleanup in reply parser: ");
|
282
|
-
reader =
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
ret =
|
287
|
-
err = redisReplyReaderGetError(reader);
|
286
|
+
reader = redisReaderCreate();
|
287
|
+
redisReaderFeed(reader,(char*)"*2\r\n",4);
|
288
|
+
redisReaderFeed(reader,(char*)"$5\r\nhello\r\n",11);
|
289
|
+
redisReaderFeed(reader,(char*)"@foo\r\n",6);
|
290
|
+
ret = redisReaderGetReply(reader,NULL);
|
288
291
|
test_cond(ret == REDIS_ERR &&
|
289
|
-
strcasecmp(
|
290
|
-
|
292
|
+
strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0);
|
293
|
+
redisReaderFree(reader);
|
291
294
|
|
292
295
|
test("Set error on nested multi bulks with depth > 1: ");
|
293
|
-
reader =
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
ret =
|
298
|
-
err = redisReplyReaderGetError(reader);
|
296
|
+
reader = redisReaderCreate();
|
297
|
+
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
298
|
+
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
299
|
+
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
300
|
+
ret = redisReaderGetReply(reader,NULL);
|
299
301
|
test_cond(ret == REDIS_ERR &&
|
300
|
-
strncasecmp(
|
301
|
-
|
302
|
+
strncasecmp(reader->errstr,"No support for",14) == 0);
|
303
|
+
redisReaderFree(reader);
|
302
304
|
|
303
305
|
test("Works with NULL functions for reply: ");
|
304
|
-
reader =
|
305
|
-
|
306
|
-
|
307
|
-
ret =
|
306
|
+
reader = redisReaderCreate();
|
307
|
+
reader->fn = NULL;
|
308
|
+
redisReaderFeed(reader,(char*)"+OK\r\n",5);
|
309
|
+
ret = redisReaderGetReply(reader,&reply);
|
308
310
|
test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
|
309
|
-
|
311
|
+
redisReaderFree(reader);
|
310
312
|
|
311
313
|
test("Works when a single newline (\\r\\n) covers two calls to feed: ");
|
312
|
-
reader =
|
313
|
-
|
314
|
-
|
315
|
-
ret =
|
314
|
+
reader = redisReaderCreate();
|
315
|
+
reader->fn = NULL;
|
316
|
+
redisReaderFeed(reader,(char*)"+OK\r",4);
|
317
|
+
ret = redisReaderGetReply(reader,&reply);
|
316
318
|
assert(ret == REDIS_OK && reply == NULL);
|
317
|
-
|
318
|
-
ret =
|
319
|
+
redisReaderFeed(reader,(char*)"\n",1);
|
320
|
+
ret = redisReaderGetReply(reader,&reply);
|
319
321
|
test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
|
320
|
-
|
322
|
+
redisReaderFree(reader);
|
321
323
|
|
322
|
-
test("
|
323
|
-
reader =
|
324
|
-
|
325
|
-
|
326
|
-
ret =
|
324
|
+
test("Don't reset state after protocol error: ");
|
325
|
+
reader = redisReaderCreate();
|
326
|
+
reader->fn = NULL;
|
327
|
+
redisReaderFeed(reader,(char*)"x",1);
|
328
|
+
ret = redisReaderGetReply(reader,&reply);
|
327
329
|
assert(ret == REDIS_ERR);
|
328
|
-
ret =
|
329
|
-
test_cond(ret ==
|
330
|
+
ret = redisReaderGetReply(reader,&reply);
|
331
|
+
test_cond(ret == REDIS_ERR && reply == NULL);
|
330
332
|
}
|
331
333
|
|
332
334
|
static void test_throughput(void) {
|
333
|
-
int i;
|
335
|
+
int i, num;
|
334
336
|
long long t1, t2;
|
335
337
|
redisContext *c = blocking_context;
|
336
338
|
redisReply **replies;
|
@@ -339,28 +341,57 @@ static void test_throughput(void) {
|
|
339
341
|
for (i = 0; i < 500; i++)
|
340
342
|
freeReplyObject(redisCommand(c,"LPUSH mylist foo"));
|
341
343
|
|
342
|
-
|
344
|
+
num = 1000;
|
345
|
+
replies = malloc(sizeof(redisReply*)*num);
|
343
346
|
t1 = usec();
|
344
|
-
for (i = 0; i <
|
347
|
+
for (i = 0; i < num; i++) {
|
345
348
|
replies[i] = redisCommand(c,"PING");
|
346
349
|
assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS);
|
347
350
|
}
|
348
351
|
t2 = usec();
|
349
|
-
for (i = 0; i <
|
352
|
+
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
|
350
353
|
free(replies);
|
351
|
-
printf("\t(
|
354
|
+
printf("\t(%dx PING: %.3fs)\n", num, (t2-t1)/1000000.0);
|
352
355
|
|
353
|
-
replies = malloc(sizeof(redisReply*)*
|
356
|
+
replies = malloc(sizeof(redisReply*)*num);
|
354
357
|
t1 = usec();
|
355
|
-
for (i = 0; i <
|
358
|
+
for (i = 0; i < num; i++) {
|
356
359
|
replies[i] = redisCommand(c,"LRANGE mylist 0 499");
|
357
360
|
assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY);
|
358
361
|
assert(replies[i] != NULL && replies[i]->elements == 500);
|
359
362
|
}
|
360
363
|
t2 = usec();
|
361
|
-
for (i = 0; i <
|
364
|
+
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
|
365
|
+
free(replies);
|
366
|
+
printf("\t(%dx LRANGE with 500 elements: %.3fs)\n", num, (t2-t1)/1000000.0);
|
367
|
+
|
368
|
+
num = 10000;
|
369
|
+
replies = malloc(sizeof(redisReply*)*num);
|
370
|
+
for (i = 0; i < num; i++)
|
371
|
+
redisAppendCommand(c,"PING");
|
372
|
+
t1 = usec();
|
373
|
+
for (i = 0; i < num; i++) {
|
374
|
+
assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);
|
375
|
+
assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS);
|
376
|
+
}
|
377
|
+
t2 = usec();
|
378
|
+
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
|
379
|
+
free(replies);
|
380
|
+
printf("\t(%dx PING (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
|
381
|
+
|
382
|
+
replies = malloc(sizeof(redisReply*)*num);
|
383
|
+
for (i = 0; i < num; i++)
|
384
|
+
redisAppendCommand(c,"LRANGE mylist 0 499");
|
385
|
+
t1 = usec();
|
386
|
+
for (i = 0; i < num; i++) {
|
387
|
+
assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);
|
388
|
+
assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY);
|
389
|
+
assert(replies[i] != NULL && replies[i]->elements == 500);
|
390
|
+
}
|
391
|
+
t2 = usec();
|
392
|
+
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
|
362
393
|
free(replies);
|
363
|
-
printf("\t(
|
394
|
+
printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
|
364
395
|
}
|
365
396
|
|
366
397
|
static void cleanup(void) {
|