nutcracker 0.2.4.1 → 0.2.4.2

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.
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