nutcracker 0.2.4.1 → 0.2.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/README.md +28 -10
  2. data/Rakefile +5 -19
  3. data/bin/nutcracker +6 -1
  4. data/ext/nutcracker/ChangeLog +9 -0
  5. data/ext/nutcracker/Makefile.in +54 -29
  6. data/ext/nutcracker/README.md +13 -11
  7. data/ext/nutcracker/aclocal.m4 +46 -26
  8. data/ext/nutcracker/config/config.guess +209 -240
  9. data/ext/nutcracker/config/config.sub +157 -70
  10. data/ext/nutcracker/config/depcomp +66 -8
  11. data/ext/nutcracker/config/install-sh +18 -11
  12. data/ext/nutcracker/config/ltmain.sh +2632 -1384
  13. data/ext/nutcracker/config/missing +4 -49
  14. data/ext/nutcracker/configure +2866 -2118
  15. data/ext/nutcracker/configure.ac +1 -1
  16. data/ext/nutcracker/contrib/Makefile.in +17 -10
  17. data/ext/nutcracker/m4/libtool.m4 +1437 -812
  18. data/ext/nutcracker/m4/ltoptions.m4 +24 -8
  19. data/ext/nutcracker/m4/ltversion.m4 +6 -6
  20. data/ext/nutcracker/m4/lt~obsolete.m4 +9 -3
  21. data/ext/nutcracker/notes/recommendation.md +21 -2
  22. data/ext/nutcracker/notes/redis.md +9 -9
  23. data/ext/nutcracker/scripts/redis-check.sh +9 -0
  24. data/ext/nutcracker/src/Makefile.in +18 -11
  25. data/ext/nutcracker/src/hashkit/Makefile.am +1 -0
  26. data/ext/nutcracker/src/hashkit/Makefile.in +23 -13
  27. data/ext/nutcracker/src/hashkit/nc_crc16.c +66 -0
  28. data/ext/nutcracker/src/hashkit/nc_hashkit.h +2 -0
  29. data/ext/nutcracker/src/hashkit/nc_modula.c +18 -6
  30. data/ext/nutcracker/src/nc_conf.c +14 -35
  31. data/ext/nutcracker/src/nc_conf.h +1 -1
  32. data/ext/nutcracker/src/nc_message.h +2 -0
  33. data/ext/nutcracker/src/nc_server.c +9 -7
  34. data/ext/nutcracker/src/proto/Makefile.in +16 -9
  35. data/ext/nutcracker/src/proto/nc_redis.c +17 -4
  36. data/lib/nutcracker/version.rb +1 -1
  37. data/lib/nutcracker.rb +60 -2
  38. metadata +3 -2
@@ -1109,14 +1109,6 @@ conf_pre_validate(struct conf *cf)
1109
1109
  return NC_OK;
1110
1110
  }
1111
1111
 
1112
- static int
1113
- conf_server_pname_cmp(const void *t1, const void *t2)
1114
- {
1115
- const struct conf_server *s1 = t1, *s2 = t2;
1116
-
1117
- return string_compare(&s1->pname, &s2->pname);
1118
- }
1119
-
1120
1112
  static int
1121
1113
  conf_server_name_cmp(const void *t1, const void *t2)
