durable_rules 0.33.13 → 0.34.01

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.
data/deps/hiredis/sds.h CHANGED
@@ -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
@@ -35,6 +35,9 @@
35
35
 
36
36
  #include <sys/types.h>
37
37
  #include <stdarg.h>
38
+ #ifdef _MSC_VER
39
+ #include "win32.h"
40
+ #endif
38
41
 
39
42
  typedef char *sds;
40
43
 
@@ -45,12 +48,12 @@ struct sdshdr {
45
48
  };
46
49
 
47
50
  static inline size_t sdslen(const sds s) {
48
- struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
51
+ struct sdshdr *sh = (struct sdshdr *)(s-sizeof *sh);
49
52
  return sh->len;
50
53
  }
51
54
 
52
55
  static inline size_t sdsavail(const sds s) {
53
- struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
56
+ struct sdshdr *sh = (struct sdshdr *)(s-sizeof *sh);
54
57
  return sh->free;
55
58
  }
56
59
 
@@ -76,7 +79,8 @@ sds sdscatprintf(sds s, const char *fmt, ...)
76
79
  sds sdscatprintf(sds s, const char *fmt, ...);
77
80
  #endif
78
81
 
79
- sds sdstrim(sds s, const char *cset);
82
+ sds sdscatfmt(sds s, char const *fmt, ...);
83
+ void sdstrim(sds s, const char *cset);
80
84
  void sdsrange(sds s, int start, int end);
81
85
  void sdsupdatelen(sds s);
82
86
  void sdsclear(sds s);
@@ -89,7 +93,8 @@ sds sdsfromlonglong(long long value);
89
93
  sds sdscatrepr(sds s, const char *p, size_t len);
90
94
  sds *sdssplitargs(const char *line, int *argc);
91
95
  sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
92
- sds sdsjoin(char **argv, int argc, char *sep);
96
+ sds sdsjoin(char **argv, int argc, char *sep, size_t seplen);
97
+ sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);
93
98
 
94
99
  /* Low level functions exposed to the user API */
95
100
  sds sdsMakeRoomFor(sds s, size_t addlen);
data/deps/hiredis/test.c CHANGED
@@ -8,12 +8,15 @@
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"
14
+ #include "net.h"
13
15
 
14
16
  enum connection_type {
15
17
  CONN_TCP,
16
- CONN_UNIX
18
+ CONN_UNIX,
19
+ CONN_FD
17
20
  };
18
21
 
