hiredis 0.5.2 → 0.6.0

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