hiredis-client 0.5.1 → 0.6.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.
- 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
|