hiredis 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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) {
|