nutcracker 0.3.0.12 → 0.4.0.13

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 (107) hide show
  1. checksums.yaml +5 -13
  2. data/README.md +3 -3
  3. data/Rakefile +12 -10
  4. data/ext/nutcracker/Makefile.in +215 -162
  5. data/ext/nutcracker/README.md +16 -4
  6. data/ext/nutcracker/aclocal.m4 +432 -254
  7. data/ext/nutcracker/{contrib/yaml-0.1.4/configure → autom4te.cache/output.0} +11367 -4545
  8. data/ext/nutcracker/autom4te.cache/output.1 +19907 -0
  9. data/ext/nutcracker/autom4te.cache/output.2 +19907 -0
  10. data/ext/nutcracker/autom4te.cache/requests +518 -0
  11. data/ext/nutcracker/autom4te.cache/traces.0 +2715 -0
  12. data/ext/nutcracker/autom4te.cache/traces.1 +967 -0
  13. data/ext/nutcracker/autom4te.cache/traces.2 +2715 -0
  14. data/ext/nutcracker/config/compile +347 -0
  15. data/ext/nutcracker/config/config.guess +116 -78
  16. data/ext/nutcracker/config/config.sub +65 -45
  17. data/ext/nutcracker/config/depcomp +295 -192
  18. data/ext/nutcracker/config/install-sh +7 -7
  19. data/ext/nutcracker/config/ltmain.sh +15 -20
  20. data/ext/nutcracker/config/missing +149 -265
  21. data/ext/nutcracker/configure +493 -367
  22. data/ext/nutcracker/contrib/Makefile.in +158 -116
  23. data/ext/nutcracker/extconf.rb +0 -1
  24. data/ext/nutcracker/m4/libtool.m4 +4 -23
  25. data/ext/nutcracker/m4/ltoptions.m4 +0 -0
  26. data/ext/nutcracker/m4/ltsugar.m4 +0 -0
  27. data/ext/nutcracker/m4/ltversion.m4 +0 -0
  28. data/ext/nutcracker/m4/lt~obsolete.m4 +0 -0
  29. data/ext/nutcracker/notes/recommendation.md +1 -1
  30. data/ext/nutcracker/notes/redis.md +35 -3
  31. data/ext/nutcracker/scripts/benchmark-mget.py +43 -0
  32. data/ext/nutcracker/scripts/nutcracker.spec +61 -3
  33. data/ext/nutcracker/scripts/redis-check.sh +43 -0
  34. data/ext/nutcracker/src/Makefile.in +205 -142
  35. data/ext/nutcracker/src/event/Makefile.in +164 -66
  36. data/ext/nutcracker/src/hashkit/Makefile.in +164 -66
  37. data/ext/nutcracker/src/nc_conf.c +2 -0
  38. data/ext/nutcracker/src/nc_connection.c +31 -0
  39. data/ext/nutcracker/src/nc_connection.h +3 -0
  40. data/ext/nutcracker/src/nc_core.c +38 -2
  41. data/ext/nutcracker/src/nc_core.h +11 -0
  42. data/ext/nutcracker/src/nc_log.c +90 -12
  43. data/ext/nutcracker/src/nc_log.h +11 -0
  44. data/ext/nutcracker/src/nc_mbuf.h +1 -1
  45. data/ext/nutcracker/src/nc_message.c +162 -116
  46. data/ext/nutcracker/src/nc_message.h +161 -129
  47. data/ext/nutcracker/src/nc_proxy.c +34 -4
  48. data/ext/nutcracker/src/nc_request.c +158 -32
  49. data/ext/nutcracker/src/nc_server.c +59 -5
  50. data/ext/nutcracker/src/nc_server.h +1 -0
  51. data/ext/nutcracker/src/nc_signal.c +2 -2
  52. data/ext/nutcracker/src/nc_stats.c +21 -0
  53. data/ext/nutcracker/src/nc_stats.h +28 -26
  54. data/ext/nutcracker/src/nc_string.c +176 -1
  55. data/ext/nutcracker/src/nc_string.h +26 -0
  56. data/ext/nutcracker/src/nc_util.c +12 -0
  57. data/ext/nutcracker/src/nc_util.h +1 -0
  58. data/ext/nutcracker/src/proto/Makefile.in +164 -66
  59. data/ext/nutcracker/src/proto/nc_memcache.c +279 -88
  60. data/ext/nutcracker/src/proto/nc_proto.h +3 -4
  61. data/ext/nutcracker/src/proto/nc_redis.c +561 -134
  62. data/lib/nutcracker/version.rb +1 -1
  63. metadata +31 -67
  64. data/ext/nutcracker/contrib/yaml-0.1.4/LICENSE +0 -19
  65. data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.am +0 -20
  66. data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.in +0 -736
  67. data/ext/nutcracker/contrib/yaml-0.1.4/README +0 -27
  68. data/ext/nutcracker/contrib/yaml-0.1.4/aclocal.m4 +0 -956
  69. data/ext/nutcracker/contrib/yaml-0.1.4/config.h.in +0 -80
  70. data/ext/nutcracker/contrib/yaml-0.1.4/config/config.guess +0 -1561
  71. data/ext/nutcracker/contrib/yaml-0.1.4/config/config.sub +0 -1686
  72. data/ext/nutcracker/contrib/yaml-0.1.4/config/depcomp +0 -630
  73. data/ext/nutcracker/contrib/yaml-0.1.4/config/install-sh +0 -520
  74. data/ext/nutcracker/contrib/yaml-0.1.4/config/ltmain.sh +0 -8406
  75. data/ext/nutcracker/contrib/yaml-0.1.4/config/missing +0 -376
  76. data/ext/nutcracker/contrib/yaml-0.1.4/configure.ac +0 -75
  77. data/ext/nutcracker/contrib/yaml-0.1.4/doc/doxygen.cfg +0 -222
  78. data/ext/nutcracker/contrib/yaml-0.1.4/include/yaml.h +0 -1971
  79. data/ext/nutcracker/contrib/yaml-0.1.4/m4/libtool.m4 +0 -7357
  80. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltoptions.m4 +0 -368
  81. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltsugar.m4 +0 -123
  82. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltversion.m4 +0 -23
  83. data/ext/nutcracker/contrib/yaml-0.1.4/m4/lt~obsolete.m4 +0 -92
  84. data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.am +0 -4
  85. data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.in +0 -484
  86. data/ext/nutcracker/contrib/yaml-0.1.4/src/api.c +0 -1392
  87. data/ext/nutcracker/contrib/yaml-0.1.4/src/dumper.c +0 -394
  88. data/ext/nutcracker/contrib/yaml-0.1.4/src/emitter.c +0 -2329
  89. data/ext/nutcracker/contrib/yaml-0.1.4/src/loader.c +0 -432
  90. data/ext/nutcracker/contrib/yaml-0.1.4/src/parser.c +0 -1374
  91. data/ext/nutcracker/contrib/yaml-0.1.4/src/reader.c +0 -465
  92. data/ext/nutcracker/contrib/yaml-0.1.4/src/scanner.c +0 -3570
  93. data/ext/nutcracker/contrib/yaml-0.1.4/src/writer.c +0 -141
  94. data/ext/nutcracker/contrib/yaml-0.1.4/src/yaml_private.h +0 -640
  95. data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.am +0 -8
  96. data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.in +0 -675
  97. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor-alt.c +0 -800
  98. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor.c +0 -1130
  99. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter-alt.c +0 -217
  100. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter.c +0 -202
  101. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-dumper.c +0 -311
  102. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-emitter.c +0 -327
  103. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-loader.c +0 -63
  104. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-parser.c +0 -63
  105. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-scanner.c +0 -63
  106. data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-reader.c +0 -354
  107. data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-version.c +0 -29
