hiredis-client 0.4.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 002d836b8dec0059c6dd1bfe640f613594b34bb625a724b1a72183e321ebc98f
4
- data.tar.gz: 96ea371a99e2091712fb01366f00bff21398f0e08039b573d677c8157ef41af6
3
+ metadata.gz: ba60e75acf78441a3ee79cc33c7dd02be25481a229e6c3a697f6595864da50f5
4
+ data.tar.gz: 8e850b60219abce73e320a42b610fadfec522ab0f926c429a98f6c51dcfd862f
5
5
  SHA512:
6
- metadata.gz: fc7b1a377d1531936f3456ca54dfe07d99e0a9e7c7adb72cfbdd4126ea1ca0f8ce206ded1338a78f6e43ebcaa5b976a08bdf0849a976cf57690ae61da4b5bd39
7
- data.tar.gz: 4ee028ab34699d2301a8bd6b23ae02c9056ab1b049548a945a9a83b0a55c5eb3dcd33472fefc83d125be451709a7a5bfb722f7d9cca64e507213e7fe2d234d96
6
+ metadata.gz: 86f117da17118c442f127d11eec64d9dea91fb3da1070a111e2be1611815056e4443bcc2904d8e709bd3a4095e1704f9c32a47fb6a09688670c9f4d9221f4635
7
+ data.tar.gz: fa1896db0cf13d0d33ad812659f381968de920e1516fc05aa1467e1c302fd958b3fbfa9919171f6bdaff63a44e8d21c13de9fb8efd1b56524d6f84d1961d865a
@@ -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,8 +46,8 @@ 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;
49
+ static VALUE rb_eRedisClientCommandError, rb_eRedisClientConnectionError, rb_eRedisClientCannotConnectError, rb_eRedisClientProtocolError;
50
+ static VALUE rb_eRedisClientReadTimeoutError, rb_eRedisClientWriteTimeoutError;
50
51
  static ID id_parse, id_add, id_new;
51
52
 
