nutcracker 0.3.0.12 → 0.4.0.13

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