@@ -299,6 +299,18 @@ nc_stacktrace(int skip_count)
299
299
  #endif
300
300
  }
301
301
 
302
+ void
303
+ nc_stacktrace_fd(int fd)
304
+ {
305
+ #ifdef NC_HAVE_BACKTRACE
306
+ void *stack[64];
307
+ int size;
308
+
309
+ size = backtrace(stack, 64);
310
+ backtrace_symbols_fd(stack, size, fd);
311
+ #endif
312
+ }
313
+
302
314
  void
303
315
  nc_assert(const char *cond, const char *file, int line, int panic)
304
316
  {
@@ -185,6 +185,7 @@ ssize_t _nc_recvn(int sd, void *vptr, size_t n);
185
185
 
186
186
  void nc_assert(const char *cond, const char *file, int line, int panic);
187
187
  void nc_stacktrace(int skip_count);
188
+ void nc_stacktrace_fd(int fd);
188
189
 
189
190
  int _scnprintf(char *buf, size_t size, const char *fmt, ...);
190
191
  int _vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
@@ -1,9 +1,8 @@
1
- # Makefile.in generated by automake 1.11.3 from Makefile.am.
1
+ # Makefile.in generated by automake 1.14.1 from Makefile.am.
2
2
  # @configure_input@
3
3
 
4
- # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5
- # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
6
- # Foundation, Inc.
4
+ # Copyright (C) 1994-2013 Free Software Foundation, Inc.
5
+
7
6
  # This Makefile.in is free software; the Free Software Foundation
8
7
  # gives unlimited permission to copy and/or distribute it,
9
8
  # with or without modifications, as long as this notice is preserved.
@@ -17,6 +16,51 @@
17
16
 
18
17
 
19
18
  VPATH = @srcdir@
19
+ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
20
+ am__make_running_with_option = \
21
+ case $${target_option-} in \
22
+ ?) ;; \
23
+ *) echo "am__make_running_with_option: internal error: invalid" \
24
+ "target option '$${target_option-}' specified" >&2; \
25
+ exit 1;; \
26
+ esac; \
27
+ has_opt=no; \
28
+ sane_makeflags=$$MAKEFLAGS; \
29
+ if $(am__is_gnu_make); then \
30
+ sane_makeflags=$$MFLAGS; \
31
+ else \
32
+ case $$MAKEFLAGS in \
33
+ *\\[\ \ ]*) \
34
+ bs=\\; \
35
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
36
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
37
+ esac; \
38
+ fi; \
39
+ skip_next=no; \
40
+ strip_trailopt () \
41
+ { \
42
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
43
+ }; \
44
+ for flg in $$sane_makeflags; do \
45
+ test $$skip_next = yes && { skip_next=no; continue; }; \
46
+ case $$flg in \
47
+ *=*|--*) continue;; \
48
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
49
+ -*I?*) strip_trailopt 'I';; \
50
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
51
+ -*O?*) strip_trailopt 'O';; \
52
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
53
+ -*l?*) strip_trailopt 'l';; \
54
+ -[dEDm]) skip_next=yes;; \
55
+ -[JT]) skip_next=yes;; \
56
+ esac; \
57
+ case $$flg in \
58
+ *$$target_option*) has_opt=yes; break;; \
59
+ esac; \
60
+ done; \
61
+ test $$has_opt = yes
62
+ am__make_dryrun = (target_option=n; $(am__make_running_with_option))
63
+ am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
20
64
  pkgdatadir = $(datadir)/@PACKAGE@
