hiredis-client 0.4.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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