hiredis 0.5.2 → 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.
@@ -1,6 +1,6 @@
1
- /* SDSLib, A C dynamic strings library
1
+ /* SDS (Simple Dynamic Strings), A C dynamic strings library.
2
2
  *
3
- * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
3
+ * Copyright (c) 2006-2014, Salvatore Sanfilippo <antirez at gmail dot com>
4
4
  * All rights reserved.
5
5
  *
6
6
  * Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,8 @@
31
31
  #ifndef __SDS_H
32
32
  #define __SDS_H
33
33
 
34
+ #define SDS_MAX_PREALLOC (1024*1024)
35
+
34
36
  #include <sys/types.h>
35
37
  #include <stdarg.h>
36
38
 
@@ -43,12 +45,12 @@ struct sdshdr {
43
45
  };
44
46
 
45
47
  static inline size_t sdslen(const sds s) {
46
- struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
48
+ struct sdshdr *sh = (struct sdshdr *)(s-sizeof *sh);
47
49
  return sh->len;
48
50
  }
49
51
 
50
52
  static inline size_t sdsavail(const sds s) {
51
- struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
53
+ struct sdshdr *sh = (struct sdshdr *)(s-sizeof *sh);
52
54
  return sh->free;
53
55
  }
54
56
 
@@ -58,12 +60,13 @@ sds sdsempty(void);
58
60
  size_t sdslen(const sds s);
59
61
  sds sdsdup(const sds s);
60
62
  void sdsfree(sds s);
61
- size_t sdsavail(sds s);
63
+ size_t sdsavail(const sds s);
62
64
  sds sdsgrowzero(sds s, size_t len);
63
65
  sds sdscatlen(sds s, const void *t, size_t len);
64
66
  sds sdscat(sds s, const char *t);
65
- sds sdscpylen(sds s, char *t, size_t len);
66
- sds sdscpy(sds s, char *t);
67
+ sds sdscatsds(sds s, const sds t);
68
+ sds sdscpylen(sds s, const char *t, size_t len);
69
+ sds sdscpy(sds s, const char *t);
67
70
 
68
71
  sds sdscatvprintf(sds s, const char *fmt, va_list ap);
69
72
  #ifdef __GNUC__
@@ -73,16 +76,27 @@ sds sdscatprintf(sds s, const char *fmt, ...)
73
76
  sds sdscatprintf(sds s, const char *fmt, ...);
74
77
  #endif
75
78
 
76
- sds sdstrim(sds s, const char *cset);
77
- sds sdsrange(sds s, int start, int end);
79
+ sds sdscatfmt(sds s, char const *fmt, ...);
80
+ void sdstrim(sds s, const char *cset);
81
+ void sdsrange(sds s, int start, int end);
78
82
  void sdsupdatelen(sds s);
79
- int sdscmp(sds s1, sds s2);
80
- sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count);
83
+ void sdsclear(sds s);
84
+ int sdscmp(const sds s1, const sds s2);
85
+ sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);
81
86
  void sdsfreesplitres(sds *tokens, int count);
82
87
  void sdstolower(sds s);
83
88
  void sdstoupper(sds s);
84
89
  sds sdsfromlonglong(long long value);
85
- sds sdscatrepr(sds s, char *p, size_t len);
86
- sds *sdssplitargs(char *line, int *argc);
90
+ sds sdscatrepr(sds s, const char *p, size_t len);
91
+ sds *sdssplitargs(const char *line, int *argc);
92
+ sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
93
+ sds sdsjoin(char **argv, int argc, char *sep, size_t seplen);
94
+ sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);
95
+
96
+ /* Low level functions exposed to the user API */
97
+ sds sdsMakeRoomFor(sds s, size_t addlen);
98
+ void sdsIncrLen(sds s, int incr);
99
+ sds sdsRemoveFreeSpace(sds s);
100
+ size_t sdsAllocSize(sds s);
87
101
 
88
102
  #endif
@@ -8,12 +8,14 @@
8
8
  #include <unistd.h>
9
9
  #include <signal.h>
10
10
  #include <errno.h>
11
+ #include <limits.h>
11
12
 
12
13
  #include "hiredis.h"
13
14
 
14
15
  enum connection_type {
15
16
  CONN_TCP,
16
- CONN_UNIX
17
+ CONN_UNIX,
18
+ CONN_FD
17
19
  };
18
20
 