21
65
  pkgincludedir = $(includedir)/@PACKAGE@
22
66
  pkglibdir = $(libdir)/@PACKAGE@
@@ -36,8 +80,8 @@ POST_UNINSTALL = :
36
80
  build_triplet = @build@
37
81
  host_triplet = @host@
38
82
  subdir = src/proto
39
- DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
40
- $(srcdir)/Makefile.in
83
+ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
84
+ $(top_srcdir)/config/depcomp $(noinst_HEADERS)
41
85
  ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
42
86
  am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
43
87
  $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
@@ -51,31 +95,83 @@ CONFIG_CLEAN_FILES =
51
95
  CONFIG_CLEAN_VPATH_FILES =
52
96
  LIBRARIES = $(noinst_LIBRARIES)
53
97
  ARFLAGS = cru
98
+ AM_V_AR = $(am__v_AR_@AM_V@)
99
+ am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
100
+ am__v_AR_0 = @echo " AR " $@;
101
+ am__v_AR_1 =
54
102
  libproto_a_AR = $(AR) $(ARFLAGS)
55
103
  libproto_a_LIBADD =
56
104
  am_libproto_a_OBJECTS = nc_memcache.$(OBJEXT) nc_redis.$(OBJEXT)
57
105
  libproto_a_OBJECTS = $(am_libproto_a_OBJECTS)
106
+ AM_V_P = $(am__v_P_@AM_V@)
107
+ am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
108
+ am__v_P_0 = false
109
+ am__v_P_1 = :
110
+ AM_V_GEN = $(am__v_GEN_@AM_V@)
111
+ am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
112
+ am__v_GEN_0 = @echo " GEN " $@;
113
+ am__v_GEN_1 =
114
+ AM_V_at = $(am__v_at_@AM_V@)
115
+ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
116
+ am__v_at_0 = @
117
+ am__v_at_1 =
58
118
  DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
59
119
  depcomp = $(SHELL) $(top_srcdir)/config/depcomp
60
120
  am__depfiles_maybe = depfiles
61
121
  am__mv = mv -f
62
122
  COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
63
123
  $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
64
- LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
65
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
66
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
124
+ AM_V_lt = $(am__v_lt_@AM_V@)
125
+ am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
126
+ am__v_lt_0 = --silent
127
+ am__v_lt_1 =
128
+ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
129
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
130
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
131
+ $(AM_CFLAGS) $(CFLAGS)
132
+ AM_V_CC = $(am__v_CC_@AM_V@)
133
+ am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
134
+ am__v_CC_0 = @echo " CC " $@;
135
+ am__v_CC_1 =
67
136
  CCLD = $(CC)
68
- LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
69
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
70
- $(LDFLAGS) -o $@
137
+ LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
138
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
139
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
140
+ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
141
+ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
142
+ am__v_CCLD_0 = @echo " CCLD " $@;
143
+ am__v_CCLD_1 =
71
144
  SOURCES = $(libproto_a_SOURCES)
72
145
  DIST_SOURCES = $(libproto_a_SOURCES)
146
+ am__can_run_installinfo = \
147
+ case $$AM_UPDATE_INFO_DIR in \
148
+ n|no|NO) false;; \
149
+ *) (install-info --version) >/dev/null 2>&1;; \
150
+ esac
73
151
  HEADERS = $(noinst_HEADERS)
152
+ am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
153
+ # Read a list of newline-separated strings from the standard input,
154
+ # and print each of them once, without duplicates. Input order is
155
+ # *not* preserved.
156
+ am__uniquify_input = $(AWK) '\
157
+ BEGIN { nonempty = 0; } \
158
+ { items[$$0] = 1; nonempty = 1; } \
159
+ END { if (nonempty) { for (i in items) print i; }; } \
160
+ '
161
+ # Make sure the list of sources is unique. This is necessary because,
162
+ # e.g., the same source file might be shared among _SOURCES variables
163
+ # for different programs/libraries.
164
+ am__define_uniq_tagged_files = \
165
+ list='$(am__tagged_files)'; \
166
+ unique=`for i in $$list; do \
167
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
168
+ done | $(am__uniquify_input)`
74
169
  ETAGS = etags
75
170
  CTAGS = ctags
76
171
  DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
77
172
  ACLOCAL = @ACLOCAL@
78
173
  AMTAR = @AMTAR@
174
+ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
79
175
  AR = @AR@
80
176
  AUTOCONF = @AUTOCONF@
81
177
  AUTOHEADER = @AUTOHEADER@
@@ -239,10 +335,11 @@ $(am__aclocal_m4_deps):
239
335
 
240
336
  clean-noinstLIBRARIES:
241
337
  -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
338
+
242
339
  libproto.a: $(libproto_a_OBJECTS) $(libproto_a_DEPENDENCIES) $(EXTRA_libproto_a_DEPENDENCIES)
243
- -rm -f libproto.a
244
- $(libproto_a_AR) libproto.a $(libproto_a_OBJECTS) $(libproto_a_LIBADD)
245
- $(RANLIB) libproto.a
340
+ $(AM_V_at)-rm -f libproto.a
341
+ $(AM_V_AR)$(libproto_a_AR) libproto.a $(libproto_a_OBJECTS) $(libproto_a_LIBADD)
342
+ $(AM_V_at)$(RANLIB) libproto.a
246
343
 
247
344
  mostlyclean-compile:
248
345
  -rm -f *.$(OBJEXT)
@@ -254,25 +351,25 @@ distclean-compile:
254
351
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nc_redis.Po@am__quote@
255
352
 