52
53
  typedef struct {
@@ -150,6 +151,12 @@ static void *reply_append(const redisReadTask *task, VALUE value) {
150
151
  }
151
152
 
152
153
  static void *reply_create_string(const redisReadTask *task, char *cstr, size_t len) {
154
+ if (len >= 4 && task->type == REDIS_REPLY_VERB) {
155
+ // Skip 4 bytes of verbatim type header.
156
+ cstr += 4;
157
+ len -= 4;
158
+ }
159
+
153
160
  VALUE string = rb_external_str_new(cstr, len);
154
161
  if (rb_enc_str_coderange(string) == ENC_CODERANGE_BROKEN) {
155
162
  rb_enc_associate(string, rb_ascii8bit_encoding());
@@ -170,14 +177,12 @@ static void *reply_create_array(const redisReadTask *task, size_t elements) {
170
177
  switch (task->type) {
171
178
  case REDIS_REPLY_PUSH:
172
179
  case REDIS_REPLY_ARRAY:
180
+ case REDIS_REPLY_SET:
173
181
  value = rb_ary_new_capa(elements);
174
182
  break;
175
183
  case REDIS_REPLY_MAP:
176
184
  value = rb_hash_new_capa(elements / 2);
177
185
  break;
178
- case REDIS_REPLY_SET:
179
- value = rb_funcallv(rb_cSet, id_new, 0, NULL);
180
- break;
181
186
  default:
182
187
  rb_bug("[hiredis] Unexpected create array type %d", task->parent->type);
183
188
  break;
@@ -325,6 +330,8 @@ static inline void redis_raise_error_and_disconnect(redisContext *context, VALUE
325
330
  case REDIS_ERR_IO:
326
331
  rb_sys_fail(0);
327
332
  break;
333
+ case REDIS_ERR_PROTOCOL:
334
+ rb_raise(rb_eRedisClientProtocolError, "%s", errstr);
328
335
  default:
329
336
  /* Raise something else */
330
337
  rb_raise(rb_eRedisClientConnectionError, "%s", errstr);
@@ -420,7 +427,7 @@ static int hiredis_wait_writable(int fd, const struct timeval *timeout, int *iss
420
427
 
421
428
  static VALUE hiredis_connect_finish(hiredis_connection_t *connection, redisContext *context) {
422
429
  if (context->err) {
423
- redis_raise_error_and_disconnect(context, rb_eRedisClientConnectTimeoutError);
430
+ redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
424
431
  }
425
432
 
426
433
  int writable = 0;
@@ -429,23 +436,23 @@ static VALUE hiredis_connect_finish(hiredis_connection_t *connection, redisConte
429
436
 
430
437
  /* Wait for socket to become writable */
431
438
  if (hiredis_wait_writable(context->fd, &connection->connect_timeout, &writable) < 0) {
432
- redis_raise_error_and_disconnect(context, rb_eRedisClientConnectTimeoutError);
439
+ redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
433
440
  }
434
441
 
435
442
  if (!writable) {
436
443
  errno = ETIMEDOUT;
437
- redis_raise_error_and_disconnect(context, rb_eRedisClientConnectTimeoutError);
444
+ redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
438
445
  }
439
446
 
440
447
  /* Check for socket error */
441
448
  if (getsockopt(context->fd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0) {
442
449
  context->err = REDIS_ERR_IO;
443
- redis_raise_error_and_disconnect(context, rb_eRedisClientConnectTimeoutError);
450
+ redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
444
451
  }
445
452
 
446
453
  if (optval) {
447
454
  errno = optval;
448
- redis_raise_error_and_disconnect(context, rb_eRedisClientConnectTimeoutError);
455
+ redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
449
456
  }
450
457
 
451
458
  context->reader->fn = &reply_functions;
@@ -477,7 +484,7 @@ static VALUE hiredis_init_ssl(VALUE self, VALUE ssl_param) {
477
484
  SSL_CONTEXT(ssl_param, ssl_context)
478
485
 
479
486
  if (redisInitiateSSLWithContext(connection->context, ssl_context->context) != REDIS_OK) {
480
- hiredis_raise_error_and_disconnect(connection, rb_eRedisClientConnectTimeoutError);
487
+ hiredis_raise_error_and_disconnect(connection, rb_eRedisClientCannotConnectError);
481
488
  }
482
489
 
483
490
  redisSSL *redis_ssl = redisGetSSLSocket(connection->context);
@@ -485,15 +492,15 @@ static VALUE hiredis_init_ssl(VALUE self, VALUE ssl_param) {
485
492
  if (redis_ssl->wantRead) {
486
493
  int readable = 0;
487
494
  if (hiredis_wait_readable(connection->context->fd, &connection->connect_timeout, &readable) < 0) {
488
- hiredis_raise_error_and_disconnect(connection, rb_eRedisClientConnectTimeoutError);
495
+ hiredis_raise_error_and_disconnect(connection, rb_eRedisClientCannotConnectError);
489
496
  }
490
497
  if (!readable) {
491
498
  errno = EAGAIN;
492
- hiredis_raise_error_and_disconnect(connection, rb_eRedisClientConnectTimeoutError);
499
+ hiredis_raise_error_and_disconnect(connection, rb_eRedisClientCannotConnectError);
493
500
  }
494
501
 
495
502
  if (redisInitiateSSLContinue(connection->context) != REDIS_OK) {
496
- hiredis_raise_error_and_disconnect(connection, rb_eRedisClientConnectTimeoutError);
503
+ hiredis_raise_error_and_disconnect(connection, rb_eRedisClientCannotConnectError);
497
504
  };
498
505
  }
499
506
 
@@ -530,6 +537,44 @@ static VALUE hiredis_write(VALUE self, VALUE command) {
530
537
  return Qnil;
531
538
  }
532
539
 
540
+ typedef struct {
541
+ redisContext *context;
542
+ int return_value;
543
+ } hiredis_buffer_read_args_t;
544
+
545
+ void *hiredis_buffer_read_safe(void *_args) {
546
+ hiredis_buffer_read_args_t *args = _args;
547
+ args->return_value = redisBufferRead(args->context);
548
+ return NULL;
549
+ }
550
+ int hiredis_buffer_read_nogvl(redisContext *context) {
551
+ hiredis_buffer_read_args_t args = {
552
+ .context = context,
553
+ };
554
+ rb_thread_call_without_gvl(hiredis_buffer_read_safe, &args, RUBY_UBF_IO, 0);
555
+ return args.return_value;
556
+ }
557
+
558
+ typedef struct {
559
+ redisContext *context;
560
+ int *done;
561
+ int return_value;
562
+ } hiredis_buffer_write_args_t;
563
+
564
+ void *hiredis_buffer_write_safe(void *_args) {
565
+ hiredis_buffer_write_args_t *args = _args;
566
+ args->return_value = redisBufferWrite(args->context, args->done);
567
+ return NULL;
568
+ }
569
+ int hiredis_buffer_write_nogvl(redisContext *context, int *done) {
570
+ hiredis_buffer_write_args_t args = {
571
+ .context = context,
572
+ .done = done,
573
+ };
574
+ rb_thread_call_without_gvl(hiredis_buffer_write_safe, &args, RUBY_UBF_IO, 0);
575
+ return args.return_value;
576
+ }
577
+
533
578
  static VALUE hiredis_flush(VALUE self) {
534
579
  CONNECTION(self, connection);
535
580
  ENSURE_CONNECTED(connection);
@@ -537,7 +582,7 @@ static VALUE hiredis_flush(VALUE self) {
537
582
  int wdone = 0;
538
583
  while (!wdone) {
539
584
  errno = 0;
540
- if (redisBufferWrite(connection->context, &wdone) == REDIS_ERR) {
585
+ if (hiredis_buffer_write_nogvl(connection->context, &wdone) == REDIS_ERR) {
541
586
  if (errno == EAGAIN) {
542
587
  int writable = 0;
543
588
 
@@ -573,7 +618,7 @@ static int hiredis_read_internal(hiredis_connection_t *connection, VALUE *reply)
573
618
  while (!wdone) {
574
619
  errno = 0;
575
620
 
576
- if (redisBufferWrite(connection->context, &wdone) == REDIS_ERR) {
621
+ if (hiredis_buffer_write_nogvl(connection->context, &wdone) == REDIS_ERR) {
577
622
  /* Socket error */
578
623
  return -1;
579
624
  }
@@ -596,7 +641,7 @@ static int hiredis_read_internal(hiredis_connection_t *connection, VALUE *reply)
596
641
  while (redis_reply == NULL) {
597
642
  errno = 0;
598
643
 
599
- if (redisBufferRead(connection->context) == REDIS_ERR) {
644
+ if (hiredis_buffer_read_nogvl(connection->context) == REDIS_ERR) {
600
645
  /* Socket error */
601
646
  return -1;
602
647
  }
@@ -665,9 +710,6 @@ void Init_hiredis_connection(void) {
665
710
  id_add = rb_intern("add");
666
711
  id_new = rb_intern("new");
667
712
 
668
- rb_cSet = rb_const_get(rb_cObject, rb_intern("Set"));
669
- rb_global_variable(&rb_cSet);
670
-
671
713
  VALUE rb_cRedisClient = rb_const_get(rb_cObject, rb_intern("RedisClient"));
672
714
 
673
715
  rb_eRedisClientCommandError = rb_const_get(rb_cRedisClient, rb_intern("CommandError"));
@@ -676,8 +718,11 @@ void Init_hiredis_connection(void) {
676
718
  rb_eRedisClientConnectionError = rb_const_get(rb_cRedisClient, rb_intern("ConnectionError"));
677
719
  rb_global_variable(&rb_eRedisClientConnectionError);
678
720
 
679
- rb_eRedisClientConnectTimeoutError = rb_const_get(rb_cRedisClient, rb_intern("ConnectTimeoutError"));
680
- rb_global_variable(&rb_eRedisClientConnectTimeoutError);
721
+ rb_eRedisClientCannotConnectError = rb_const_get(rb_cRedisClient, rb_intern("CannotConnectError"));
722
+ rb_global_variable(&rb_eRedisClientCannotConnectError);
723
+
724
+ rb_eRedisClientProtocolError = rb_const_get(rb_cRedisClient, rb_intern("ProtocolError"));
725
+ rb_global_variable(&rb_eRedisClientProtocolError);
681
726
 
682
727
  rb_eRedisClientReadTimeoutError = rb_const_get(rb_cRedisClient, rb_intern("ReadTimeoutError"));
683
728
  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.4.0
4
+ version: 0.6.0
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-05-06 00:00:00.000000000 Z
11
+ date: 2022-08-16 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.4.0
19
+ version: 0.6.0
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.4.0
26
+ version: 0.6.0
27
27
  description:
28
28
  email:
29
29
  - jean.boussier@gmail.com