hiredis-client 0.5.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/redis_client/hiredis/hiredis_connection.c +70 -29
- data/lib/redis_client/hiredis_connection.rb +5 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a1e6c581e8cdaf2e39e684939f9747503d80f2573065d18a43b9002a83005f3
|
4
|
+
data.tar.gz: d3a82df8aa27552818f25757fadc2e9789cecd2e149051a05379f6361f618bab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b06e2e1ace5bac902ce44d25e1739f4597ef2b22604c34ba769b79c261fb0e72f31b6e94fe7c7dbd7d950f3bed692bac113cf60bdb7fc11f21c8ac28ae2a8a0f
|
7
|
+
data.tar.gz: 714b5eb43dfd5236ace702d9ed47301720c422db22ee501678e30ad143d1d1a9d187d66d2e555b31442bb4e3dbbdc4dbae03faca6a6277e9e84315e6869b9a3c
|
@@ -31,6 +31,7 @@
|
|
31
31
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
32
32
|
|
33
33
|
#include "ruby.h"
|
34
|
+
#include "ruby/thread.h"
|
34
35
|
#include "ruby/encoding.h"
|
35
36
|
#include <errno.h>
|
36
37
|
#include <sys/socket.h>
|
@@ -45,15 +46,15 @@ static inline VALUE rb_hash_new_capa(long capa)
|
|
45
46
|
}
|
46
47
|
#endif
|
47
48
|
|
48
|
-
static VALUE
|
49
|
-
static VALUE
|
50
|
-
static ID id_parse
|
49
|
+
static VALUE rb_eRedisClientCommandError, rb_eRedisClientConnectionError, rb_eRedisClientCannotConnectError, rb_eRedisClientProtocolError;
|
50
|
+
static VALUE rb_eRedisClientReadTimeoutError, rb_eRedisClientWriteTimeoutError;
|
51
|
+
static ID id_parse;
|
51
52
|
|
52
53
|
typedef struct {
|
53
54
|
redisSSLContext *context;
|
54
55
|
} hiredis_ssl_context_t;
|
55
56
|
|
56
|
-
#define ENSURE_CONNECTED(connection) if (!connection->context) rb_raise(
|
57
|
+
#define ENSURE_CONNECTED(connection) if (!connection->context) rb_raise(rb_eRedisClientConnectionError, "Not connected");
|
57
58
|
|
58
59
|
#define SSL_CONTEXT(from, name) \
|
59
60
|
hiredis_ssl_context_t *name = NULL; \
|
@@ -126,6 +127,7 @@ static void *reply_append(const redisReadTask *task, VALUE value) {
|
|
126
127
|
|
127
128
|
switch (task->parent->type) {
|
128
129
|
case REDIS_REPLY_ARRAY:
|
130
|
+
case REDIS_REPLY_SET:
|
129
131
|
case REDIS_REPLY_PUSH:
|
130
132
|
rb_ary_store(parent, task->idx, value);
|
131
133
|
break;
|
@@ -138,9 +140,6 @@ static void *reply_append(const redisReadTask *task, VALUE value) {
|
|
138
140
|
task->parent->privdata = (void*)value;
|
139
141
|
}
|
140
142
|
break;
|
141
|
-
case REDIS_REPLY_SET:
|
142
|
-
rb_funcall(parent, id_add, 1, value);
|
143
|
-
break;
|
144
143
|
default:
|
145
144
|
rb_bug("[hiredis] Unexpected task parent type %d", task->parent->type);
|
146
145
|
break;
|
@@ -150,6 +149,12 @@ static void *reply_append(const redisReadTask *task, VALUE value) {
|
|
150
149
|
}
|
151
150
|
|
152
151
|
static void *reply_create_string(const redisReadTask *task, char *cstr, size_t len) {
|
152
|
+
if (len >= 4 && task->type == REDIS_REPLY_VERB) {
|
153
|
+
// Skip 4 bytes of verbatim type header.
|
154
|
+
cstr += 4;
|
155
|
+
len -= 4;
|
156
|
+
}
|
157
|
+
|
153
158
|
VALUE string = rb_external_str_new(cstr, len);
|
154
159
|
if (rb_enc_str_coderange(string) == ENC_CODERANGE_BROKEN) {
|
155
160
|
rb_enc_associate(string, rb_ascii8bit_encoding());
|
@@ -170,14 +175,12 @@ static void *reply_create_array(const redisReadTask *task, size_t elements) {
|
|
170
175
|
switch (task->type) {
|
171
176
|
case REDIS_REPLY_PUSH:
|
172
177
|
case REDIS_REPLY_ARRAY:
|
178
|
+
case REDIS_REPLY_SET:
|
173
179
|
value = rb_ary_new_capa(elements);
|
174
180
|
break;
|
175
181
|
case REDIS_REPLY_MAP:
|
176
182
|
value = rb_hash_new_capa(elements / 2);
|
177
183
|
break;
|
178
|
-
case REDIS_REPLY_SET:
|
179
|
-
value = rb_funcallv(rb_cSet, id_new, 0, NULL);
|
180
|
-
break;
|
181
184
|
default:
|
182
185
|
rb_bug("[hiredis] Unexpected create array type %d", task->parent->type);
|
183
186
|
break;
|
@@ -325,6 +328,8 @@ static inline void redis_raise_error_and_disconnect(redisContext *context, VALUE
|
|
325
328
|
case REDIS_ERR_IO:
|
326
329
|
rb_sys_fail(0);
|
327
330
|
break;
|
331
|
+
case REDIS_ERR_PROTOCOL:
|
332
|
+
rb_raise(rb_eRedisClientProtocolError, "%s", errstr);
|
328
333
|
default:
|
329
334
|
/* Raise something else */
|
330
335
|
rb_raise(rb_eRedisClientConnectionError, "%s", errstr);
|
@@ -420,7 +425,7 @@ static int hiredis_wait_writable(int fd, const struct timeval *timeout, int *iss
|
|
420
425
|
|
421
426
|
static VALUE hiredis_connect_finish(hiredis_connection_t *connection, redisContext *context) {
|
422
427
|
if (context->err) {
|
423
|
-
redis_raise_error_and_disconnect(context,
|
428
|
+
redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
|
424
429
|
}
|
425
430
|
|
426
431
|
int writable = 0;
|
@@ -429,23 +434,23 @@ static VALUE hiredis_connect_finish(hiredis_connection_t *connection, redisConte
|
|
429
434
|
|
430
435
|
/* Wait for socket to become writable */
|
431
436
|
if (hiredis_wait_writable(context->fd, &connection->connect_timeout, &writable) < 0) {
|
432
|
-
redis_raise_error_and_disconnect(context,
|
437
|
+
redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
|
433
438
|
}
|
434
439
|
|
435
440
|
if (!writable) {
|
436
441
|
errno = ETIMEDOUT;
|
437
|
-
redis_raise_error_and_disconnect(context,
|
442
|
+
redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
|
438
443
|
}
|
439
444
|
|
440
445
|
/* Check for socket error */
|
441
446
|
if (getsockopt(context->fd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0) {
|
442
447
|
context->err = REDIS_ERR_IO;
|
443
|
-
redis_raise_error_and_disconnect(context,
|
448
|
+
redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
|
444
449
|
}
|
445
450
|
|
446
451
|
if (optval) {
|
447
452
|
errno = optval;
|
448
|
-
redis_raise_error_and_disconnect(context,
|
453
|
+
redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
|
449
454
|
}
|
450
455
|
|
451
456
|
context->reader->fn = &reply_functions;
|
@@ -477,7 +482,7 @@ static VALUE hiredis_init_ssl(VALUE self, VALUE ssl_param) {
|
|
477
482
|
SSL_CONTEXT(ssl_param, ssl_context)
|
478
483
|
|
479
484
|
if (redisInitiateSSLWithContext(connection->context, ssl_context->context) != REDIS_OK) {
|
480
|
-
hiredis_raise_error_and_disconnect(connection,
|
485
|
+
hiredis_raise_error_and_disconnect(connection, rb_eRedisClientCannotConnectError);
|
481
486
|
}
|
482
487
|
|
483
488
|
redisSSL *redis_ssl = redisGetSSLSocket(connection->context);
|
@@ -485,15 +490,15 @@ static VALUE hiredis_init_ssl(VALUE self, VALUE ssl_param) {
|
|
485
490
|
if (redis_ssl->wantRead) {
|
486
491
|
int readable = 0;
|
487
492
|
if (hiredis_wait_readable(connection->context->fd, &connection->connect_timeout, &readable) < 0) {
|
488
|
-
hiredis_raise_error_and_disconnect(connection,
|
493
|
+
hiredis_raise_error_and_disconnect(connection, rb_eRedisClientCannotConnectError);
|
489
494
|
}
|
490
495
|
if (!readable) {
|
491
496
|
errno = EAGAIN;
|
492
|
-
hiredis_raise_error_and_disconnect(connection,
|
497
|
+
hiredis_raise_error_and_disconnect(connection, rb_eRedisClientCannotConnectError);
|
493
498
|
}
|
494
499
|
|
495
500
|
if (redisInitiateSSLContinue(connection->context) != REDIS_OK) {
|
496
|
-
hiredis_raise_error_and_disconnect(connection,
|
501
|
+
hiredis_raise_error_and_disconnect(connection, rb_eRedisClientCannotConnectError);
|
497
502
|
};
|
498
503
|
}
|
499
504
|
|
@@ -530,6 +535,44 @@ static VALUE hiredis_write(VALUE self, VALUE command) {
|
|
530
535
|
return Qnil;
|
531
536
|
}
|
532
537
|
|
538
|
+
typedef struct {
|
539
|
+
redisContext *context;
|
540
|
+
int return_value;
|
541
|
+
} hiredis_buffer_read_args_t;
|
542
|
+
|
543
|
+
void *hiredis_buffer_read_safe(void *_args) {
|
544
|
+
hiredis_buffer_read_args_t *args = _args;
|
545
|
+
args->return_value = redisBufferRead(args->context);
|
546
|
+
return NULL;
|
547
|
+
}
|
548
|
+
int hiredis_buffer_read_nogvl(redisContext *context) {
|
549
|
+
hiredis_buffer_read_args_t args = {
|
550
|
+
.context = context,
|
551
|
+
};
|
552
|
+
rb_thread_call_without_gvl(hiredis_buffer_read_safe, &args, RUBY_UBF_IO, 0);
|
553
|
+
return args.return_value;
|
554
|
+
}
|
555
|
+
|
556
|
+
typedef struct {
|
557
|
+
redisContext *context;
|
558
|
+
int *done;
|
559
|
+
int return_value;
|
560
|
+
} hiredis_buffer_write_args_t;
|
561
|
+
|
562
|
+
void *hiredis_buffer_write_safe(void *_args) {
|
563
|
+
hiredis_buffer_write_args_t *args = _args;
|
564
|
+
args->return_value = redisBufferWrite(args->context, args->done);
|
565
|
+
return NULL;
|
566
|
+
}
|
567
|
+
int hiredis_buffer_write_nogvl(redisContext *context, int *done) {
|
568
|
+
hiredis_buffer_write_args_t args = {
|
569
|
+
.context = context,
|
570
|
+
.done = done,
|
571
|
+
};
|
572
|
+
rb_thread_call_without_gvl(hiredis_buffer_write_safe, &args, RUBY_UBF_IO, 0);
|
573
|
+
return args.return_value;
|
574
|
+
}
|
575
|
+
|
533
576
|
static VALUE hiredis_flush(VALUE self) {
|
534
577
|
CONNECTION(self, connection);
|
535
578
|
ENSURE_CONNECTED(connection);
|
@@ -537,7 +580,7 @@ static VALUE hiredis_flush(VALUE self) {
|
|
537
580
|
int wdone = 0;
|
538
581
|
while (!wdone) {
|
539
582
|
errno = 0;
|
540
|
-
if (
|
583
|
+
if (hiredis_buffer_write_nogvl(connection->context, &wdone) == REDIS_ERR) {
|
541
584
|
if (errno == EAGAIN) {
|
542
585
|
int writable = 0;
|
543
586
|
|
@@ -573,7 +616,7 @@ static int hiredis_read_internal(hiredis_connection_t *connection, VALUE *reply)
|
|
573
616
|
while (!wdone) {
|
574
617
|
errno = 0;
|
575
618
|
|
576
|
-
if (
|
619
|
+
if (hiredis_buffer_write_nogvl(connection->context, &wdone) == REDIS_ERR) {
|
577
620
|
/* Socket error */
|
578
621
|
return -1;
|
579
622
|
}
|
@@ -596,7 +639,7 @@ static int hiredis_read_internal(hiredis_connection_t *connection, VALUE *reply)
|
|
596
639
|
while (redis_reply == NULL) {
|
597
640
|
errno = 0;
|
598
641
|
|
599
|
-
if (
|
642
|
+
if (hiredis_buffer_read_nogvl(connection->context) == REDIS_ERR) {
|
600
643
|
/* Socket error */
|
601
644
|
return -1;
|
602
645
|
}
|
@@ -662,11 +705,6 @@ void Init_hiredis_connection(void) {
|
|
662
705
|
redisInitOpenSSL();
|
663
706
|
|
664
707
|
id_parse = rb_intern("parse");
|
665
|
-
id_add = rb_intern("add");
|
666
|
-
id_new = rb_intern("new");
|
667
|
-
|
668
|
-
rb_cSet = rb_const_get(rb_cObject, rb_intern("Set"));
|
669
|
-
rb_global_variable(&rb_cSet);
|
670
708
|
|
671
709
|
VALUE rb_cRedisClient = rb_const_get(rb_cObject, rb_intern("RedisClient"));
|
672
710
|
|
@@ -676,8 +714,11 @@ void Init_hiredis_connection(void) {
|
|
676
714
|
rb_eRedisClientConnectionError = rb_const_get(rb_cRedisClient, rb_intern("ConnectionError"));
|
677
715
|
rb_global_variable(&rb_eRedisClientConnectionError);
|
678
716
|
|
679
|
-
|
680
|
-
rb_global_variable(&
|
717
|
+
rb_eRedisClientCannotConnectError = rb_const_get(rb_cRedisClient, rb_intern("CannotConnectError"));
|
718
|
+
rb_global_variable(&rb_eRedisClientCannotConnectError);
|
719
|
+
|
720
|
+
rb_eRedisClientProtocolError = rb_const_get(rb_cRedisClient, rb_intern("ProtocolError"));
|
721
|
+
rb_global_variable(&rb_eRedisClientProtocolError);
|
681
722
|
|
682
723
|
rb_eRedisClientReadTimeoutError = rb_const_get(rb_cRedisClient, rb_intern("ReadTimeoutError"));
|
683
724
|
rb_global_variable(&rb_eRedisClientReadTimeoutError);
|
@@ -34,7 +34,11 @@ class RedisClient
|
|
34
34
|
self.write_timeout = write_timeout
|
35
35
|
|
36
36
|
if config.path
|
37
|
-
|
37
|
+
begin
|
38
|
+
connect_unix(config.path)
|
39
|
+
rescue SystemCallError => error
|
40
|
+
raise CannotConnectError, error.message, error.backtrace
|
41
|
+
end
|
38
42
|
else
|
39
43
|
connect_tcp(config.host, config.port)
|
40
44
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hiredis-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis-client
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.6.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.6.2
|
27
27
|
description:
|
28
28
|
email:
|
29
29
|
- jean.boussier@gmail.com
|