256
353
  .c.o:
257
- @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
258
- @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
259
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
354
+ @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
355
+ @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
356
+ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
260
357
  @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
261
- @am__fastdepCC_FALSE@ $(COMPILE) -c $<
358
+ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
262
359
 
263
360
  .c.obj:
264
- @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
265
- @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
266
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
361
+ @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
362
+ @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
363
+ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
267
364
  @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
268
- @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
365
+ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
269
366
 
270
367
  .c.lo:
271
- @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
272
- @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
273
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
368
+ @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
369
+ @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
370
+ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
274
371
  @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
275
- @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
372
+ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
276
373
 
277
374
  mostlyclean-libtool:
278
375
  -rm -f *.lo
@@ -280,26 +377,15 @@ mostlyclean-libtool:
280
377
  clean-libtool:
281
378
  -rm -rf .libs _libs
282
379
 
283
- ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
284
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
285
- unique=`for i in $$list; do \
286
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
287
- done | \
288
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
289
- END { if (nonempty) { for (i in files) print i; }; }'`; \
290
- mkid -fID $$unique
291
- tags: TAGS
292
-
293
- TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
294
- $(TAGS_FILES) $(LISP)
380
+ ID: $(am__tagged_files)
381
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
382
+ tags: tags-am
383
+ TAGS: tags
384
+
385
+ tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
295
386
  set x; \
296
387
  here=`pwd`; \
297
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
298
- unique=`for i in $$list; do \
299
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
300
- done | \
301
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
302
- END { if (nonempty) { for (i in files) print i; }; }'`; \
388
+ $(am__define_uniq_tagged_files); \
303
389
  shift; \
304
390
  if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
305
391
  test -n "$$unique" || unique=$$empty_fix; \
@@ -311,15 +397,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
311
397
  $$unique; \
312
398
  fi; \
313
399
  fi
314
- ctags: CTAGS
315
- CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
316
- $(TAGS_FILES) $(LISP)
317
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
318
- unique=`for i in $$list; do \
319
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
320
- done | \
321
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
322
- END { if (nonempty) { for (i in files) print i; }; }'`; \
400
+ ctags: ctags-am
401
+
402
+ CTAGS: ctags
403
+ ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
404
+ $(am__define_uniq_tagged_files); \
323
405
  test -z "$(CTAGS_ARGS)$$unique" \
324
406
  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
325
407
  $$unique
@@ -328,6 +410,21 @@ GTAGS:
328
410
  here=`$(am__cd) $(top_builddir) && pwd` \
329
411
  && $(am__cd) $(top_srcdir) \
330
412
  && gtags -i $(GTAGS_ARGS) "$$here"
413
+ cscopelist: cscopelist-am
414
+
415
+ cscopelist-am: $(am__tagged_files)
416
+ list='$(am__tagged_files)'; \
417
+ case "$(srcdir)" in \
418
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
419
+ *) sdir=$(subdir)/$(srcdir) ;; \
420
+ esac; \
421
+ for i in $$list; do \
422
+ if test -f "$$i"; then \
423
+ echo "$(subdir)/$$i"; \
424
+ else \
425
+ echo "$$sdir/$$i"; \
426
+ fi; \
427
+ done >> $(top_builddir)/cscope.files
331
428
 
332
429
  distclean-tags:
333
430
  -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
@@ -470,18 +567,19 @@ uninstall-am:
470
567
 
471
568
  .MAKE: install-am install-strip
472
569
 
473
- .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
474
- clean-libtool clean-noinstLIBRARIES ctags distclean \
475
- distclean-compile distclean-generic distclean-libtool \
476
- distclean-tags distdir dvi dvi-am html html-am info info-am \
477
- install install-am install-data install-data-am install-dvi \
478
- install-dvi-am install-exec install-exec-am install-html \
479
- install-html-am install-info install-info-am install-man \
480
- install-pdf install-pdf-am install-ps install-ps-am \
481
- install-strip installcheck installcheck-am installdirs \
482
- maintainer-clean maintainer-clean-generic mostlyclean \
483
- mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
484
- pdf pdf-am ps ps-am tags uninstall uninstall-am
570
+ .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
571
+ clean-libtool clean-noinstLIBRARIES cscopelist-am ctags \
572
+ ctags-am distclean distclean-compile distclean-generic \
573
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
574
+ html-am info info-am install install-am install-data \
575
+ install-data-am install-dvi install-dvi-am install-exec \
576
+ install-exec-am install-html install-html-am install-info \
577
+ install-info-am install-man install-pdf install-pdf-am \
578
+ install-ps install-ps-am install-strip installcheck \
579
+ installcheck-am installdirs maintainer-clean \
580
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
581
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
582
+ tags tags-am uninstall uninstall-am
485
583
 
486
584
 
487
585
  # Tell versions [3.59,3.63) of GNU make to not export all variables.
@@ -192,6 +192,7 @@ memcache_parse_req(struct msg *r)
192
192
  m = r->token;
193
193
  r->token = NULL;
194
194
  r->type = MSG_UNKNOWN;
195
+ r->narg++;
195
196
 