19
21
  struct config {
@@ -22,6 +24,7 @@ struct config {
22
24
  struct {
23
25
  const char *host;
24
26
  int port;
27
+ struct timeval timeout;
25
28
  } tcp;
26
29
 
27
30
  struct {
@@ -62,7 +65,7 @@ static redisContext *select_database(redisContext *c) {
62
65
  return c;
63
66
  }
64
67
 
65
- static void disconnect(redisContext *c) {
68
+ static int disconnect(redisContext *c, int keep_fd) {
66
69
  redisReply *reply;
67
70
 
68
71
  /* Make sure we're on DB 9. */
@@ -73,8 +76,11 @@ static void disconnect(redisContext *c) {
73
76
  assert(reply != NULL);
74
77
  freeReplyObject(reply);
75
78
 
76
- /* Free the context as well. */
79
+ /* Free the context as well, but keep the fd if requested. */
80
+ if (keep_fd)
81
+ return redisFreeKeepFd(c);
77
82
  redisFree(c);
83
+ return -1;
78
84
  }
79
85
 
80
86
  static redisContext *connect(struct config config) {
@@ -84,12 +90,24 @@ static redisContext *connect(struct config config) {
84
90
  c = redisConnect(config.tcp.host, config.tcp.port);
85
91
  } else if (config.type == CONN_UNIX) {
86
92
  c = redisConnectUnix(config.unix.path);
93
+ } else if (config.type == CONN_FD) {
94
+ /* Create a dummy connection just to get an fd to inherit */
95
+ redisContext *dummy_ctx = redisConnectUnix(config.unix.path);
96
+ if (dummy_ctx) {
97
+ int fd = disconnect(dummy_ctx, 1);
98
+ printf("Connecting to inherited fd %d\n", fd);
99
+ c = redisConnectFd(fd);
100
+ }
87
101
  } else {
88
102
  assert(NULL);
89
103
  }
90
104
 
91
- if (c->err) {
105
+ if (c == NULL) {
106
+ printf("Connection error: can't allocate redis context\n");
107
+ exit(1);
108
+ } else if (c->err) {
92
109
  printf("Connection error: %s\n", c->errstr);
110
+ redisFree(c);
93
111
  exit(1);
94
112
  }
95
113
 
@@ -125,13 +143,13 @@ static void test_format_commands(void) {
125
143
  free(cmd);
126
144
 
127
145
  test("Format command with %%b string interpolation: ");
128
- len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3);
146
+ len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"b\0r",(size_t)3);
129
147
  test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 &&
130
148
  len == 4+4+(3+2)+4+(3+2)+4+(3+2));
131
149
  free(cmd);
132
150
 
133
151
  test("Format command with %%b and an empty string: ");
134
- len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"",0);
152
+ len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"",(size_t)0);
135
153
  test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 &&
136
154
  len == 4+4+(3+2)+4+(3+2)+4+(0+2));
137
155
  free(cmd);
@@ -177,7 +195,7 @@ static void test_format_commands(void) {
177
195
  FLOAT_WIDTH_TEST(double);
178
196
 
179
197
  test("Format command with invalid printf format: ");
180
- len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",3);
198
+ len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",(size_t)3);
181
199
  test_cond(len == -1);
182
200
 
183
201
  const char *argv[3];
@@ -200,6 +218,28 @@ static void test_format_commands(void) {
200
218
  free(cmd);
201
219
  }
202
220
 
221
+ static void test_append_formatted_commands(struct config config) {
222
+ redisContext *c;
223
+ redisReply *reply;
224
+ char *cmd;
225
+ int len;
226
+
227
+ c = connect(config);
228
+
229
+ test("Append format command: ");
230
+
231
+ len = redisFormatCommand(&cmd, "SET foo bar");
232
+
233
+ test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK);
234
+
235
+ assert(redisGetReply(c, (void*)&reply) == REDIS_OK);
236
+
237
+ free(cmd);
238
+ freeReplyObject(reply);
239
+
240
+ disconnect(c, 0);
241
+ }
242
+
203
243
  static void test_reply_reader(void) {
204
244
  redisReader *reader;
205
245
  void *reply;
@@ -279,14 +319,31 @@ static void test_reply_reader(void) {
279
319
  redisReaderFree(reader);
280
320
  }
281
321
 
322
+ static void test_free_null(void) {
323
+ void *redisContext = NULL;
324
+ void *reply = NULL;
325
+
326
+ test("Don't fail when redisFree is passed a NULL value: ");
327
+ redisFree(redisContext);
328
+ test_cond(redisContext == NULL);
329
+
330
+ test("Don't fail when freeReplyObject is passed a NULL value: ");
331
+ freeReplyObject(reply);
332
+ test_cond(reply == NULL);
333
+ }
334
+
282
335
  static void test_blocking_connection_errors(void) {
283
336
  redisContext *c;
284
337
 
285
338
  test("Returns error when host cannot be resolved: ");
286
- c = redisConnect((char*)"idontexist.local", 6379);
339
+ c = redisConnect((char*)"idontexist.test", 6379);
287
340
  test_cond(c->err == REDIS_ERR_OTHER &&
288
341
  (strcmp(c->errstr,"Name or service not known") == 0 ||
289
- strcmp(c->errstr,"Can't resolve: idontexist.local") == 0));
342
+ strcmp(c->errstr,"Can't resolve: idontexist.test") == 0 ||
343
+ strcmp(c->errstr,"nodename nor servname provided, or not known") == 0 ||
344
+ strcmp(c->errstr,"No address associated with hostname") == 0 ||
345
+ strcmp(c->errstr,"Temporary failure in name resolution") == 0 ||
346
+ strcmp(c->errstr,"no address associated with name") == 0));
290
347
  redisFree(c);
291
348
 
292
349
  test("Returns error when the port is not open: ");
@@ -328,7 +385,7 @@ static void test_blocking_connection(struct config config) {
328
385
  freeReplyObject(reply);
329
386
 
330
387
  test("%%b String interpolation works: ");
331
- reply = redisCommand(c,"SET %b %b","foo",3,"hello\x00world",11);
388
+ reply = redisCommand(c,"SET %b %b","foo",(size_t)3,"hello\x00world",(size_t)11);
332
389
  freeReplyObject(reply);
333
390
  reply = redisCommand(c,"GET foo");
334
391
  test_cond(reply->type == REDIS_REPLY_STRING &&
@@ -376,7 +433,7 @@ static void test_blocking_connection(struct config config) {
376
433
  strcasecmp(reply->element[1]->str,"pong") == 0);
377
434
  freeReplyObject(reply);
378
435
 
379
- disconnect(c);
436
+ disconnect(c, 0);
380
437
  }
381
438
 
382
439
  static void test_blocking_io_errors(struct config config) {
@@ -430,6 +487,30 @@ static void test_blocking_io_errors(struct config config) {
430
487
  redisFree(c);
431
488
  }
432
489
 
490
+ static void test_invalid_timeout_errors(struct config config) {
491
+ redisContext *c;
492
+
493
+ test("Set error when an invalid timeout usec value is given to redisConnectWithTimeout: ");
494
+
495
+ config.tcp.timeout.tv_sec = 0;
496
+ config.tcp.timeout.tv_usec = 10000001;
497
+
498
+ c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
499
+
500
+ test_cond(c->err == REDIS_ERR_IO);
501
+ redisFree(c);
502
+
503
+ test("Set error when an invalid timeout sec value is given to redisConnectWithTimeout: ");
504
+
505
+ config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1;
506
+ config.tcp.timeout.tv_usec = 0;
507
+
508
+ c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
509
+
510
+ test_cond(c->err == REDIS_ERR_IO);
511
+ redisFree(c);
512
+ }
513
+
433
514
  static void test_throughput(struct config config) {
434
515
  redisContext *c = connect(config);
435
516
  redisReply **replies;
@@ -492,7 +573,7 @@ static void test_throughput(struct config config) {
492
573
  free(replies);
493
574
  printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
494
575
 
495
- disconnect(c);
576
+ disconnect(c, 0);
496
577
  }
497
578
 
498
579
  // static long __test_callback_flags = 0;
@@ -605,6 +686,7 @@ int main(int argc, char **argv) {
605
686
  }
606
687
  };
607
688
  int throughput = 1;
689
+ int test_inherit_fd = 1;
608
690
 
609
691
  /* Ignore broken pipe signal (for I/O error tests). */
610
692
  signal(SIGPIPE, SIG_IGN);
@@ -623,6 +705,8 @@ int main(int argc, char **argv) {
623
705
  cfg.unix.path = argv[0];
624
706
  } else if (argc >= 1 && !strcmp(argv[0],"--skip-throughput")) {
625
707
  throughput = 0;
708
+ } else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) {
709
+ test_inherit_fd = 0;
626
710
  } else {
627
711
  fprintf(stderr, "Invalid argument: %s\n", argv[0]);
628
712
  exit(1);
@@ -633,11 +717,14 @@ int main(int argc, char **argv) {
633
717
  test_format_commands();
634
718
  test_reply_reader();
635
719
  test_blocking_connection_errors();
720
+ test_free_null();
636
721
 
637
722
  printf("\nTesting against TCP connection (%s:%d):\n", cfg.tcp.host, cfg.tcp.port);
638
723
  cfg.type = CONN_TCP;
639
724
  test_blocking_connection(cfg);
640
725
  test_blocking_io_errors(cfg);
726
+ test_invalid_timeout_errors(cfg);
727
+ test_append_formatted_commands(cfg);
641
728
  if (throughput) test_throughput(cfg);
642
729
 
643
730
  printf("\nTesting against Unix socket connection (%s):\n", cfg.unix.path);
@@ -646,6 +733,13 @@ int main(int argc, char **argv) {
646
733
  test_blocking_io_errors(cfg);
647
734
  if (throughput) test_throughput(cfg);
648
735
 
736
+ if (test_inherit_fd) {
737
+ printf("\nTesting against inherited fd (%s):\n", cfg.unix.path);
738
+ cfg.type = CONN_FD;
739
+ test_blocking_connection(cfg);
740
+ }
741
+
742
+
649
743
  if (fails) {
650
744
  printf("*** %d TESTS FAILED ***\n", fails);
651
745
  return 1;
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hiredis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pieter Noordhuis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-10 00:00:00.000000000 Z
11
+ date: 2015-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -28,16 +28,30 @@ dependencies:
28
28
  name: rake-compiler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.7.1
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.7.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 5.5.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 5.5.1
41
55
  description: Ruby wrapper for hiredis (protocol serialization/deserialization and
42
56
  blocking I/O)
43
57
  email:
@@ -47,38 +61,40 @@ extensions:
47
61
  - ext/hiredis_ext/extconf.rb
48
62
  extra_rdoc_files: []
49
63
  files:
50
- - ext/hiredis_ext/extconf.rb
64
+ - COPYING
65
+ - Rakefile
51
66
  - ext/hiredis_ext/connection.c
67
+ - ext/hiredis_ext/extconf.rb
52
68
  - ext/hiredis_ext/hiredis_ext.c
53
- - ext/hiredis_ext/reader.c
54
69
  - ext/hiredis_ext/hiredis_ext.h
55
- - vendor/hiredis/async.c
56
- - vendor/hiredis/dict.c
57
- - vendor/hiredis/hiredis.c
58
- - vendor/hiredis/net.c
59
- - vendor/hiredis/sds.c
60
- - vendor/hiredis/test.c
61
- - vendor/hiredis/async.h
62
- - vendor/hiredis/dict.h
63
- - vendor/hiredis/fmacros.h
64
- - vendor/hiredis/hiredis.h
65
- - vendor/hiredis/net.h
66
- - vendor/hiredis/sds.h
67
- - vendor/hiredis/COPYING
68
- - vendor/hiredis/Makefile
70
+ - ext/hiredis_ext/reader.c
71
+ - lib/hiredis.rb
69
72
  - lib/hiredis/connection.rb
70
- - lib/hiredis/errors.rb
71
73
  - lib/hiredis/ext/connection.rb
72
74
  - lib/hiredis/ext/reader.rb
73
75
  - lib/hiredis/reader.rb
74
76
  - lib/hiredis/ruby/connection.rb
75
77
  - lib/hiredis/ruby/reader.rb
76
78
  - lib/hiredis/version.rb
77
- - lib/hiredis.rb
78
- - COPYING
79
- - Rakefile
79
+ - vendor/hiredis/COPYING
80
+ - vendor/hiredis/Makefile
81
+ - vendor/hiredis/async.c
82
+ - vendor/hiredis/async.h
83
+ - vendor/hiredis/dict.c
84
+ - vendor/hiredis/dict.h
85
+ - vendor/hiredis/fmacros.h
86
+ - vendor/hiredis/hiredis.c
87
+ - vendor/hiredis/hiredis.h
88
+ - vendor/hiredis/net.c
89
+ - vendor/hiredis/net.h
90
+ - vendor/hiredis/read.c
91
+ - vendor/hiredis/read.h
92
+ - vendor/hiredis/sds.c
93
+ - vendor/hiredis/sds.h
94
+ - vendor/hiredis/test.c
80
95
  homepage: http://github.com/redis/hiredis-rb
81
- licenses: []
96
+ licenses:
97
+ - BSD-3-Clause
82
98
  metadata: {}
83
99
  post_install_message:
84
100
  rdoc_options: []
@@ -86,17 +102,17 @@ require_paths:
86
102
  - lib
87
103
  required_ruby_version: !ruby/object:Gem::Requirement
88
104
  requirements:
89
- - - '>='
105
+ - - ">="
90
106
  - !ruby/object:Gem::Version
91
107
  version: '0'
92
108
  required_rubygems_version: !ruby/object:Gem::Requirement
93
109
  requirements:
94
- - - '>='
110
+ - - ">="
95
111
  - !ruby/object:Gem::Version
96
112
  version: '0'
97
113
  requirements: []
98
114
  rubyforge_project:
99
- rubygems_version: 2.0.3
115
+ rubygems_version: 2.4.5
100
116
  signing_key:
101
117
  specification_version: 4
102
118
  summary: Ruby wrapper for hiredis (protocol serialization/deserialization and blocking