durable_rules 0.33.13 → 0.34.01

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