196
197
  switch (p - m) {
197
198
 
@@ -307,23 +308,35 @@ memcache_parse_req(struct msg *r)
307
308
 
308
309
  case SW_SPACES_BEFORE_KEY:
309
310
  if (ch != ' ') {
310
- r->token = p;
311
- r->key_start = p;
311
+ p = p - 1; /* go back by 1 byte */
312
+ r->token = NULL;
312
313
  state = SW_KEY;
313
314
  }
314
-
315
315
  break;
316
316
 
317
317
  case SW_KEY:
318
+ if (r->token == NULL) {
319
+ r->token = p;
320
+ }
318
321
  if (ch == ' ' || ch == CR) {
319
- if ((p - r->key_start) > MEMCACHE_MAX_KEY_LENGTH) {
322
+ struct keypos *kpos;
323
+
324
+ if ((p - r->token) > MEMCACHE_MAX_KEY_LENGTH) {
320
325
  log_error("parsed bad req %"PRIu64" of type %d with key "
321
326
  "prefix '%.*s...' and length %d that exceeds "
322
327
  "maximum key length", r->id, r->type, 16,
323
- r->key_start, p - r->key_start);
328
+ r->token, p - r->token);
324
329
  goto error;
325
330
  }
326
- r->key_end = p;
331
+
332
+ kpos = array_push(r->keys);
333
+ if (kpos == NULL) {
334
+ goto enomem;
335
+ }
336
+ kpos->start = r->token;
337
+ kpos->end = p;
338
+
339
+ r->narg++;
327
340
  r->token = NULL;
328
341
 
329
342
  /* get next state */
@@ -360,8 +373,9 @@ memcache_parse_req(struct msg *r)
360
373
  break;
361
374
 
362
375
  default:
363
- r->token = p;
364
- goto fragment;
376
+ r->token = NULL;
377
+ p = p - 1; /* go back by 1 byte */
378
+ state = SW_KEY;
365
379
  }
366
380
 
367
381
  break;
@@ -424,7 +438,6 @@ memcache_parse_req(struct msg *r)
424
438
  goto error;
425
439
  }
426
440
  /* vlen_start <- p */
427
- r->token = p;
428
441
  r->vlen = (uint32_t)(ch - '0');
429
442
  state = SW_VLEN;
430
443
  }
@@ -677,19 +690,6 @@ memcache_parse_req(struct msg *r)
677
690
  r->state, r->pos - b->pos, b->last - b->pos);
678
691
  return;
679
692
 
680
- fragment:
681
- ASSERT(p != b->last);
682
- ASSERT(r->token != NULL);
683
- r->pos = r->token;
684
- r->token = NULL;
685
- r->state = state;
686
- r->result = MSG_PARSE_FRAGMENT;
687
-
688
- log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "parsed req %"PRIu64" res %d "
689
- "type %d state %d rpos %d of %d", r->id, r->result, r->type,
690
- r->state, r->pos - b->pos, b->last - b->pos);
691
- return;
692
-
693
693
  done:
694
694
  ASSERT(r->type > MSG_UNKNOWN && r->type < MSG_SENTINEL);
695
695
  r->pos = p + 1;
@@ -702,6 +702,15 @@ done:
702
702
  r->state, r->pos - b->pos, b->last - b->pos);
703
703
  return;
704
704
 
705
+ enomem:
706
+ r->result = MSG_PARSE_ERROR;
707
+ r->state = state;
708
+
709
+ log_hexdump(LOG_INFO, b->pos, mbuf_length(b), "out of memory on parse req %"PRIu64" "
710
+ "res %d type %d state %d", r->id, r->result, r->type, r->state);
711
+
712
+ return;
713
+
705
714
  error:
706
715
  r->result = MSG_PARSE_ERROR;
707
716
  r->state = state;
@@ -724,17 +733,17 @@ memcache_parse_rsp(struct msg *r)
724
733
  SW_RSP_STR,
725
734
  SW_SPACES_BEFORE_KEY,
726
735
  SW_KEY,
727
- SW_SPACES_BEFORE_FLAGS,
736
+ SW_SPACES_BEFORE_FLAGS, /* 5 */
728
737
  SW_FLAGS,
729
738
  SW_SPACES_BEFORE_VLEN,
730
739
  SW_VLEN,
731
740
  SW_RUNTO_VAL,
732
- SW_VAL,
741
+ SW_VAL, /* 10 */
733
742
  SW_VAL_LF,
734
743
  SW_END,
735
744
  SW_RUNTO_CRLF,
736
745
  SW_CRLF,
737
- SW_ALMOST_DONE,
746
+ SW_ALMOST_DONE, /* 15 */
738
747
  SW_SENTINEL
739
748
  } state;
740
749
 
