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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba2a16ce75c627a3bdf88b08b484718e32d352c03a21c5d3d7c96201453952b8
4
- data.tar.gz: 4d75701dadbf783d8426bd0225e35e3388845c4303a61e1b28122aac664c4f47
3
+ metadata.gz: 4a1e6c581e8cdaf2e39e684939f9747503d80f2573065d18a43b9002a83005f3
4
+ data.tar.gz: d3a82df8aa27552818f25757fadc2e9789cecd2e149051a05379f6361f618bab
5
5
  SHA512:
6
- metadata.gz: 92aa71bb1f4b460b06278fb026b0b12edfbc8bb8f2edb4a8a7e006d1afdfbd9f34e665c8592b0245b2355742b4922c37ea42412adbf0ee36b188c0a7817f07f4
7
- data.tar.gz: f8af4f856b5e48bc75ef12520a62c0010e02976ea6961cdb9d50087cdf7b654f8b7c58b267aef4d1fa3535c0449c08f17fcf163c6abcdfdf8fad9f81086d8092
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 rb_cSet, rb_eRedisClientCommandError, rb_eRedisClientConnectionError;
49
- static VALUE rb_eRedisClientConnectTimeoutError, rb_eRedisClientReadTimeoutError, rb_eRedisClientWriteTimeoutError;
50
- static ID id_parse, id_add, id_new;
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(rb_eRuntimeError, "[BUG] not connected");
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, rb_eRedisClientConnectTimeoutError);
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, rb_eRedisClientConnectTimeoutError);
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, rb_eRedisClientConnectTimeoutError);
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, rb_eRedisClientConnectTimeoutError);
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, rb_eRedisClientConnectTimeoutError);
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, rb_eRedisClientConnectTimeoutError);
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, rb_eRedisClientConnectTimeoutError);
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, rb_eRedisClientConnectTimeoutError);
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, rb_eRedisClientConnectTimeoutError);
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 (redisBufferWrite(connection->context, &wdone) == REDIS_ERR) {
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 (redisBufferWrite(connection->context, &wdone) == REDIS_ERR) {
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 (redisBufferRead(connection->context) == REDIS_ERR) {
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
- rb_eRedisClientConnectTimeoutError = rb_const_get(rb_cRedisClient, rb_intern("ConnectTimeoutError"));
680
- rb_global_variable(&rb_eRedisClientConnectTimeoutError);
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
- connect_unix(config.path)
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.5.1
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-06-02 00:00:00.000000000 Z
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.5.1
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.5.1
26
+ version: 0.6.2
27
27
  description:
28
28
  email:
29
29
  - jean.boussier@gmail.com