19
22
  struct config {
@@ -22,6 +25,7 @@ struct config {
22
25
  struct {
23
26
  const char *host;
24
27
  int port;
28
+ struct timeval timeout;
25
29
  } tcp;
26
30
 
27
31
  struct {
@@ -40,6 +44,13 @@ static long long usec(void) {
40
44
  return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;
41
45
  }
42
46
 
47
+ /* The assert() calls below have side effects, so we need assert()
48
+ * even if we are compiling without asserts (-DNDEBUG). */
49
+ #ifdef NDEBUG
50
+ #undef assert
51
+ #define assert(e) (void)(e)
52
+ #endif
53
+
43
54
  static redisContext *select_database(redisContext *c) {
44
55
  redisReply *reply;
45
56
 
@@ -62,7 +73,7 @@ static redisContext *select_database(redisContext *c) {
62
73
  return c;
63
74
  }
64
75
 
65
- static void disconnect(redisContext *c) {
76
+ static int disconnect(redisContext *c, int keep_fd) {
66
77
  redisReply *reply;
67
78
 
68
79
  /* Make sure we're on DB 9. */
@@ -73,8 +84,11 @@ static void disconnect(redisContext *c) {
73
84
  assert(reply != NULL);
74
85
  freeReplyObject(reply);
75
86
 
76
- /* Free the context as well. */
87
+ /* Free the context as well, but keep the fd if requested. */
88
+ if (keep_fd)
89
+ return redisFreeKeepFd(c);
77
90
  redisFree(c);
91
+ return -1;
78
92
  }
79
93
 
80
94
  static redisContext *connect(struct config config) {
@@ -84,12 +98,24 @@ static redisContext *connect(struct config config) {
84
98
  c = redisConnect(config.tcp.host, config.tcp.port);
85
99
  } else if (config.type == CONN_UNIX) {
86
100
  c = redisConnectUnix(config.unix.path);
101
+ } else if (config.type == CONN_FD) {
102
+ /* Create a dummy connection just to get an fd to inherit */
103
+ redisContext *dummy_ctx = redisConnectUnix(config.unix.path);
104
+ if (dummy_ctx) {
105
+ int fd = disconnect(dummy_ctx, 1);
106
+ printf("Connecting to inherited fd %d\n", fd);
107
+ c = redisConnectFd(fd);
108
+ }
87
109
  } else {
88
110
  assert(NULL);
89
111
  }
90
112
 
91
- if (c->err) {
113
+ if (c == NULL) {
114
+ printf("Connection error: can't allocate redis context\n");
115
+ exit(1);
116
+ } else if (c->err) {
92
117
  printf("Connection error: %s\n", c->errstr);
118
+ redisFree(c);
93
119
  exit(1);
94
120
  }
95
121
 
@@ -125,13 +151,13 @@ static void test_format_commands(void) {
125
151
  free(cmd);
126
152
 
127
153
  test("Format command with %%b string interpolation: ");
128
- len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3);
154
+ len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"b\0r",(size_t)3);
129
155
  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
156
  len == 4+4+(3+2)+4+(3+2)+4+(3+2));
131
157
  free(cmd);
132
158
 
133
159
  test("Format command with %%b and an empty string: ");
134
- len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"",0);
160
+ len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"",(size_t)0);
135
161
  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
162
  len == 4+4+(3+2)+4+(3+2)+4+(0+2));
137
163
  free(cmd);
@@ -177,7 +203,7 @@ static void test_format_commands(void) {
177
203
  FLOAT_WIDTH_TEST(double);
178
204
 
179
205
  test("Format command with invalid printf format: ");
180
- len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",3);
206
+ len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",(size_t)3);
181
207
  test_cond(len == -1);
182
208
 
183
209
  const char *argv[3];
@@ -200,10 +226,33 @@ static void test_format_commands(void) {
200
226
  free(cmd);
201
227
  }
202
228
 
229
+ static void test_append_formatted_commands(struct config config) {
230
+ redisContext *c;
231
+ redisReply *reply;
232
+ char *cmd;
233
+ int len;
234
+
235
+ c = connect(config);
236
+
237
+ test("Append format command: ");
238
+
239
+ len = redisFormatCommand(&cmd, "SET foo bar");
240
+
241
+ test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK);
242
+
243
+ assert(redisGetReply(c, (void*)&reply) == REDIS_OK);
244
+
245
+ free(cmd);
246
+ freeReplyObject(reply);
247
+
248
+ disconnect(c, 0);
249
+ }
250
+
203
251
  static void test_reply_reader(void) {
204
252
  redisReader *reader;
205
253
  void *reply;
206
254
  int ret;
255
+ int i;
207
256
 
208
257
  test("Error handling in reply parser: ");
209
258
  reader = redisReaderCreate();
@@ -225,12 +274,13 @@ static void test_reply_reader(void) {
225
274
  strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0);
226
275
  redisReaderFree(reader);
227
276
 
228
- test("Set error on nested multi bulks with depth > 2: ");
277
+ test("Set error on nested multi bulks with depth > 7: ");
229
278
  reader = redisReaderCreate();
230
- redisReaderFeed(reader,(char*)"*1\r\n",4);
231
- redisReaderFeed(reader,(char*)"*1\r\n",4);
232
- redisReaderFeed(reader,(char*)"*1\r\n",4);
233
- redisReaderFeed(reader,(char*)"*1\r\n",4);
279
+
280
+ for (i = 0; i < 9; i++) {
281
+ redisReaderFeed(reader,(char*)"*1\r\n",4);
282
+ }
283
+
234
284
  ret = redisReaderGetReply(reader,NULL);
235
285
  test_cond(ret == REDIS_ERR &&
236
286
  strncasecmp(reader->errstr,"No support for",14) == 0);
@@ -277,14 +327,32 @@ static void test_reply_reader(void) {
277
327
  redisReaderFree(reader);
278
328
  }
279
329
 
330
+ static void test_free_null(void) {
331
+ void *redisContext = NULL;
332
+ void *reply = NULL;
333
+
334
+ test("Don't fail when redisFree is passed a NULL value: ");
335
+ redisFree(redisContext);
336
+ test_cond(redisContext == NULL);
337
+
338
+ test("Don't fail when freeReplyObject is passed a NULL value: ");
339
+ freeReplyObject(reply);
340
+ test_cond(reply == NULL);
341
+ }
342
+
280
343
  static void test_blocking_connection_errors(void) {
281
344
  redisContext *c;
282
345
 
283
346
  test("Returns error when host cannot be resolved: ");
284
- c = redisConnect((char*)"idontexist.local", 6379);
347
+ c = redisConnect((char*)"idontexist.test", 6379);
285
348
  test_cond(c->err == REDIS_ERR_OTHER &&
286
349
  (strcmp(c->errstr,"Name or service not known") == 0 ||
287
- strcmp(c->errstr,"Can't resolve: idontexist.local") == 0));
350
+ strcmp(c->errstr,"Can't resolve: idontexist.test") == 0 ||
351
+ strcmp(c->errstr,"nodename nor servname provided, or not known") == 0 ||
352
+ strcmp(c->errstr,"No address associated with hostname") == 0 ||
353
+ strcmp(c->errstr,"Temporary failure in name resolution") == 0 ||
354
+ strcmp(c->errstr,"hostname nor servname provided, or not known") == 0 ||
355
+ strcmp(c->errstr,"no address associated with name") == 0));
288
356
  redisFree(c);
289
357
 
290
358
  test("Returns error when the port is not open: ");
@@ -326,7 +394,7 @@ static void test_blocking_connection(struct config config) {
326
394
  freeReplyObject(reply);
327
395
 
328
396
  test("%%b String interpolation works: ");
329
- reply = redisCommand(c,"SET %b %b","foo",3,"hello\x00world",11);
397
+ reply = redisCommand(c,"SET %b %b","foo",(size_t)3,"hello\x00world",(size_t)11);
330
398
  freeReplyObject(reply);
331
399
  reply = redisCommand(c,"GET foo");
332
400
  test_cond(reply->type == REDIS_REPLY_STRING &&
@@ -374,7 +442,53 @@ static void test_blocking_connection(struct config config) {
374
442
  strcasecmp(reply->element[1]->str,"pong") == 0);
375
443
  freeReplyObject(reply);
376
444
 
377
- disconnect(c);
445
+ disconnect(c, 0);
446
+ }
447
+
448
+ static void test_blocking_connection_timeouts(struct config config) {
449
+ redisContext *c;
450
+ redisReply *reply;
451
+ ssize_t s;
452
+ const char *cmd = "DEBUG SLEEP 3\r\n";
453
+ struct timeval tv;
454
+
455
+ c = connect(config);
456
+ test("Successfully completes a command when the timeout is not exceeded: ");
457
+ reply = redisCommand(c,"SET foo fast");
458
+ freeReplyObject(reply);
459
+ tv.tv_sec = 0;
460
+ tv.tv_usec = 10000;
461
+ redisSetTimeout(c, tv);
462
+ reply = redisCommand(c, "GET foo");
463
+ test_cond(reply != NULL && reply->type == REDIS_REPLY_STRING && memcmp(reply->str, "fast", 4) == 0);
464
+ freeReplyObject(reply);
465
+ disconnect(c, 0);
466
+
467
+ c = connect(config);
468
+ test("Does not return a reply when the command times out: ");
469
+ s = write(c->fd, cmd, strlen(cmd));
470
+ tv.tv_sec = 0;
471
+ tv.tv_usec = 10000;
472
+ redisSetTimeout(c, tv);
473
+ reply = redisCommand(c, "GET foo");
474
+ test_cond(s > 0 && reply == NULL && c->err == REDIS_ERR_IO && strcmp(c->errstr, "Resource temporarily unavailable") == 0);
475
+ freeReplyObject(reply);
476
+
477
+ test("Reconnect properly reconnects after a timeout: ");
478
+ redisReconnect(c);
479
+ reply = redisCommand(c, "PING");
480
+ test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
481
+ freeReplyObject(reply);
482
+
483
+ test("Reconnect properly uses owned parameters: ");
484
+ config.tcp.host = "foo";
485
+ config.unix.path = "foo";
486
+ redisReconnect(c);
487
+ reply = redisCommand(c, "PING");
488
+ test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
489
+ freeReplyObject(reply);
490
+
491
+ disconnect(c, 0);
378
492
  }
379
493
 
380
494
  static void test_blocking_io_errors(struct config config) {
@@ -400,7 +514,7 @@ static void test_blocking_io_errors(struct config config) {
400
514
 
401
515
  test("Returns I/O error when the connection is lost: ");
402
516
  reply = redisCommand(c,"QUIT");
403
- if (major >= 2 && minor > 0) {
517
+ if (major > 2 || (major == 2 && minor > 0)) {
404
518
  /* > 2.0 returns OK on QUIT and read() should be issued once more
405
519
  * to know the descriptor is at EOF. */
406
520
  test_cond(strcasecmp(reply->str,"OK") == 0 &&
@@ -428,6 +542,30 @@ static void test_blocking_io_errors(struct config config) {
428
542
  redisFree(c);
429
543
  }
430
544
 
545
+ static void test_invalid_timeout_errors(struct config config) {
546
+ redisContext *c;
547
+
548
+ test("Set error when an invalid timeout usec value is given to redisConnectWithTimeout: ");
549
+
550
+ config.tcp.timeout.tv_sec = 0;
551
+ config.tcp.timeout.tv_usec = 10000001;
552
+
553
+ c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
554
+
555
+ test_cond(c->err == REDIS_ERR_IO);
556
+ redisFree(c);
557
+
558
+ test("Set error when an invalid timeout sec value is given to redisConnectWithTimeout: ");
559
+
560
+ config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1;
561
+ config.tcp.timeout.tv_usec = 0;
562
+
563
+ c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
564
+
565
+ test_cond(c->err == REDIS_ERR_IO);
566
+ redisFree(c);
567
+ }
568
+
431
569
  static void test_throughput(struct config config) {
432
570
  redisContext *c = connect(config);
433
571
  redisReply **replies;
@@ -490,7 +628,7 @@ static void test_throughput(struct config config) {
490
628
  free(replies);
491
629
  printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
492
630
 
493
- disconnect(c);
631
+ disconnect(c, 0);
494
632
  }
495
633
 
496
634
  // static long __test_callback_flags = 0;
@@ -603,6 +741,7 @@ int main(int argc, char **argv) {
603
741
  }
604
742
  };
605
743
  int throughput = 1;
744
+ int test_inherit_fd = 1;
606
745
 
607
746
  /* Ignore broken pipe signal (for I/O error tests). */
608
747
  signal(SIGPIPE, SIG_IGN);
@@ -621,6 +760,8 @@ int main(int argc, char **argv) {
621
760
  cfg.unix.path = argv[0];
622
761
  } else if (argc >= 1 && !strcmp(argv[0],"--skip-throughput")) {
623
762
  throughput = 0;
763
+ } else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) {
764
+ test_inherit_fd = 0;
624
765
  } else {
625
766
  fprintf(stderr, "Invalid argument: %s\n", argv[0]);
626
767
  exit(1);
@@ -631,19 +772,31 @@ int main(int argc, char **argv) {
631
772
  test_format_commands();
632
773
  test_reply_reader();
633
774
  test_blocking_connection_errors();
775
+ test_free_null();
634
776
 
635
777
  printf("\nTesting against TCP connection (%s:%d):\n", cfg.tcp.host, cfg.tcp.port);
636
778
  cfg.type = CONN_TCP;
637
779
  test_blocking_connection(cfg);
780
+ test_blocking_connection_timeouts(cfg);
638
781
  test_blocking_io_errors(cfg);
782
+ test_invalid_timeout_errors(cfg);
783
+ test_append_formatted_commands(cfg);
639
784
  if (throughput) test_throughput(cfg);
640
785
 
641
786
  printf("\nTesting against Unix socket connection (%s):\n", cfg.unix.path);
642
787
  cfg.type = CONN_UNIX;
643
788
  test_blocking_connection(cfg);
789
+ test_blocking_connection_timeouts(cfg);
644
790
  test_blocking_io_errors(cfg);
645
791
  if (throughput) test_throughput(cfg);
646
792
 
793
+ if (test_inherit_fd) {
794
+ printf("\nTesting against inherited fd (%s):\n", cfg.unix.path);
795
+ cfg.type = CONN_FD;
796
+ test_blocking_connection(cfg);
797
+ }
798
+
799
+
647
800
  if (fails) {
648
801
  printf("*** %d TESTS FAILED ***\n", fails);
649
802
  return 1;
@@ -0,0 +1,42 @@
1
+ #ifndef _WIN32_HELPER_INCLUDE
2
+ #define _WIN32_HELPER_INCLUDE
3
+ #ifdef _MSC_VER
4
+
5
+ #ifndef inline
6
+ #define inline __inline
7
+ #endif
8
+
9
+ #ifndef va_copy
10
+ #define va_copy(d,s) ((d) = (s))
11
+ #endif
12
+
13
+ #ifndef snprintf
14
+ #define snprintf c99_snprintf
15
+
16
+ __inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap)
17
+ {
18
+ int count = -1;
19
+
20
+ if (size != 0)
21
+ count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
22
+ if (count == -1)
23
+ count = _vscprintf(format, ap);
24
+
25
+ return count;
26
+ }
27
+
28
+ __inline int c99_snprintf(char* str, size_t size, const char* format, ...)
29
+ {
30
+ int count;
31
+ va_list ap;
32
+
33
+ va_start(ap, format);
34
+ count = c99_vsnprintf(str, size, format, ap);
35
+ va_end(ap);
36
+
37
+ return count;
38
+ }
39
+ #endif
40
+
41
+ #endif
42
+ #endif
data/librb/durable.rb CHANGED
@@ -427,9 +427,17 @@ module Durable
427
427
  rule_name = "r_#{index}"
428
428
  rule = nil
429
429
  if block
430
- run_lambda = -> c {
431
- c.instance_exec c, &block
432
- }
430
+ run_lambda = nil
431
+ if block.arity < 2
432
+ run_lambda = -> c {
433
+ c.instance_exec c, &block
434
+ }
435
+ else
436
+ run_lambda = -> (c, complete) {
437
+ c.instance_exec c, complete, &block
438
+ }
439
+ end
440
+
433
441
  rule = operator ? {operator => expression_definition, :run => run_lambda} : {:run => run_lambda}
434
442
  else
435
443
  rule = operator ? {operator => expression_definition} : {}
@@ -475,8 +483,18 @@ module Durable
475
483
  def to(state_name, rule = nil, &block)
476
484
  rule = define_rule(nil, nil, {}, &block) if !rule
477
485
  rule[:to] = state_name
478
- if block
479
- rule[:run] = -> s {s.instance_exec(s, &block)}
486
+ if block
487
+ if block.arity < 2
488
+ rule[:run] = -> c {
489
+ c.instance_exec c, &block
490
+ }
491
+ else
492
+ rule[:run] = -> (c, complete) {
493
+ c.instance_exec c, complete, &block
494
+ }
495
+ end
496
+ else
497
+ rule[:run] = -> c {}
480
498
  end
481
499
  self
482
500
  end
@@ -536,7 +554,18 @@ module Durable
536
554
 
537
555
  def stage(stage_name, &block)
538
556
  if block
539
- @stages[stage_name] = {:run => -> s {s.instance_exec(s, &block)}, :to => {}}
557
+ run_lambda = nil
558
+ if block.arity < 2
559
+ run_lambda = -> c {
560
+ c.instance_exec c, &block
561
+ }
562
+ else
563
+ run_lambda = -> (c, complete) {
564
+ c.instance_exec c, complete, &block
565
+ }
566
+ end
567
+
568
+ @stages[stage_name] = {:run => run_lambda, :to => {}}
540
569
  else
541
570
  @stages[stage_name] = {:to => {}}
542
571
  end