@@ -795,14 +804,14 @@ memcache_parse_rsp(struct msg *r)
795
804
  if (ch == ' ' || ch == CR) {
796
805
  /* type_end <- p - 1 */
797
806
  m = r->token;
798
- r->token = NULL;
807
+ /* r->token = NULL; */
799
808
  r->type = MSG_UNKNOWN;
800
809
 
801
810
  switch (p - m) {
802
811
  case 3:
803
812
  if (str4cmp(m, 'E', 'N', 'D', '\r')) {
804
813
  r->type = MSG_RSP_MC_END;
805
- /* end_start <- m; end_end <- p - 1*/
814
+ /* end_start <- m; end_end <- p - 1 */
806
815
  r->end = m;
807
816
  break;
808
817
  }
@@ -924,21 +933,8 @@ memcache_parse_rsp(struct msg *r)
924
933
  break;
925
934
 
926
935
  case SW_KEY:
927
- if (r->token == NULL) {
928
- r->token = p;
929
- r->key_start = p;
930
- }
931
-
932
936
  if (ch == ' ') {
933
- if ((p - r->key_start) > MEMCACHE_MAX_KEY_LENGTH) {
934
- log_error("parsed bad req %"PRIu64" of type %d with key "
935
- "prefix '%.*s...' and length %d that exceeds "
936
- "maximum key length", r->id, r->type, 16,
937
- r->key_start, p - r->key_start);
938
- goto error;
939
- }
940
- r->key_end = p;
941
- r->token = NULL;
937
+ /* r->token = NULL; */
942
938
  state = SW_SPACES_BEFORE_FLAGS;
943
939
  }
944
940
 
@@ -958,7 +954,7 @@ memcache_parse_rsp(struct msg *r)
958
954
  case SW_FLAGS:
959
955
  if (r->token == NULL) {
960
956
  /* flags_start <- p */
961
- r->token = p;
957
+ /* r->token = p; */
962
958
  }
963
959
 
964
960
  if (isdigit(ch)) {
@@ -966,7 +962,7 @@ memcache_parse_rsp(struct msg *r)
966
962
  ;
967
963
  } else if (ch == ' ') {
968
964
  /* flags_end <- p - 1 */
969
- r->token = NULL;
965
+ /* r->token = NULL; */
970
966
  state = SW_SPACES_BEFORE_VLEN;
971
967
  } else {
972
968
  goto error;
@@ -981,21 +977,18 @@ memcache_parse_rsp(struct msg *r)
981
977
  }
982
978
  p = p - 1; /* go back by 1 byte */
983
979
  state = SW_VLEN;
980
+ r->vlen = 0;
984
981
  }
985
982
 
986
983
  break;
987
984
 
988
985
  case SW_VLEN:
989
- if (r->token == NULL) {
990
- /* vlen_start <- p */
991
- r->token = p;
992
- r->vlen = (uint32_t)(ch - '0');
993
- } else if (isdigit(ch)) {
986
+ if (isdigit(ch)) {
994
987
  r->vlen = r->vlen * 10 + (uint32_t)(ch - '0');
995
988
  } else if (ch == ' ' || ch == CR) {
996
989
  /* vlen_end <- p - 1 */
997
990
  p = p - 1; /* go back by 1 byte */
998
- r->token = NULL;
991
+ /* r->token = NULL; */
999
992
  state = SW_RUNTO_CRLF;
1000
993
  } else {
1001
994
  goto error;
@@ -1008,6 +1001,7 @@ memcache_parse_rsp(struct msg *r)
1008
1001
  case LF:
1009
1002
  /* val_start <- p + 1 */
1010
1003
  state = SW_VAL;
1004
+ r->token = NULL;
1011
1005
  break;
1012
1006
 
1013
1007
  default:
@@ -1041,7 +1035,8 @@ memcache_parse_rsp(struct msg *r)
1041
1035
  case SW_VAL_LF:
1042
1036
  switch (ch) {
1043
1037
  case LF:
1044
- state = SW_END;
1038
+ /* state = SW_END; */
1039
+ state = SW_RSP_STR;
1045
1040
  break;
1046
1041
 
1047
1042
  default:
@@ -1134,6 +1129,9 @@ memcache_parse_rsp(struct msg *r)
1134
1129
  r->state = state;
1135
1130
 
1136
1131
  if (b->last == b->end && r->token != NULL) {
1132
+ if (state <= SW_RUNTO_VAL || state == SW_CRLF || state == SW_ALMOST_DONE) {
1133
+ r->state = SW_START;
1134
+ }
1137
1135
  r->pos = r->token;
1138
1136
  r->token = NULL;
1139
1137
  r->result = MSG_PARSE_REPAIR;
@@ -1169,52 +1167,139 @@ error:
1169
1167
  r->state);
1170
1168
  }
1171
1169
 
1172
- /*
1173
- * Pre-split copy handler invoked when the request is a multi vector -
1174
- * 'get' or 'gets' request and is about to be split into two requests
1175
- */
1176
- void
1177
- memcache_pre_splitcopy(struct mbuf *mbuf, void *arg)
1170
+ static rstatus_t
1171
+ memcache_append_key(struct msg *r, uint8_t *key, uint32_t keylen)
1178
1172
  {
1179
- struct msg *r = arg; /* request vector */
1180
- struct string get = string("get "); /* 'get ' string */
1181
- struct string gets = string("gets "); /* 'gets ' string */
1173
+ struct mbuf *mbuf;
1174
+ struct keypos *kpos;
1182
1175
 
1183
- ASSERT(r->request);
1184
- ASSERT(!r->redis);
1185
- ASSERT(mbuf_empty(mbuf));
1176
+ mbuf = msg_ensure_mbuf(r, keylen + 2);
1177
+ if (mbuf == NULL) {
1178
+ return NC_ENOMEM;
1179
+ }
1186
1180
 
1187
- switch (r->type) {
1188
- case MSG_REQ_MC_GET:
1189
- mbuf_copy(mbuf, get.data, get.len);
1190
- break;
1181
+ kpos = array_push(r->keys);
1182
+ if (kpos == NULL) {
1183
+ return NC_ENOMEM;
1184
+ }
1191
1185
 
1192
- case MSG_REQ_MC_GETS:
1193
- mbuf_copy(mbuf, gets.data, gets.len);
1194
- break;
1186
+ kpos->start = mbuf->last;
1187
+ kpos->end = mbuf->last + keylen;
1188
+ mbuf_copy(mbuf, key, keylen);
1189
+ r->mlen += keylen;
1195
1190
 
1196
- default:
1197
- NOT_REACHED();
1198
- }
1191
+ mbuf_copy(mbuf, (uint8_t *)" ", 1);
1192
+ r->mlen += 1;
1193
+ return NC_OK;
1199
1194
  }
1200
1195
 
1201
1196
  /*
1202
- * Post-split copy handler invoked when the request is a multi vector -
1203
- * 'get' or 'gets' request and has already been split into two requests
1197
+ * read the comment in proto/nc_redis.c
1204
1198
  */
1205
- rstatus_t
1206
- memcache_post_splitcopy(struct msg *r)
1199
+ static rstatus_t
1200
+ memcache_fragment_retrieval(struct msg *r, uint32_t ncontinuum,
1201
+ struct msg_tqh *frag_msgq,
1202
+ uint32_t key_step)
1207
1203
  {
1208
1204
  struct mbuf *mbuf;
1209
- struct string crlf = string(CRLF);
1205
+ struct msg **sub_msgs;
1206
+ uint32_t i;
1207
+ rstatus_t status;
1210
1208
 
1211
- ASSERT(r->request);
1212
- ASSERT(!r->redis);
1213
- ASSERT(!STAILQ_EMPTY(&r->mhdr));
1209
+ sub_msgs = nc_zalloc(ncontinuum * sizeof(*sub_msgs));
1210
+ if (sub_msgs == NULL) {
1211
+ return NC_ENOMEM;
1212
+ }
1213
+
1214
+ ASSERT(r->frag_seq == NULL);
1215
+ r->frag_seq = nc_alloc(array_n(r->keys) * sizeof(*r->frag_seq));
1216
+ if (r->frag_seq == NULL) {
1217
+ nc_free(sub_msgs);
1218
+ return NC_ENOMEM;
1219
+ }
1220
+
1221
+ mbuf = STAILQ_FIRST(&r->mhdr);
1222
+ mbuf->pos = mbuf->start;
1223
+
1224
+ /*
1225
+ * This code is based on the assumption that 'gets ' is located
1226
+ * in a contiguous location.
1227
+ * This is always true because we have capped our MBUF_MIN_SIZE at 512 and
1228
+ * whenever we have multiple messages, we copy the tail message into a new mbuf
1229
+ */
1230
+ for (; *(mbuf->pos) != ' ';) { /* eat get/gets */
1231
+ mbuf->pos++;
1232
+ }
1233
+ mbuf->pos++;
1234
+
1235
+ r->frag_id = msg_gen_frag_id();
1236
+ r->nfrag = 0;
1237
+ r->frag_owner = r;
1238
+
1239
+ for (i = 0; i < array_n(r->keys); i++) { /* for each key */
1240
+ struct msg *sub_msg;
1241
+ struct keypos *kpos = array_get(r->keys, i);
1242
+ uint32_t idx = msg_backend_idx(r, kpos->start, kpos->end - kpos->start);
1243
+
1244
+ if (sub_msgs[idx] == NULL) {
1245
+ sub_msgs[idx] = msg_get(r->owner, r->request, r->redis);
1246
+ if (sub_msgs[idx] == NULL) {
1247
+ nc_free(sub_msgs);
1248
+ return NC_ENOMEM;
1249
+ }
1250
+ }
1251
+ r->frag_seq[i] = sub_msg = sub_msgs[idx];
1252
+
1253
+ sub_msg->narg++;
1254
+ status = memcache_append_key(sub_msg, kpos->start, kpos->end - kpos->start);
1255
+ if (status != NC_OK) {
1256
+ nc_free(sub_msgs);
1257
+ return status;
1258
+ }
1259
+ }
1260
+
1261
+ for (i = 0; i < ncontinuum; i++) { /* prepend mget header, and forward it */
1262
+ struct msg *sub_msg = sub_msgs[i];
1263
+ if (sub_msg == NULL) {
1264
+ continue;
1265
+ }
1266
+
1267
+ /* prepend get/gets */
1268
+ if (r->type == MSG_REQ_MC_GET) {
1269
+ status = msg_prepend(sub_msg, (uint8_t *)"get ", 4);
1270
+ } else if (r->type == MSG_REQ_MC_GETS) {
1271
+ status = msg_prepend(sub_msg, (uint8_t *)"gets ", 5);
1272
+ }
1273
+ if (status != NC_OK) {
1274
+ nc_free(sub_msgs);
1275
+ return status;
1276
+ }
1277
+
1278
+ /* append \r\n */
1279
+ status = msg_append(sub_msg, (uint8_t *)CRLF, CRLF_LEN);
1280
+ if (status != NC_OK) {
1281
+ nc_free(sub_msgs);
1282
+ return status;
1283
+ }
1214
1284
 
1215
- mbuf = STAILQ_LAST(&r->mhdr, mbuf, next);
1216
- mbuf_copy(mbuf, crlf.data, crlf.len);
1285
+ sub_msg->type = r->type;
1286
+ sub_msg->frag_id = r->frag_id;
1287
+ sub_msg->frag_owner = r->frag_owner;
1217
1288
 
1289
+ TAILQ_INSERT_TAIL(frag_msgq, sub_msg, m_tqe);
1290
+ r->nfrag++;
1291
+ }
1292
+
1293
+ nc_free(sub_msgs);
1294
+ return NC_OK;
1295
+ }
1296
+
1297
+ rstatus_t
1298
+ memcache_fragment(struct msg *r, uint32_t ncontinuum, struct msg_tqh *frag_msgq)
1299
+ {
1300
+ if (memcache_retrieval(r)) {
1301
+ return memcache_fragment_retrieval(r, ncontinuum, frag_msgq, 1);
1302
+ }
1218
1303
  return NC_OK;
1219
1304
  }
1220
1305
 
@@ -1237,6 +1322,7 @@ memcache_pre_coalesce(struct msg *r)
1237
1322
  return;
1238
1323
  }
1239
1324
 
1325
+ pr->frag_owner->nfrag_done++;
1240
1326
  switch (r->type) {
1241
1327
 
1242
1328
  case MSG_RSP_MC_VALUE:
@@ -1244,13 +1330,9 @@ memcache_pre_coalesce(struct msg *r)
1244
1330
 
1245
1331
  /*
1246
1332
  * Readjust responses of the fragmented message vector by not
1247
- * including the end marker for all but the last response
1333
+ * including the end marker for all
1248
1334
  */
1249
1335
 
1250
- if (pr->last_fragment) {
1251
- break;
1252
- }
1253
-
1254
1336
  ASSERT(r->end != NULL);
1255
1337
 
1256
1338
  for (;;) {
@@ -1294,6 +1376,84 @@ memcache_pre_coalesce(struct msg *r)
1294
1376
  }
1295
1377
  }
1296
1378
 
1379
+ /*
1380
+ * copy one response from src to dst
1381
+ * return bytes copied
1382
+ * */
1383
+ static rstatus_t
1384
+ memcache_copy_bulk(struct msg *dst, struct msg *src)
1385
+ {
1386
+ struct mbuf *mbuf, *nbuf;
1387
+ uint8_t *p;
1388
+ uint32_t len = 0;
1389
+ uint32_t bytes = 0;
1390
+ uint32_t i = 0;
1391
+
1392
+ for (mbuf = STAILQ_FIRST(&src->mhdr);
1393
+ mbuf && mbuf_empty(mbuf);
1394
+ mbuf = STAILQ_FIRST(&src->mhdr)) {
1395
+
1396
+ mbuf_remove(&src->mhdr, mbuf);
1397
+ mbuf_put(mbuf);
1398
+ }
1399
+
1400
+ mbuf = STAILQ_FIRST(&src->mhdr);
1401
+ if (mbuf == NULL) {
1402
+ return NC_OK; /* key not exists */
1403
+ }
1404
+ p = mbuf->pos;
1405
+
1406
+ /* get : VALUE key 0 len\r\nval\r\n */
1407
+ /* gets: VALUE key 0 len cas\r\nval\r\n */
1408
+
1409
+ ASSERT(*p == 'V');
1410
+ for (i = 0; i < 3; i++) { /* eat 'VALUE key 0 ' */
1411
+ for (; *p != ' ';) {
1412
+ p++;
1413
+ }
1414
+ p++;
1415
+ }
1416
+
1417
+ len = 0;
1418
+ for (; p < mbuf->last && isdigit(*p); p++) {
1419
+ len = len * 10 + (uint32_t)(*p - '0');
1420
+ }
1421
+
1422
+ for (; p < mbuf->last && ('\r' != *p); p++) { /* eat cas for gets */
1423
+ ;
1424
+ }
1425
+
1426
+ len += CRLF_LEN * 2;
1427
+ len += (p - mbuf->pos);
1428
+
1429
+ bytes = len;
1430
+
1431
+ /* copy len bytes to dst */
1432
+ for (; mbuf;) {
1433
+ if (mbuf_length(mbuf) <= len) { /* steal this mbuf from src to dst */
1434
+ nbuf = STAILQ_NEXT(mbuf, next);
1435
+ mbuf_remove(&src->mhdr, mbuf);
1436
+ mbuf_insert(&dst->mhdr, mbuf);
1437
+ len -= mbuf_length(mbuf);
1438
+ mbuf = nbuf;
1439
+ } else { /* split it */
1440
+ nbuf = mbuf_get();
1441
+ if (nbuf == NULL) {
1442
+ return NC_ENOMEM;
1443
+ }
1444
+ mbuf_copy(nbuf, mbuf->pos, len);
1445
+ mbuf_insert(&dst->mhdr, nbuf);
1446
+ mbuf->pos += len;
1447
+ break;
1448
+ }
1449
+ }
1450
+
1451
+ dst->mlen += bytes;
1452
+ src->mlen -= bytes;
1453
+ log_debug(LOG_VVERB, "memcache_copy_bulk copy bytes: %d", bytes);
1454
+ return NC_OK;
1455
+ }
1456
+
1297
1457
  /*
1298
1458
  * Post-coalesce handler is invoked when the message is a response to
1299
1459
  * the fragmented multi vector request - 'get' or 'gets' and all the
@@ -1301,6 +1461,37 @@ memcache_pre_coalesce(struct msg *r)
1301
1461
  * the fragmented request is consider to be done
1302
1462
  */
1303
1463
  void
1304
- memcache_post_coalesce(struct msg *r)
1464
+ memcache_post_coalesce(struct msg *request)
1305
1465
  {
1466
+ struct msg *response = request->peer;
1467
+ struct msg *sub_msg;
1468
+ uint32_t i;
1469
+ rstatus_t status;
1470
+
1471
+ ASSERT(!response->request);
1472
+ ASSERT(request->request && (request->frag_owner == request));
1473
+ if (request->error || request->ferror) {
1474
+ response->owner->err = 1;
1475
+ return;
1476
+ }
1477
+
1478
+ for (i = 0; i < array_n(request->keys); i++) { /* for each key */
1479
+ sub_msg = request->frag_seq[i]->peer; /* get it's peer response */
1480
+ if (sub_msg == NULL) {
1481
+ response->owner->err = 1;
1482
+ return;
1483
+ }
1484
+ status = memcache_copy_bulk(response, sub_msg);
1485
+ if (status != NC_OK) {
1486
+ response->owner->err = 1;
1487
+ return;
1488
+ }
1489
+ }
1490
+
1491
+ /* append END\r\n */
1492
+ status = msg_append(response, (uint8_t *)"END\r\n", 5);
1493
+ if (status != NC_OK) {
1494
+ response->owner->err = 1;
1495
+ return;
1496
+ }
1306
1497
  }