1122
1114
  {
@@ -1156,27 +1148,10 @@ conf_validate_server(struct conf *cf, struct conf_pool *cp)
1156
1148
 
1157
1149
  /*
1158
1150
  * Disallow duplicate servers - servers with identical "host:port:weight"
1159
- * or "name" combination are considered as duplicates
1151
+ * or "name" combination are considered as duplicates. When server name
1152
+ * is configured, we only check for duplicate "name" and not for duplicate
1153
+ * "host:port:weight"
1160
1154
  */
1161
- array_sort(&cp->server, conf_server_pname_cmp);
1162
- for (valid = true, i = 0; i < nserver - 1; i++) {
1163
- struct conf_server *cs1, *cs2;
1164
-
1165
- cs1 = array_get(&cp->server, i);
1166
- cs2 = array_get(&cp->server, i + 1);
1167
-
1168
- if (string_compare(&cs1->pname, &cs2->pname) == 0) {
1169
- log_error("conf: pool '%.*s' has servers with same name '%.*s'",
1170
- cp->name.len, cp->name.data, cs1->pname.len,
1171
- cs1->pname.data);
1172
- valid = false;
1173
- break;
1174
- }
1175
- }
1176
- if (!valid) {
1177
- return NC_ERROR;
1178
- }
1179
-
1180
1155
  array_sort(&cp->server, conf_server_name_cmp);
1181
1156
  for (valid = true, i = 0; i < nserver - 1; i++) {
1182
1157
  struct conf_server *cs1, *cs2;
@@ -1497,7 +1472,7 @@ conf_add_server(struct conf *cf, struct command *cmd, void *conf)
1497
1472
  struct conf_server *field;
1498
1473
  uint8_t *p, *q, *start;
1499
1474
  uint8_t *pname, *addr, *port, *weight, *name;
1500
- uint32_t k, pnamelen, addrlen, portlen, weightlen, namelen;
1475
+ uint32_t k, delimlen, pnamelen, addrlen, portlen, weightlen, namelen;
1501
1476
  struct string address;
1502
1477
  char delim[] = " ::";
1503
1478
 
@@ -1514,7 +1489,7 @@ conf_add_server(struct conf *cf, struct command *cmd, void *conf)
1514
1489
 
1515
1490
  value = array_top(&cf->arg);
1516
1491
 
1517
- /* parse "hostname:port:weight [name]" from the end */
1492
+ /* parse "hostname:port:weight [name]" or "/path/unix_socket:weight [name]" from the end */
1518
1493
  p = value->data + value->len - 1;
1519
1494
  start = value->data;
1520
1495
  addr = NULL;
@@ -1526,6 +1501,8 @@ conf_add_server(struct conf *cf, struct command *cmd, void *conf)
1526
1501
  name = NULL;
1527
1502
  namelen = 0;
1528
1503
 
1504
+ delimlen = value->data[0] == '/' ? 2 : 3;
1505
+
1529
1506
  for (k = 0; k < sizeof(delim); k++) {
1530
1507
  q = nc_strrchr(p, start, delim[k]);
1531
1508
  if (q == NULL) {
@@ -1562,8 +1539,8 @@ conf_add_server(struct conf *cf, struct command *cmd, void *conf)
1562
1539
  p = q - 1;
1563
1540
  }
1564
1541
 
1565
- if (k != 3) {
1566
- return "has an invalid \"hostname:port:weight [name]\" format string";
1542
+ if (k != delimlen) {
1543
+ return "has an invalid \"hostname:port:weight [name]\"or \"/path/unix_socket:weight [name]\" format string";
1567
1544
  }
1568
1545
 
1569
1546
  pname = value->data;
@@ -1582,9 +1559,11 @@ conf_add_server(struct conf *cf, struct command *cmd, void *conf)
1582
1559
  return "has an invalid weight in \"hostname:port:weight [name]\" format string";
1583
1560
  }
1584
1561
 
1585
- field->port = nc_atoi(port, portlen);
1586
- if (field->port < 0 || !nc_valid_port(field->port)) {
1587
- return "has an invalid port in \"hostname:port:weight [name]\" format string";
1562
+ if (value->data[0] != '/') {
1563
+ field->port = nc_atoi(port, portlen);
1564
+ if (field->port < 0 || !nc_valid_port(field->port)) {
1565
+ return "has an invalid port in \"hostname:port:weight [name]\" format string";
1566
+ }
1588
1567
  }
1589
1568
 
1590
1569
  if (name == NULL) {
@@ -120,7 +120,7 @@ char *conf_set_string(struct conf *cf, struct command *cmd, void *conf);
120
120
  char *conf_set_listen(struct conf *cf, struct command *cmd, void *conf);
121
121
  char *conf_add_server(struct conf *cf, struct command *cmd, void *conf);
122
122
  char *conf_set_num(struct conf *cf, struct command *cmd, void *conf);
123
- char * conf_set_bool(struct conf *cf, struct command *cmd, void *conf);
123
+ char *conf_set_bool(struct conf *cf, struct command *cmd, void *conf);
124
124
  char *conf_set_hash(struct conf *cf, struct command *cmd, void *conf);
125
125
  char *conf_set_distribution(struct conf *cf, struct command *cmd, void *conf);
126
126
  char *conf_set_hashtag(struct conf *cf, struct command *cmd, void *conf);
@@ -71,6 +71,7 @@ typedef enum msg_type {
71
71
  MSG_REQ_REDIS_BITCOUNT,
72
72
  MSG_REQ_REDIS_DECR,
73
73
  MSG_REQ_REDIS_DECRBY,
74
+ MSG_REQ_REDIS_DUMP,
74
75
  MSG_REQ_REDIS_GET,
75
76
  MSG_REQ_REDIS_GETBIT,
76
77
  MSG_REQ_REDIS_GETRANGE,
@@ -80,6 +81,7 @@ typedef enum msg_type {
80
81
  MSG_REQ_REDIS_INCRBYFLOAT,
81
82
  MSG_REQ_REDIS_MGET,
82
83
  MSG_REQ_REDIS_PSETEX,
84
+ MSG_REQ_REDIS_RESTORE,
83
85
  MSG_REQ_REDIS_SET,
84
86
  MSG_REQ_REDIS_SETBIT,
85
87
  MSG_REQ_REDIS_SETEX,
@@ -451,7 +451,7 @@ server_connect(struct context *ctx, struct server *server, struct conn *conn)
451
451
  log_debug(LOG_VVERB, "connect to server '%.*s'", server->pname.len,
452
452
  server->pname.data);
453
453
 
454
- conn->sd = socket(conn->family, SOCK_STREAM, 0);
454
+ conn->sd = socket(conn->family, SOCK_STREAM, 0);
455
455
  if (conn->sd < 0) {
456
456
  log_error("socket for server '%.*s' failed: %s", server->pname.len,
457
457
  server->pname.data, strerror(errno));
@@ -467,11 +467,13 @@ server_connect(struct context *ctx, struct server *server, struct conn *conn)
467
467
  goto error;
468
468
  }
469
469
 
470
- status = nc_set_tcpnodelay(conn->sd);
471
- if (status != NC_OK) {
472
- log_warn("set tcpnodelay on s %d for server '%.*s' failed, ignored: %s",
473
- conn->sd, server->pname.len, server->pname.data,
474
- strerror(errno));
470
+ if (server->pname.data[0] != '/') {
471
+ status = nc_set_tcpnodelay(conn->sd);
472
+ if (status != NC_OK) {
473
+ log_warn("set tcpnodelay on s %d for server '%.*s' failed, ignored: %s",
474
+ conn->sd, server->pname.len, server->pname.data,
475
+ strerror(errno));
476
+ }
475
477
  }
476
478
 
477
479
  status = event_add_conn(ctx->ep, conn);
@@ -484,7 +486,7 @@ server_connect(struct context *ctx, struct server *server, struct conn *conn)
484
486
 
485
487
  ASSERT(!conn->connecting && !conn->connected);
486
488
 
487
- status = connect(conn->sd, conn->addr, conn->addrlen);
489
+ status = connect(conn->sd, conn->addr, conn->addrlen);
488
490
  if (status != NC_OK) {
489
491
  if (errno == EINPROGRESS) {
490
492
  conn->connecting = 1;
@@ -1,9 +1,9 @@
1
- # Makefile.in generated by automake 1.11 from Makefile.am.
1
+ # Makefile.in generated by automake 1.11.3 from Makefile.am.
2
2
  # @configure_input@
3
3
 
4
4
  # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5
- # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
6
- # Inc.
5
+ # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
6
+ # Foundation, Inc.
7
7
  # This Makefile.in is free software; the Free Software Foundation
8
8
  # gives unlimited permission to copy and/or distribute it,
9
9
  # with or without modifications, as long as this notice is preserved.
@@ -93,6 +93,7 @@ CXXFLAGS = @CXXFLAGS@
93
93
  CYGPATH_W = @CYGPATH_W@
94
94
  DEFS = @DEFS@
95
95
  DEPDIR = @DEPDIR@
96
+ DLLTOOL = @DLLTOOL@
96
97
  DSYMUTIL = @DSYMUTIL@
97
98
  DUMPBIN = @DUMPBIN@
98
99
  ECHO_C = @ECHO_C@
@@ -116,6 +117,7 @@ LIPO = @LIPO@
116
117
  LN_S = @LN_S@
117
118
  LTLIBOBJS = @LTLIBOBJS@
118
119
  MAKEINFO = @MAKEINFO@
120
+ MANIFEST_TOOL = @MANIFEST_TOOL@
119
121
  MKDIR_P = @MKDIR_P@
120
122
  NM = @NM@
121
123
  NMEDIT = @NMEDIT@
@@ -141,6 +143,7 @@ abs_builddir = @abs_builddir@
141
143
  abs_srcdir = @abs_srcdir@
142
144
  abs_top_builddir = @abs_top_builddir@
143
145
  abs_top_srcdir = @abs_top_srcdir@
146
+ ac_ct_AR = @ac_ct_AR@
144
147
  ac_ct_CC = @ac_ct_CC@
145
148
  ac_ct_CXX = @ac_ct_CXX@
146
149
  ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
@@ -174,7 +177,6 @@ libdir = @libdir@
174
177
  libexecdir = @libexecdir@
175
178
  localedir = @localedir@
176
179
  localstatedir = @localstatedir@
177
- lt_ECHO = @lt_ECHO@
178
180
  mandir = @mandir@
179
181
  mkdir_p = @mkdir_p@
180
182
  oldincludedir = @oldincludedir@
@@ -237,7 +239,7 @@ $(am__aclocal_m4_deps):
237
239
 
238
240
  clean-noinstLIBRARIES:
239
241
  -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
240
- libproto.a: $(libproto_a_OBJECTS) $(libproto_a_DEPENDENCIES)
242
+ libproto.a: $(libproto_a_OBJECTS) $(libproto_a_DEPENDENCIES) $(EXTRA_libproto_a_DEPENDENCIES)
241
243
  -rm -f libproto.a
242
244
  $(libproto_a_AR) libproto.a $(libproto_a_OBJECTS) $(libproto_a_LIBADD)
243
245
  $(RANLIB) libproto.a
@@ -374,10 +376,15 @@ install-am: all-am
374
376
 
375
377
  installcheck: installcheck-am
376
378
  install-strip:
377
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
378
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
379
- `test -z '$(STRIP)' || \
380
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
379
+ if test -z '$(STRIP)'; then \
380
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
381
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
382
+ install; \
383
+ else \
384
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
385
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
386
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
387
+ fi
381
388
  mostlyclean-generic:
382
389
 
383
390
  clean-generic:
@@ -34,6 +34,7 @@ redis_arg0(struct msg *r)
34
34
  case MSG_REQ_REDIS_PTTL:
35
35
  case MSG_REQ_REDIS_TTL:
36
36
  case MSG_REQ_REDIS_TYPE:
37
+ case MSG_REQ_REDIS_DUMP:
37
38
 
38
39
  case MSG_REQ_REDIS_DECR:
39
40
  case MSG_REQ_REDIS_GET:
@@ -138,6 +139,8 @@ redis_arg2(struct msg *r)
138
139
  case MSG_REQ_REDIS_ZINCRBY:
139
140
  case MSG_REQ_REDIS_ZREMRANGEBYRANK:
140
141
  case MSG_REQ_REDIS_ZREMRANGEBYSCORE:
142
+
143
+ case MSG_REQ_REDIS_RESTORE:
141
144
  return true;
142
145
 
143
146
  default:
@@ -458,6 +461,11 @@ redis_parse_req(struct msg *r)
458
461
  break;
459
462
  }
460
463
 
464
+ if (str4icmp(m, 'd', 'u', 'm', 'p')) {
465
+ r->type = MSG_REQ_REDIS_DUMP;
466
+ break;
467
+ }
468
+
461
469
  if (str4icmp(m, 'h', 'd', 'e', 'l')) {
462
470
  r->type = MSG_REQ_REDIS_HDEL;
463
471
  break;
@@ -767,6 +775,11 @@ redis_parse_req(struct msg *r)
767
775
  break;
768
776
  }
769
777
 
778
+ if (str7icmp(m, 'r', 'e', 's', 't', 'o', 'r', 'e')) {
779
+ r->type = MSG_REQ_REDIS_RESTORE;
780
+ break;
781
+ }
782
+
770
783
  break;
771
784
 
772
785
  case 8:
@@ -947,11 +960,11 @@ redis_parse_req(struct msg *r)
947
960
  "key", r->id, r->type);
948
961
  goto error;
949
962
  }
950
- if (r->rlen > mbuf_data_size()) {
963
+ if (r->rlen >= mbuf_data_size()) {
951
964
  log_error("parsed bad req %"PRIu64" of type %d with key "
952
- "length %d that exceeds maximum redis key "
953
- "length of %d", r->id, r->type, r->rlen,
954
- mbuf_data_size());
965
+ "length %d that greater than or equal to maximum"
966
+ " redis key length of %d", r->id, r->type,
967
+ r->rlen, mbuf_data_size());
955
968
  goto error;
956
969
  }
957
970
  if (r->rnarg == 0) {
@@ -1,3 +1,3 @@
1
1
  module Nutcracker
2
- VERSION = "0.2.4.1".freeze
2
+ VERSION = "0.2.4.2".freeze
3
3
  end
data/lib/nutcracker.rb CHANGED
@@ -1,7 +1,65 @@
1
1
  require 'nutcracker/version'
2
+ require 'socket'
3
+ require 'json'
2
4
 
3
5
  module Nutcracker
6
+
7
+ def self.start options
8
+ Nutcracker::Process.new(options).start
9
+ end
10
+
11
+ def self.executable
12
+ File.expand_path("../../ext/nutcracker/src/nutcracker", __FILE__)
13
+ end
14
+
4
15
  def self.version
5
- VERSION
16
+ Nutcracker::VERSION
6
17
  end
7
- end
18
+
19
+ class Process
20
+ attr_reader :pid, :options
21
+
22
+ def initialize options
23
+ @options = options
24
+ end
25
+
26
+ def start
27
+ raise RuntimeError, "Nutcracker is already running (#{pid})..." if running?
28
+ @pid = ::Process.spawn("#{Nutcracker.executable} -c #{options.fetch(:config_file).inspect}")
29
+ Kernel.at_exit { stop if running? }
30
+ self
31
+ end
32
+
33
+ def running?
34
+ !!(pid and ::Process.getpgid pid rescue false)
35
+ end
36
+
37
+ def stop
38
+ signal :TERM
39
+ end
40
+
41
+ def kill
42
+ signal :KILL
43
+ end
44
+
45
+ def join
46
+ verify_running! and ::Process.waitpid2 pid
47
+ end
48
+
49
+ def stats
50
+ JSON.parse TCPSocket.new('localhost',22222).read rescue {}
51
+ end
52
+
53
+ private
54
+
55
+ def verify_running!
56
+ running? or raise RuntimeError, "Nutcracker isn't running..."
57
+ end
58
+
59
+ def signal term
60
+ verify_running! and ::Process.kill(term, pid)
61
+ end
62
+
63
+ end
64
+
65
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nutcracker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4.1
4
+ version: 0.2.4.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-20 00:00:00.000000000 Z
12
+ date: 2013-05-22 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Gem/Bundler benefits for Twitter's Nutcraker C app
15
15
  email: eran@kontera.com
@@ -113,6 +113,7 @@ files:
113
113
  - ext/nutcracker/scripts/redis-check.sh
114
114
  - ext/nutcracker/src/hashkit/Makefile.am
115
115
  - ext/nutcracker/src/hashkit/Makefile.in
116
+ - ext/nutcracker/src/hashkit/nc_crc16.c
116
117
  - ext/nutcracker/src/hashkit/nc_crc32.c
117
118
  - ext/nutcracker/src/hashkit/nc_fnv.c
118
119
  - ext/nutcracker/src/hashkit/nc_hashkit.h