hiredis 0.4.5 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|