hiredis 0.4.5 → 0.5.0
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.
- checksums.yaml +7 -0
- data/Rakefile +7 -1
- data/ext/hiredis_ext/connection.c +55 -24
- data/ext/hiredis_ext/extconf.rb +13 -2
- data/ext/hiredis_ext/hiredis_ext.c +2 -0
- data/ext/hiredis_ext/hiredis_ext.h +7 -0
- data/ext/hiredis_ext/reader.c +2 -0
- data/lib/hiredis/version.rb +1 -1
- data/vendor/hiredis/Makefile +2 -2
- data/vendor/hiredis/async.c +29 -11
- data/vendor/hiredis/hiredis.c +12 -10
- data/vendor/hiredis/hiredis.h +9 -3
- data/vendor/hiredis/net.c +24 -12
- data/vendor/hiredis/test.c +10 -7
- metadata +44 -28
- data/lib/hiredis/errors.rb +0 -5
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d434e6b09126833f2a6dcf82385105de08f629dd
|
4
|
+
data.tar.gz: 2d668be20b90a469f8f905f5915868e143cf5ae4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 637b4bc535ceca4c61aff1f3a1d7456819dc9abdfc934618eac3f8c66b2d791a8106197c552ee6a8635611bcb8588cebb4d183a0de60e21ad4b8b10a29f494eb
|
7
|
+
data.tar.gz: 5170e3ae0d95f728b2ca8566717de256aba4a4e3f804618a968ce81bbe8e3fca5b57942fe3d050441c10fe44aaf3f3c140ed7d8c99bc45e153033cb34884ad99
|
data/Rakefile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "bundler"
|
2
2
|
Bundler::GemHelper.install_tasks
|
3
3
|
|
4
|
+
require "rbconfig"
|
4
5
|
require "rake/testtask"
|
5
6
|
require "rake/extensiontask"
|
6
7
|
|
@@ -18,7 +19,12 @@ unless defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
|
|
18
19
|
if !File.directory?("vendor/hiredis/.git")
|
19
20
|
system("git submodule update --init")
|
20
21
|
end
|
21
|
-
|
22
|
+
RbConfig::CONFIG['configure_args'] =~ /with-make-prog\=(\w+)/
|
23
|
+
make_program = $1 || ENV['make']
|
24
|
+
unless make_program then
|
25
|
+
make_program = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make'
|
26
|
+
end
|
27
|
+
system("cd vendor/hiredis && #{make_program} clean")
|
22
28
|
end
|
23
29
|
end
|
24
30
|
|
@@ -72,24 +72,58 @@ static VALUE connection_parent_context_alloc(VALUE klass) {
|
|
72
72
|
return Data_Wrap_Struct(klass, parent_context_mark, parent_context_free, pc);
|
73
73
|
}
|
74
74
|
|
75
|
+
|
76
|
+
/*
|
77
|
+
* The rb_fdset_t API was introduced in Ruby 1.9.1. The rb_fd_thread_select
|
78
|
+
* function was introduced in a later version. Therefore, there are one more
|
79
|
+
* versions where we cannot simply test HAVE_RB_FD_INIT and be done, we have to
|
80
|
+
* explicitly test for HAVE_RB_THREAD_FD_SELECT (also see extconf.rb).
|
81
|
+
*/
|
82
|
+
#ifdef HAVE_RB_THREAD_FD_SELECT
|
83
|
+
typedef rb_fdset_t _fdset_t;
|
84
|
+
#define _fd_zero(f) rb_fd_zero(f)
|
85
|
+
#define _fd_set(n, f) rb_fd_set(n, f)
|
86
|
+
#define _fd_clr(n, f) rb_fd_clr(n, f)
|
87
|
+
#define _fd_isset(n, f) rb_fd_isset(n, f)
|
88
|
+
#define _fd_copy(d, s, n) rb_fd_copy(d, s, n)
|
89
|
+
#define _fd_ptr(f) rb_fd_ptr(f)
|
90
|
+
#define _fd_init(f) rb_fd_init(f)
|
91
|
+
#define _fd_term(f) rb_fd_term(f)
|
92
|
+
#define _fd_max(f) rb_fd_max(f)
|
93
|
+
#define _thread_fd_select(n, r, w, e, t) rb_thread_fd_select(n, r, w, e, t)
|
94
|
+
#else
|
95
|
+
typedef fd_set _fdset_t;
|
96
|
+
#define _fd_zero(f) FD_ZERO(f)
|
97
|
+
#define _fd_set(n, f) FD_SET(n, f)
|
98
|
+
#define _fd_clr(n, f) FD_CLR(n, f)
|
99
|
+
#define _fd_isset(n, f) FD_ISSET(n, f)
|
100
|
+
#define _fd_copy(d, s, n) (*(d) = *(s))
|
101
|
+
#define _fd_ptr(f) (f)
|
102
|
+
#define _fd_init(f) FD_ZERO(f)
|
103
|
+
#define _fd_term(f) (void)(f)
|
104
|
+
#define _fd_max(f) FD_SETSIZE
|
105
|
+
#define _thread_fd_select(n, r, w, e, t) rb_thread_select(n, r, w, e, t)
|
106
|
+
#endif
|
107
|
+
|
75
108
|
static int __wait_readable(int fd, const struct timeval *timeout, int *isset) {
|
76
109
|
struct timeval to;
|
77
110
|
struct timeval *toptr = NULL;
|
78
|
-
fd_set fds;
|
79
|
-
FD_ZERO(&fds);
|
80
|
-
FD_SET(fd, &fds);
|
81
111
|
|
82
|
-
|
112
|
+
_fdset_t fds;
|
113
|
+
_fd_init(&fds);
|
114
|
+
_fd_set(fd, &fds);
|
115
|
+
|
116
|
+
/* rb_fd_select modifies the passed timeval, so we pass a copy */
|
83
117
|
if (timeout != NULL) {
|
84
118
|
memcpy(&to, timeout, sizeof(to));
|
85
119
|
toptr = &to;
|
86
120
|
}
|
87
121
|
|
88
|
-
if (
|
122
|
+
if (_thread_fd_select(fd + 1, &fds, NULL, NULL, toptr) < 0) {
|
89
123
|
return -1;
|
90
124
|
}
|
91
125
|
|
92
|
-
if (
|
126
|
+
if (_fd_isset(fd, &fds) && isset) {
|
93
127
|
*isset = 1;
|
94
128
|
}
|
95
129
|
|
@@ -99,21 +133,22 @@ static int __wait_readable(int fd, const struct timeval *timeout, int *isset) {
|
|
99
133
|
static int __wait_writable(int fd, const struct timeval *timeout, int *isset) {
|
100
134
|
struct timeval to;
|
101
135
|
struct timeval *toptr = NULL;
|
102
|
-
fd_set fds;
|
103
|
-
FD_ZERO(&fds);
|
104
|
-
FD_SET(fd, &fds);
|
105
136
|
|
106
|
-
|
137
|
+
_fdset_t fds;
|
138
|
+
_fd_init(&fds);
|
139
|
+
_fd_set(fd, &fds);
|
140
|
+
|
141
|
+
/* rb_fd_select modifies the passed timeval, so we pass a copy */
|
107
142
|
if (timeout != NULL) {
|
108
143
|
memcpy(&to, timeout, sizeof(to));
|
109
144
|
toptr = &to;
|
110
145
|
}
|
111
146
|
|
112
|
-
if (
|
147
|
+
if (_thread_fd_select(fd + 1, NULL, &fds, NULL, toptr) < 0) {
|
113
148
|
return -1;
|
114
149
|
}
|
115
150
|
|
116
|
-
if (
|
151
|
+
if (_fd_isset(fd, &fds) && isset) {
|
117
152
|
*isset = 1;
|
118
153
|
}
|
119
154
|
|
@@ -124,6 +159,9 @@ static VALUE connection_generic_connect(VALUE self, redisContext *c, VALUE arg_t
|
|
124
159
|
redisParentContext *pc;
|
125
160
|
struct timeval tv;
|
126
161
|
struct timeval *timeout = NULL;
|
162
|
+
int writable = 0;
|
163
|
+
int optval = 0;
|
164
|
+
socklen_t optlen = sizeof(optval);
|
127
165
|
|
128
166
|
Data_Get_Struct(self,redisParentContext,pc);
|
129
167
|
|
@@ -158,7 +196,6 @@ static VALUE connection_generic_connect(VALUE self, redisContext *c, VALUE arg_t
|
|
158
196
|
}
|
159
197
|
|
160
198
|
/* Wait for socket to become writable */
|
161
|
-
int writable = 0;
|
162
199
|
if (__wait_writable(c->fd, timeout, &writable) < 0) {
|
163
200
|
goto sys_fail;
|
164
201
|
}
|
@@ -169,8 +206,6 @@ static VALUE connection_generic_connect(VALUE self, redisContext *c, VALUE arg_t
|
|
169
206
|
}
|
170
207
|
|
171
208
|
/* Check for socket error */
|
172
|
-
int optval = 0;
|
173
|
-
socklen_t optlen = sizeof(optval);
|
174
209
|
if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0) {
|
175
210
|
goto sys_fail;
|
176
211
|
}
|
@@ -191,7 +226,6 @@ sys_fail:
|
|
191
226
|
}
|
192
227
|
|
193
228
|
static VALUE connection_connect(int argc, VALUE *argv, VALUE self) {
|
194
|
-
redisParentContext *pc;
|
195
229
|
redisContext *c;
|
196
230
|
VALUE arg_host = Qnil;
|
197
231
|
VALUE arg_port = Qnil;
|
@@ -213,13 +247,11 @@ static VALUE connection_connect(int argc, VALUE *argv, VALUE self) {
|
|
213
247
|
rb_raise(rb_eArgError, "invalid number of arguments");
|
214
248
|
}
|
215
249
|
|
216
|
-
Data_Get_Struct(self,redisParentContext,pc);
|
217
250
|
c = redisConnectNonBlock(StringValuePtr(arg_host), NUM2INT(arg_port));
|
218
251
|
return connection_generic_connect(self,c,arg_timeout);
|
219
252
|
}
|
220
253
|
|
221
254
|
static VALUE connection_connect_unix(int argc, VALUE *argv, VALUE self) {
|
222
|
-
redisParentContext *pc;
|
223
255
|
redisContext *c;
|
224
256
|
VALUE arg_path = Qnil;
|
225
257
|
VALUE arg_timeout = Qnil;
|
@@ -239,7 +271,6 @@ static VALUE connection_connect_unix(int argc, VALUE *argv, VALUE self) {
|
|
239
271
|
rb_raise(rb_eArgError, "invalid number of arguments");
|
240
272
|
}
|
241
273
|
|
242
|
-
Data_Get_Struct(self,redisParentContext,pc);
|
243
274
|
c = redisConnectUnixNonBlock(StringValuePtr(arg_path));
|
244
275
|
return connection_generic_connect(self,c,arg_timeout);
|
245
276
|
}
|
@@ -265,7 +296,6 @@ static VALUE connection_disconnect(VALUE self) {
|
|
265
296
|
static VALUE connection_write(VALUE self, VALUE command) {
|
266
297
|
redisParentContext *pc;
|
267
298
|
int argc;
|
268
|
-
VALUE *args;
|
269
299
|
char **argv = NULL;
|
270
300
|
size_t *alen = NULL;
|
271
301
|
int i;
|
@@ -280,15 +310,15 @@ static VALUE connection_write(VALUE self, VALUE command) {
|
|
280
310
|
rb_raise(rb_eRuntimeError,"%s","not connected");
|
281
311
|
|
282
312
|
argc = (int)RARRAY_LEN(command);
|
283
|
-
args = RARRAY_PTR(command);
|
284
313
|
argv = malloc(argc*sizeof(char*));
|
285
314
|
alen = malloc(argc*sizeof(size_t));
|
286
315
|
for (i = 0; i < argc; i++) {
|
287
316
|
/* Replace arguments in the arguments array to prevent their string
|
288
317
|
* equivalents to be garbage collected before this loop is done. */
|
289
|
-
|
290
|
-
|
291
|
-
|
318
|
+
VALUE entry = rb_obj_as_string(rb_ary_entry(command, i));
|
319
|
+
rb_ary_store(command, i, entry);
|
320
|
+
argv[i] = RSTRING_PTR(entry);
|
321
|
+
alen[i] = RSTRING_LEN(entry);
|
292
322
|
}
|
293
323
|
redisAppendCommandArgv(pc->context,argc,(const char**)argv,alen);
|
294
324
|
free(argv);
|
@@ -459,6 +489,7 @@ static VALUE connection_fileno(VALUE self) {
|
|
459
489
|
VALUE klass_connection;
|
460
490
|
void InitConnection(VALUE mod) {
|
461
491
|
klass_connection = rb_define_class_under(mod, "Connection", rb_cObject);
|
492
|
+
rb_global_variable(&klass_connection);
|
462
493
|
rb_define_alloc_func(klass_connection, connection_parent_context_alloc);
|
463
494
|
rb_define_method(klass_connection, "connect", connection_connect, -1);
|
464
495
|
rb_define_method(klass_connection, "connect_unix", connection_connect_unix, -1);
|
data/ext/hiredis_ext/extconf.rb
CHANGED
@@ -2,16 +2,27 @@ require 'mkmf'
|
|
2
2
|
|
3
3
|
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
4
4
|
|
5
|
-
hiredis_dir = File.
|
5
|
+
hiredis_dir = File.join(File.dirname(__FILE__), %w{.. .. vendor hiredis})
|
6
6
|
unless File.directory?(hiredis_dir)
|
7
7
|
STDERR.puts "vendor/hiredis missing, please checkout its submodule..."
|
8
8
|
exit 1
|
9
9
|
end
|
10
10
|
|
11
|
+
RbConfig::CONFIG['configure_args'] =~ /with-make-prog\=(\w+)/
|
12
|
+
make_program = $1 || ENV['make']
|
13
|
+
unless make_program then
|
14
|
+
make_program = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make'
|
15
|
+
end
|
16
|
+
|
11
17
|
# Make sure hiredis is built...
|
12
|
-
|
18
|
+
Dir.chdir(hiredis_dir) do
|
19
|
+
success = system("#{make_program} static")
|
20
|
+
raise "Building hiredis failed" if !success
|
21
|
+
end
|
13
22
|
|
14
23
|
# Statically link to hiredis (mkmf can't do this for us)
|
15
24
|
$CFLAGS << " -I#{hiredis_dir}"
|
16
25
|
$LDFLAGS << " #{hiredis_dir}/libhiredis.a"
|
26
|
+
|
27
|
+
have_func("rb_thread_fd_select")
|
17
28
|
create_makefile('hiredis/ext/hiredis_ext')
|
@@ -8,6 +8,8 @@ VALUE mod_ext;
|
|
8
8
|
void Init_hiredis_ext() {
|
9
9
|
mod_hiredis = rb_define_module("Hiredis");
|
10
10
|
mod_ext = rb_define_module_under(mod_hiredis,"Ext");
|
11
|
+
rb_global_variable(&mod_hiredis);
|
12
|
+
rb_global_variable(&mod_ext);
|
11
13
|
InitReader(mod_ext);
|
12
14
|
InitConnection(mod_ext);
|
13
15
|
}
|
@@ -1,6 +1,13 @@
|
|
1
1
|
#ifndef __HIREDIS_EXT_H
|
2
2
|
#define __HIREDIS_EXT_H
|
3
3
|
|
4
|
+
/* Defined for Rubinius. This indicates a char* obtained
|
5
|
+
* through RSTRING_PTR is never modified in place. With this
|
6
|
+
* define Rubinius can disable the slow copy back mechanisms
|
7
|
+
* to make sure strings are updated at the Ruby side.
|
8
|
+
*/
|
9
|
+
#define RSTRING_NOT_MODIFIED
|
10
|
+
|
4
11
|
#include "hiredis.h"
|
5
12
|
#include "ruby.h"
|
6
13
|
|
data/ext/hiredis_ext/reader.c
CHANGED
@@ -97,6 +97,7 @@ static VALUE reader_gets(VALUE klass) {
|
|
97
97
|
VALUE klass_reader;
|
98
98
|
void InitReader(VALUE mod) {
|
99
99
|
klass_reader = rb_define_class_under(mod, "Reader", rb_cObject);
|
100
|
+
rb_global_variable(&klass_reader);
|
100
101
|
rb_define_alloc_func(klass_reader, reader_allocate);
|
101
102
|
rb_define_method(klass_reader, "feed", reader_feed, 1);
|
102
103
|
rb_define_method(klass_reader, "gets", reader_gets, 0);
|
@@ -108,6 +109,7 @@ void InitReader(VALUE mod) {
|
|
108
109
|
enc_klass = rb_const_get(rb_cObject, rb_intern("Encoding"));
|
109
110
|
enc_default_external = rb_intern("default_external");
|
110
111
|
str_force_encoding = rb_intern("force_encoding");
|
112
|
+
rb_global_variable(&enc_klass);
|
111
113
|
} else {
|
112
114
|
enc_default_external = 0;
|
113
115
|
}
|
data/lib/hiredis/version.rb
CHANGED
data/vendor/hiredis/Makefile
CHANGED
@@ -15,8 +15,8 @@ CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
|
|
15
15
|
OPTIMIZATION?=-O3
|
16
16
|
WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings
|
17
17
|
DEBUG?= -g -ggdb
|
18
|
-
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG)
|
19
|
-
REAL_LDFLAGS=$(LDFLAGS)
|
18
|
+
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG) $(ARCH)
|
19
|
+
REAL_LDFLAGS=$(LDFLAGS) $(ARCH)
|
20
20
|
|
21
21
|
DYLIBSUFFIX=so
|
22
22
|
STLIBSUFFIX=a
|
data/vendor/hiredis/async.c
CHANGED
@@ -372,6 +372,11 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
|
|
372
372
|
__redisAsyncDisconnect(ac);
|
373
373
|
return;
|
374
374
|
}
|
375
|
+
|
376
|
+
/* If monitor mode, repush callback */
|
377
|
+
if(c->flags & REDIS_MONITORING) {
|
378
|
+
__redisPushCallback(&ac->replies,&cb);
|
379
|
+
}
|
375
380
|
|
376
381
|
/* When the connection is not being disconnected, simply stop
|
377
382
|
* trying to get replies and wait for the next loop tick. */
|
@@ -381,22 +386,31 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
|
|
381
386
|
/* Even if the context is subscribed, pending regular callbacks will
|
382
387
|
* get a reply before pub/sub messages arrive. */
|
383
388
|
if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) {
|
384
|
-
/*
|
385
|
-
*
|
386
|
-
*
|
387
|
-
*
|
388
|
-
*
|
389
|
-
*
|
390
|
-
*
|
391
|
-
|
389
|
+
/*
|
390
|
+
* A spontaneous reply in a not-subscribed context can be the error
|
391
|
+
* reply that is sent when a new connection exceeds the maximum
|
392
|
+
* number of allowed connections on the server side.
|
393
|
+
*
|
394
|
+
* This is seen as an error instead of a regular reply because the
|
395
|
+
* server closes the connection after sending it.
|
396
|
+
*
|
397
|
+
* To prevent the error from being overwritten by an EOF error the
|
398
|
+
* connection is closed here. See issue #43.
|
399
|
+
*
|
400
|
+
* Another possibility is that the server is loading its dataset.
|
401
|
+
* In this case we also want to close the connection, and have the
|
402
|
+
* user wait until the server is ready to take our request.
|
403
|
+
*/
|
404
|
+
if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) {
|
392
405
|
c->err = REDIS_ERR_OTHER;
|
393
406
|
snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str);
|
394
407
|
__redisAsyncDisconnect(ac);
|
395
408
|
return;
|
396
409
|
}
|
397
|
-
/* No more regular callbacks and no errors, the context *must* be subscribed. */
|
398
|
-
assert(c->flags & REDIS_SUBSCRIBED);
|
399
|
-
|
410
|
+
/* No more regular callbacks and no errors, the context *must* be subscribed or monitoring. */
|
411
|
+
assert((c->flags & REDIS_SUBSCRIBED || c->flags & REDIS_MONITORING));
|
412
|
+
if(c->flags & REDIS_SUBSCRIBED)
|
413
|
+
__redisGetSubscribeCallback(ac,reply,&cb);
|
400
414
|
}
|
401
415
|
|
402
416
|
if (cb.fn != NULL) {
|
@@ -557,6 +571,10 @@ static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
|
|
557
571
|
/* (P)UNSUBSCRIBE does not have its own response: every channel or
|
558
572
|
* pattern that is unsubscribed will receive a message. This means we
|
559
573
|
* should not append a callback function for this command. */
|
574
|
+
} else if(strncasecmp(cstr,"monitor\r\n",9) == 0) {
|
575
|
+
/* Set monitor flag and push callback */
|
576
|
+
c->flags |= REDIS_MONITORING;
|
577
|
+
__redisPushCallback(&ac->replies,&cb);
|
560
578
|
} else {
|
561
579
|
if (c->flags & REDIS_SUBSCRIBED)
|
562
580
|
/* This will likely result in an error reply, but it needs to be
|
data/vendor/hiredis/hiredis.c
CHANGED
@@ -446,10 +446,10 @@ static int processMultiBulkItem(redisReader *r) {
|
|
446
446
|
long elements;
|
447
447
|
int root = 0;
|
448
448
|
|
449
|
-
/* Set error for nested multi bulks with depth >
|
450
|
-
if (r->ridx ==
|
449
|
+
/* Set error for nested multi bulks with depth > 7 */
|
450
|
+
if (r->ridx == 8) {
|
451
451
|
__redisReaderSetError(r,REDIS_ERR_PROTOCOL,
|
452
|
-
"No support for nested multi bulk replies with depth >
|
452
|
+
"No support for nested multi bulk replies with depth > 7");
|
453
453
|
return REDIS_ERR;
|
454
454
|
}
|
455
455
|
|
@@ -564,6 +564,7 @@ redisReader *redisReaderCreate(void) {
|
|
564
564
|
r->errstr[0] = '\0';
|
565
565
|
r->fn = &defaultFunctions;
|
566
566
|
r->buf = sdsempty();
|
567
|
+
r->maxbuf = REDIS_READER_MAX_BUF;
|
567
568
|
if (r->buf == NULL) {
|
568
569
|
free(r);
|
569
570
|
return NULL;
|
@@ -591,7 +592,7 @@ int redisReaderFeed(redisReader *r, const char *buf, size_t len) {
|
|
591
592
|
/* Copy the provided buffer. */
|
592
593
|
if (buf != NULL && len >= 1) {
|
593
594
|
/* Destroy internal buffer when it is empty and is quite large. */
|
594
|
-
if (r->len == 0 && sdsavail(r->buf) >
|
595
|
+
if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {
|
595
596
|
sdsfree(r->buf);
|
596
597
|
r->buf = sdsempty();
|
597
598
|
r->pos = 0;
|
@@ -749,6 +750,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
|
749
750
|
default:
|
750
751
|
/* Try to detect printf format */
|
751
752
|
{
|
753
|
+
static const char intfmts[] = "diouxX";
|
752
754
|
char _format[16];
|
753
755
|
const char *_p = c+1;
|
754
756
|
size_t _l = 0;
|
@@ -774,7 +776,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
|
774
776
|
va_copy(_cpy,ap);
|
775
777
|
|
776
778
|
/* Integer conversion (without modifiers) */
|
777
|
-
if (strchr(
|
779
|
+
if (strchr(intfmts,*_p) != NULL) {
|
778
780
|
va_arg(ap,int);
|
779
781
|
goto fmt_valid;
|
780
782
|
}
|
@@ -788,7 +790,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
|
788
790
|
/* Size: char */
|
789
791
|
if (_p[0] == 'h' && _p[1] == 'h') {
|
790
792
|
_p += 2;
|
791
|
-
if (*_p != '\0' && strchr(
|
793
|
+
if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
|
792
794
|
va_arg(ap,int); /* char gets promoted to int */
|
793
795
|
goto fmt_valid;
|
794
796
|
}
|
@@ -798,7 +800,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
|
798
800
|
/* Size: short */
|
799
801
|
if (_p[0] == 'h') {
|
800
802
|
_p += 1;
|
801
|
-
if (*_p != '\0' && strchr(
|
803
|
+
if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
|
802
804
|
va_arg(ap,int); /* short gets promoted to int */
|
803
805
|
goto fmt_valid;
|
804
806
|
}
|
@@ -808,7 +810,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
|
808
810
|
/* Size: long long */
|
809
811
|
if (_p[0] == 'l' && _p[1] == 'l') {
|
810
812
|
_p += 2;
|
811
|
-
if (*_p != '\0' && strchr(
|
813
|
+
if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
|
812
814
|
va_arg(ap,long long);
|
813
815
|
goto fmt_valid;
|
814
816
|
}
|
@@ -818,7 +820,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
|
818
820
|
/* Size: long */
|
819
821
|
if (_p[0] == 'l') {
|
820
822
|
_p += 1;
|
821
|
-
if (*_p != '\0' && strchr(
|
823
|
+
if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
|
822
824
|
va_arg(ap,long);
|
823
825
|
goto fmt_valid;
|
824
826
|
}
|
@@ -1066,7 +1068,7 @@ int redisSetTimeout(redisContext *c, struct timeval tv) {
|
|
1066
1068
|
* After this function is called, you may use redisContextReadReply to
|
1067
1069
|
* see if there is a reply available. */
|
1068
1070
|
int redisBufferRead(redisContext *c) {
|
1069
|
-
char buf[
|
1071
|
+
char buf[1024*16];
|
1070
1072
|
int nread;
|
1071
1073
|
|
1072
1074
|
/* Return early when the context has seen an error. */
|
data/vendor/hiredis/hiredis.h
CHANGED
@@ -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 11
|
40
|
+
#define HIREDIS_PATCH 0
|
41
41
|
|
42
42
|
#define REDIS_ERR -1
|
43
43
|
#define REDIS_OK 0
|
@@ -76,6 +76,9 @@
|
|
76
76
|
/* Flag that is set when the async context has one or more subscriptions. */
|
77
77
|
#define REDIS_SUBSCRIBED 0x20
|
78
78
|
|
79
|
+
/* Flag that is set when monitor mode is active */
|
80
|
+
#define REDIS_MONITORING 0x40
|
81
|
+
|
79
82
|
#define REDIS_REPLY_STRING 1
|
80
83
|
#define REDIS_REPLY_ARRAY 2
|
81
84
|
#define REDIS_REPLY_INTEGER 3
|
@@ -83,6 +86,8 @@
|
|
83
86
|
#define REDIS_REPLY_STATUS 5
|
84
87
|
#define REDIS_REPLY_ERROR 6
|
85
88
|
|
89
|
+
#define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */
|
90
|
+
|
86
91
|
#ifdef __cplusplus
|
87
92
|
extern "C" {
|
88
93
|
#endif
|
@@ -122,8 +127,9 @@ typedef struct redisReader {
|
|
122
127
|
char *buf; /* Read buffer */
|
123
128
|
size_t pos; /* Buffer cursor */
|
124
129
|
size_t len; /* Buffer length */
|
130
|
+
size_t maxbuf; /* Max length of unused buffer */
|
125
131
|
|
126
|
-
redisReadTask rstack[
|
132
|
+
redisReadTask rstack[9];
|
127
133
|
int ridx; /* Index of current read task */
|
128
134
|
void *reply; /* Temporary reply pointer */
|
129
135
|
|
data/vendor/hiredis/net.c
CHANGED
@@ -45,6 +45,8 @@
|
|
45
45
|
#include <errno.h>
|
46
46
|
#include <stdarg.h>
|
47
47
|
#include <stdio.h>
|
48
|
+
#include <poll.h>
|
49
|
+
#include <limits.h>
|
48
50
|
|
49
51
|
#include "net.h"
|
50
52
|
#include "sds.h"
|
@@ -121,28 +123,38 @@ static int redisSetTcpNoDelay(redisContext *c, int fd) {
|
|
121
123
|
return REDIS_OK;
|
122
124
|
}
|
123
125
|
|
126
|
+
#define __MAX_MSEC (((LONG_MAX) - 999) / 1000)
|
127
|
+
|
124
128
|
static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *timeout) {
|
125
|
-
struct
|
126
|
-
|
127
|
-
|
129
|
+
struct pollfd wfd[1];
|
130
|
+
long msec;
|
131
|
+
|
132
|
+
msec = -1;
|
133
|
+
wfd[0].fd = fd;
|
134
|
+
wfd[0].events = POLLOUT;
|
128
135
|
|
129
136
|
/* Only use timeout when not NULL. */
|
130
137
|
if (timeout != NULL) {
|
131
|
-
|
132
|
-
|
138
|
+
if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) {
|
139
|
+
close(fd);
|
140
|
+
return REDIS_ERR;
|
141
|
+
}
|
142
|
+
|
143
|
+
msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000);
|
144
|
+
|
145
|
+
if (msec < 0 || msec > INT_MAX) {
|
146
|
+
msec = INT_MAX;
|
147
|
+
}
|
133
148
|
}
|
134
149
|
|
135
150
|
if (errno == EINPROGRESS) {
|
136
|
-
|
137
|
-
FD_SET(fd, &wfd);
|
151
|
+
int res;
|
138
152
|
|
139
|
-
if (
|
140
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"
|
153
|
+
if ((res = poll(wfd, 1, msec)) == -1) {
|
154
|
+
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
|
141
155
|
close(fd);
|
142
156
|
return REDIS_ERR;
|
143
|
-
}
|
144
|
-
|
145
|
-
if (!FD_ISSET(fd, &wfd)) {
|
157
|
+
} else if (res == 0) {
|
146
158
|
errno = ETIMEDOUT;
|
147
159
|
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
148
160
|
close(fd);
|
data/vendor/hiredis/test.c
CHANGED
@@ -177,7 +177,7 @@ static void test_format_commands(void) {
|
|
177
177
|
FLOAT_WIDTH_TEST(double);
|
178
178
|
|
179
179
|
test("Format command with invalid printf format: ");
|
180
|
-
len = redisFormatCommand(&cmd,"key:%08p %b",1234,"foo",3);
|
180
|
+
len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",3);
|
181
181
|
test_cond(len == -1);
|
182
182
|
|
183
183
|
const char *argv[3];
|
@@ -204,6 +204,7 @@ static void test_reply_reader(void) {
|
|
204
204
|
redisReader *reader;
|
205
205
|
void *reply;
|
206
206
|
int ret;
|
207
|
+
int i;
|
207
208
|
|
208
209
|
test("Error handling in reply parser: ");
|
209
210
|
reader = redisReaderCreate();
|
@@ -225,12 +226,13 @@ static void test_reply_reader(void) {
|
|
225
226
|
strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0);
|
226
227
|
redisReaderFree(reader);
|
227
228
|
|
228
|
-
test("Set error on nested multi bulks with depth >
|
229
|
+
test("Set error on nested multi bulks with depth > 7: ");
|
229
230
|
reader = redisReaderCreate();
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
231
|
+
|
232
|
+
for (i = 0; i < 9; i++) {
|
233
|
+
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
234
|
+
}
|
235
|
+
|
234
236
|
ret = redisReaderGetReply(reader,NULL);
|
235
237
|
test_cond(ret == REDIS_ERR &&
|
236
238
|
strncasecmp(reader->errstr,"No support for",14) == 0);
|
@@ -283,7 +285,8 @@ static void test_blocking_connection_errors(void) {
|
|
283
285
|
test("Returns error when host cannot be resolved: ");
|
284
286
|
c = redisConnect((char*)"idontexist.local", 6379);
|
285
287
|
test_cond(c->err == REDIS_ERR_OTHER &&
|
286
|
-
strcmp(c->errstr,"
|
288
|
+
(strcmp(c->errstr,"Name or service not known") == 0 ||
|
289
|
+
strcmp(c->errstr,"Can't resolve: idontexist.local") == 0));
|
287
290
|
redisFree(c);
|
288
291
|
|
289
292
|
test("Returns error when the port is not open: ");
|
metadata
CHANGED
@@ -1,28 +1,45 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hiredis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.5.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Pieter Noordhuis
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-03-27 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '10.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '10.0'
|
14
27
|
- !ruby/object:Gem::Dependency
|
15
28
|
name: rake-compiler
|
16
|
-
requirement:
|
17
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
18
30
|
requirements:
|
19
31
|
- - ~>
|
20
32
|
- !ruby/object:Gem::Version
|
21
33
|
version: 0.7.1
|
22
34
|
type: :development
|
23
35
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
-
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.7.1
|
41
|
+
description: Ruby wrapper for hiredis (protocol serialization/deserialization and
|
42
|
+
blocking I/O)
|
26
43
|
email:
|
27
44
|
- pcnoordhuis@gmail.com
|
28
45
|
executables: []
|
@@ -31,57 +48,56 @@ extensions:
|
|
31
48
|
extra_rdoc_files: []
|
32
49
|
files:
|
33
50
|
- ext/hiredis_ext/extconf.rb
|
34
|
-
- ext/hiredis_ext/connection.c
|
35
51
|
- ext/hiredis_ext/hiredis_ext.c
|
36
52
|
- ext/hiredis_ext/reader.c
|
53
|
+
- ext/hiredis_ext/connection.c
|
37
54
|
- ext/hiredis_ext/hiredis_ext.h
|
38
55
|
- vendor/hiredis/async.c
|
39
|
-
- vendor/hiredis/dict.c
|
40
56
|
- vendor/hiredis/hiredis.c
|
57
|
+
- vendor/hiredis/test.c
|
58
|
+
- vendor/hiredis/dict.c
|
41
59
|
- vendor/hiredis/net.c
|
42
60
|
- vendor/hiredis/sds.c
|
43
|
-
- vendor/hiredis/test.c
|
44
|
-
- vendor/hiredis/async.h
|
45
|
-
- vendor/hiredis/dict.h
|
46
61
|
- vendor/hiredis/fmacros.h
|
47
|
-
- vendor/hiredis/hiredis.h
|
48
|
-
- vendor/hiredis/net.h
|
49
62
|
- vendor/hiredis/sds.h
|
63
|
+
- vendor/hiredis/dict.h
|
64
|
+
- vendor/hiredis/async.h
|
65
|
+
- vendor/hiredis/net.h
|
66
|
+
- vendor/hiredis/hiredis.h
|
50
67
|
- vendor/hiredis/COPYING
|
51
68
|
- vendor/hiredis/Makefile
|
52
|
-
- lib/hiredis/connection.rb
|
53
|
-
- lib/hiredis/errors.rb
|
54
|
-
- lib/hiredis/ext/connection.rb
|
55
|
-
- lib/hiredis/ext/reader.rb
|
56
69
|
- lib/hiredis/reader.rb
|
57
|
-
- lib/hiredis/ruby/connection.rb
|
58
|
-
- lib/hiredis/ruby/reader.rb
|
59
70
|
- lib/hiredis/version.rb
|
71
|
+
- lib/hiredis/ruby/reader.rb
|
72
|
+
- lib/hiredis/ruby/connection.rb
|
73
|
+
- lib/hiredis/ext/reader.rb
|
74
|
+
- lib/hiredis/ext/connection.rb
|
75
|
+
- lib/hiredis/connection.rb
|
60
76
|
- lib/hiredis.rb
|
61
77
|
- COPYING
|
62
78
|
- Rakefile
|
63
|
-
homepage: http://github.com/
|
79
|
+
homepage: http://github.com/redis/hiredis-rb
|
64
80
|
licenses: []
|
81
|
+
metadata: {}
|
65
82
|
post_install_message:
|
66
83
|
rdoc_options: []
|
67
84
|
require_paths:
|
68
85
|
- lib
|
69
86
|
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
-
none: false
|
71
87
|
requirements:
|
72
|
-
- -
|
88
|
+
- - '>='
|
73
89
|
- !ruby/object:Gem::Version
|
74
90
|
version: '0'
|
75
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
-
none: false
|
77
92
|
requirements:
|
78
|
-
- -
|
93
|
+
- - '>='
|
79
94
|
- !ruby/object:Gem::Version
|
80
95
|
version: '0'
|
81
96
|
requirements: []
|
82
97
|
rubyforge_project:
|
83
|
-
rubygems_version:
|
98
|
+
rubygems_version: 2.0.14
|
84
99
|
signing_key:
|
85
|
-
specification_version:
|
86
|
-
summary: Ruby
|
100
|
+
specification_version: 4
|
101
|
+
summary: Ruby wrapper for hiredis (protocol serialization/deserialization and blocking
|
102
|
+
I/O)
|
87
103
|
test_files: []
|