dalli_memcached 1.8.0

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 (209) hide show
  1. data/BENCHMARKS +142 -0
  2. data/CHANGELOG +176 -0
  3. data/Gemfile +11 -0
  4. data/Gemfile.lock +45 -0
  5. data/LICENSE +184 -0
  6. data/Manifest +209 -0
  7. data/README.rdoc +124 -0
  8. data/Rakefile +134 -0
  9. data/TODO +1 -0
  10. data/dalli_memcached.gemspec +0 -0
  11. data/ext/extconf-make.rb +25 -0
  12. data/ext/extconf.rb +78 -0
  13. data/ext/libmemcached-0.32/AUTHORS +7 -0
  14. data/ext/libmemcached-0.32/COPYING +32 -0
  15. data/ext/libmemcached-0.32/ChangeLog +303 -0
  16. data/ext/libmemcached-0.32/INSTALL +302 -0
  17. data/ext/libmemcached-0.32/Makefile.am +36 -0
  18. data/ext/libmemcached-0.32/Makefile.in +911 -0
  19. data/ext/libmemcached-0.32/NEWS +1 -0
  20. data/ext/libmemcached-0.32/README +33 -0
  21. data/ext/libmemcached-0.32/THANKS +14 -0
  22. data/ext/libmemcached-0.32/TODO +11 -0
  23. data/ext/libmemcached-0.32/aclocal.m4 +2108 -0
  24. data/ext/libmemcached-0.32/clients/Makefile.am +80 -0
  25. data/ext/libmemcached-0.32/clients/Makefile.in +773 -0
  26. data/ext/libmemcached-0.32/clients/client_options.h +32 -0
  27. data/ext/libmemcached-0.32/clients/execute.c +64 -0
  28. data/ext/libmemcached-0.32/clients/execute.h +5 -0
  29. data/ext/libmemcached-0.32/clients/generator.c +74 -0
  30. data/ext/libmemcached-0.32/clients/generator.h +20 -0
  31. data/ext/libmemcached-0.32/clients/memcat.c +178 -0
  32. data/ext/libmemcached-0.32/clients/memcp.c +251 -0
  33. data/ext/libmemcached-0.32/clients/memdump.c +170 -0
  34. data/ext/libmemcached-0.32/clients/memerror.c +80 -0
  35. data/ext/libmemcached-0.32/clients/memflush.c +143 -0
  36. data/ext/libmemcached-0.32/clients/memrm.c +160 -0
  37. data/ext/libmemcached-0.32/clients/memslap.c +441 -0
  38. data/ext/libmemcached-0.32/clients/memstat.c +326 -0
  39. data/ext/libmemcached-0.32/clients/utilities.c +207 -0
  40. data/ext/libmemcached-0.32/clients/utilities.h +41 -0
  41. data/ext/libmemcached-0.32/config.h.in +254 -0
  42. data/ext/libmemcached-0.32/config/compile +143 -0
  43. data/ext/libmemcached-0.32/config/config.guess +1561 -0
  44. data/ext/libmemcached-0.32/config/config.rpath +666 -0
  45. data/ext/libmemcached-0.32/config/config.sub +1686 -0
  46. data/ext/libmemcached-0.32/config/depcomp +630 -0
  47. data/ext/libmemcached-0.32/config/install-sh +520 -0
  48. data/ext/libmemcached-0.32/config/ltmain.sh +9636 -0
  49. data/ext/libmemcached-0.32/config/missing +376 -0
  50. data/ext/libmemcached-0.32/configure +23843 -0
  51. data/ext/libmemcached-0.32/configure.ac +120 -0
  52. data/ext/libmemcached-0.32/libmemcached/Makefile.am +111 -0
  53. data/ext/libmemcached-0.32/libmemcached/Makefile.in +1069 -0
  54. data/ext/libmemcached-0.32/libmemcached/byteorder.c +31 -0
  55. data/ext/libmemcached-0.32/libmemcached/common.h +189 -0
  56. data/ext/libmemcached-0.32/libmemcached/crc.c +86 -0
  57. data/ext/libmemcached-0.32/libmemcached/hsieh_hash.c +68 -0
  58. data/ext/libmemcached-0.32/libmemcached/jenkins_hash.c +213 -0
  59. data/ext/libmemcached-0.32/libmemcached/libmemcached.ver +1 -0
  60. data/ext/libmemcached-0.32/libmemcached/libmemcached_probes.d +30 -0
  61. data/ext/libmemcached-0.32/libmemcached/libmemcached_probes.h +82 -0
  62. data/ext/libmemcached-0.32/libmemcached/md5.c +354 -0
  63. data/ext/libmemcached-0.32/libmemcached/memcached.c +153 -0
  64. data/ext/libmemcached-0.32/libmemcached/memcached.h +305 -0
  65. data/ext/libmemcached-0.32/libmemcached/memcached.hpp +799 -0
  66. data/ext/libmemcached-0.32/libmemcached/memcached/README.txt +7 -0
  67. data/ext/libmemcached-0.32/libmemcached/memcached/protocol_binary.h +385 -0
  68. data/ext/libmemcached-0.32/libmemcached/memcached_allocators.c +72 -0
  69. data/ext/libmemcached-0.32/libmemcached/memcached_analyze.c +100 -0
  70. data/ext/libmemcached-0.32/libmemcached/memcached_auto.c +207 -0
  71. data/ext/libmemcached-0.32/libmemcached/memcached_behavior.c +290 -0
  72. data/ext/libmemcached-0.32/libmemcached/memcached_callback.c +175 -0
  73. data/ext/libmemcached-0.32/libmemcached/memcached_configure.h.in +23 -0
  74. data/ext/libmemcached-0.32/libmemcached/memcached_connect.c +371 -0
  75. data/ext/libmemcached-0.32/libmemcached/memcached_constants.h +146 -0
  76. data/ext/libmemcached-0.32/libmemcached/memcached_delete.c +0 -0
  77. data/ext/libmemcached-0.32/libmemcached/memcached_do.c +72 -0
  78. data/ext/libmemcached-0.32/libmemcached/memcached_dump.c +79 -0
  79. data/ext/libmemcached-0.32/libmemcached/memcached_exist.c +114 -0
  80. data/ext/libmemcached-0.32/libmemcached/memcached_exist.h +20 -0
  81. data/ext/libmemcached-0.32/libmemcached/memcached_fetch.c +102 -0
  82. data/ext/libmemcached-0.32/libmemcached/memcached_flush.c +89 -0
  83. data/ext/libmemcached-0.32/libmemcached/memcached_flush_buffers.c +23 -0
  84. data/ext/libmemcached-0.32/libmemcached/memcached_get.c +494 -0
  85. data/ext/libmemcached-0.32/libmemcached/memcached_get.h +87 -0
  86. data/ext/libmemcached-0.32/libmemcached/memcached_hash.c +252 -0
  87. data/ext/libmemcached-0.32/libmemcached/memcached_hosts.c +510 -0
  88. data/ext/libmemcached-0.32/libmemcached/memcached_internal.h +31 -0
  89. data/ext/libmemcached-0.32/libmemcached/memcached_io.c +594 -0
  90. data/ext/libmemcached-0.32/libmemcached/memcached_io.h +72 -0
  91. data/ext/libmemcached-0.32/libmemcached/memcached_key.c +28 -0
  92. data/ext/libmemcached-0.32/libmemcached/memcached_parse.c +74 -0
  93. data/ext/libmemcached-0.32/libmemcached/memcached_pool.h +38 -0
  94. data/ext/libmemcached-0.32/libmemcached/memcached_purge.c +76 -0
  95. data/ext/libmemcached-0.32/libmemcached/memcached_quit.c +75 -0
  96. data/ext/libmemcached-0.32/libmemcached/memcached_response.c +529 -0
  97. data/ext/libmemcached-0.32/libmemcached/memcached_result.c +57 -0
  98. data/ext/libmemcached-0.32/libmemcached/memcached_result.h +59 -0
  99. data/ext/libmemcached-0.32/libmemcached/memcached_sasl.c +225 -0
  100. data/ext/libmemcached-0.32/libmemcached/memcached_sasl.h +44 -0
  101. data/ext/libmemcached-0.32/libmemcached/memcached_server.c +159 -0
  102. data/ext/libmemcached-0.32/libmemcached/memcached_server.h +93 -0
  103. data/ext/libmemcached-0.32/libmemcached/memcached_stats.c +437 -0
  104. data/ext/libmemcached-0.32/libmemcached/memcached_storage.c +514 -0
  105. data/ext/libmemcached-0.32/libmemcached/memcached_storage.h +107 -0
  106. data/ext/libmemcached-0.32/libmemcached/memcached_strerror.c +92 -0
  107. data/ext/libmemcached-0.32/libmemcached/memcached_string.c +138 -0
  108. data/ext/libmemcached-0.32/libmemcached/memcached_string.h +53 -0
  109. data/ext/libmemcached-0.32/libmemcached/memcached_touch.c +60 -0
  110. data/ext/libmemcached-0.32/libmemcached/memcached_touch.h +31 -0
  111. data/ext/libmemcached-0.32/libmemcached/memcached_types.h +44 -0
  112. data/ext/libmemcached-0.32/libmemcached/memcached_util.h +15 -0
  113. data/ext/libmemcached-0.32/libmemcached/memcached_verbosity.c +36 -0
  114. data/ext/libmemcached-0.32/libmemcached/memcached_version.c +112 -0
  115. data/ext/libmemcached-0.32/libmemcached/memcached_watchpoint.h +38 -0
  116. data/ext/libmemcached-0.32/libmemcached/murmur_hash.c +76 -0
  117. data/ext/libmemcached-0.32/libmemcached/visibility.h +51 -0
  118. data/ext/libmemcached-0.32/libmemcachedutil/Makefile.am +11 -0
  119. data/ext/libmemcached-0.32/libmemcachedutil/Makefile.in +604 -0
  120. data/ext/libmemcached-0.32/libmemcachedutil/libmemcachedutil.ver +1 -0
  121. data/ext/libmemcached-0.32/libmemcachedutil/memcached_pool.c +170 -0
  122. data/ext/libmemcached-0.32/m4/ac_cxx_compile_stdcxx_0x.m4 +103 -0
  123. data/ext/libmemcached-0.32/m4/ac_cxx_header_stdcxx_98.m4 +67 -0
  124. data/ext/libmemcached-0.32/m4/acx_pthread.m4 +276 -0
  125. data/ext/libmemcached-0.32/m4/byteorder.m4 +40 -0
  126. data/ext/libmemcached-0.32/m4/deprecated.m4 +17 -0
  127. data/ext/libmemcached-0.32/m4/enable_utillib.m4 +16 -0
  128. data/ext/libmemcached-0.32/m4/extensions.m4 +94 -0
  129. data/ext/libmemcached-0.32/m4/hsieh.m4 +18 -0
  130. data/ext/libmemcached-0.32/m4/lib-prefix.m4 +221 -0
  131. data/ext/libmemcached-0.32/m4/libtool.m4 +7831 -0
  132. data/ext/libmemcached-0.32/m4/ltoptions.m4 +369 -0
  133. data/ext/libmemcached-0.32/m4/ltsugar.m4 +123 -0
  134. data/ext/libmemcached-0.32/m4/ltversion.m4 +23 -0
  135. data/ext/libmemcached-0.32/m4/lt~obsolete.m4 +98 -0
  136. data/ext/libmemcached-0.32/m4/memcached.m4 +30 -0
  137. data/ext/libmemcached-0.32/m4/pandora_64bit.m4 +55 -0
  138. data/ext/libmemcached-0.32/m4/pandora_canonical.m4 +151 -0
  139. data/ext/libmemcached-0.32/m4/pandora_check_compiler_version.m4 +37 -0
  140. data/ext/libmemcached-0.32/m4/pandora_check_cxx_standard.m4 +16 -0
  141. data/ext/libmemcached-0.32/m4/pandora_enable_dtrace.m4 +41 -0
  142. data/ext/libmemcached-0.32/m4/pandora_ensure_gcc_version.m4 +36 -0
  143. data/ext/libmemcached-0.32/m4/pandora_have_better_malloc.m4 +54 -0
  144. data/ext/libmemcached-0.32/m4/pandora_have_sasl.m4 +133 -0
  145. data/ext/libmemcached-0.32/m4/pandora_header_assert.m4 +23 -0
  146. data/ext/libmemcached-0.32/m4/pandora_libtool.m4 +15 -0
  147. data/ext/libmemcached-0.32/m4/pandora_optimize.m4 +79 -0
  148. data/ext/libmemcached-0.32/m4/pandora_shared_ptr.m4 +56 -0
  149. data/ext/libmemcached-0.32/m4/pandora_vc_build.m4 +32 -0
  150. data/ext/libmemcached-0.32/m4/pandora_warnings.m4 +262 -0
  151. data/ext/libmemcached-0.32/m4/pod2man.m4 +7 -0
  152. data/ext/libmemcached-0.32/m4/protocol_binary.m4 +23 -0
  153. data/ext/libmemcached-0.32/m4/setsockopt.m4 +57 -0
  154. data/ext/libmemcached-0.32/m4/visibility.m4 +52 -0
  155. data/ext/libmemcached-0.32/support/Makefile.am +4 -0
  156. data/ext/libmemcached-0.32/support/Makefile.in +487 -0
  157. data/ext/libmemcached-0.32/support/libmemcached-fc.spec.in +105 -0
  158. data/ext/libmemcached-0.32/support/libmemcached.pc.in +10 -0
  159. data/ext/libmemcached-0.32/support/libmemcached.spec +105 -0
  160. data/ext/libmemcached-0.32/support/libmemcached.spec.in +105 -0
  161. data/ext/libmemcached-0.32/support/set_benchmark.sh +5 -0
  162. data/ext/libmemcached-0.32/tests/Makefile.am +113 -0
  163. data/ext/libmemcached-0.32/tests/Makefile.in +762 -0
  164. data/ext/libmemcached-0.32/tests/atomsmasher.c +245 -0
  165. data/ext/libmemcached-0.32/tests/function.c +4904 -0
  166. data/ext/libmemcached-0.32/tests/ketama_test_cases.h +108 -0
  167. data/ext/libmemcached-0.32/tests/output.cmp +7 -0
  168. data/ext/libmemcached-0.32/tests/output.res +7 -0
  169. data/ext/libmemcached-0.32/tests/output2.res +46 -0
  170. data/ext/libmemcached-0.32/tests/plus.cpp +293 -0
  171. data/ext/libmemcached-0.32/tests/r/memcat.res +19 -0
  172. data/ext/libmemcached-0.32/tests/r/memcp.res +27 -0
  173. data/ext/libmemcached-0.32/tests/r/memrm.res +19 -0
  174. data/ext/libmemcached-0.32/tests/r/memslap.res +33 -0
  175. data/ext/libmemcached-0.32/tests/r/memstat.res +33 -0
  176. data/ext/libmemcached-0.32/tests/server.c +118 -0
  177. data/ext/libmemcached-0.32/tests/server.h +25 -0
  178. data/ext/libmemcached-0.32/tests/start.c +16 -0
  179. data/ext/libmemcached-0.32/tests/t/memcat.test +4 -0
  180. data/ext/libmemcached-0.32/tests/t/memcp.test +3 -0
  181. data/ext/libmemcached-0.32/tests/t/memrm.test +3 -0
  182. data/ext/libmemcached-0.32/tests/t/memslap.test +5 -0
  183. data/ext/libmemcached-0.32/tests/t/memstat.test +3 -0
  184. data/ext/libmemcached-0.32/tests/test.c +137 -0
  185. data/ext/libmemcached-0.32/tests/test.h +46 -0
  186. data/ext/libmemcached-0.32/tests/udp.c +76 -0
  187. data/ext/rlibmemcached.i +258 -0
  188. data/ext/rlibmemcached_wrap.c +13917 -0
  189. data/lib/memcached.rb +33 -0
  190. data/lib/memcached/auth.rb +16 -0
  191. data/lib/memcached/behaviors.rb +78 -0
  192. data/lib/memcached/exceptions.rb +84 -0
  193. data/lib/memcached/experimental.rb +48 -0
  194. data/lib/memcached/marshal_codec.rb +10 -0
  195. data/lib/memcached/memcached.rb +732 -0
  196. data/lib/memcached/rails.rb +250 -0
  197. data/test/profile/benchmark.rb +280 -0
  198. data/test/profile/c_profiler.rb +14 -0
  199. data/test/profile/exercise.rb +185 -0
  200. data/test/profile/rb_profiler.rb +21 -0
  201. data/test/profile/valgrind.rb +10 -0
  202. data/test/setup.rb +30 -0
  203. data/test/teardown.rb +0 -0
  204. data/test/test_helper.rb +18 -0
  205. data/test/unit/binding_test.rb +8 -0
  206. data/test/unit/memcached_experimental_test.rb +272 -0
  207. data/test/unit/memcached_test.rb +1487 -0
  208. data/test/unit/rails_test.rb +330 -0
  209. metadata +347 -0
@@ -0,0 +1,31 @@
1
+ /*
2
+ * Summary: Internal functions used by the library. Not for public use!
3
+ * Copy: See Copyright for the status of this software.
4
+ *
5
+ * Author: Trond Norbye
6
+ */
7
+
8
+ #ifndef LIBMEMCACHED_MEMCACHED_INTERNAL_H
9
+ #define LIBMEMCACHED_MEMCACHED_INTERNAL_H
10
+
11
+ #if defined(BUILDING_LIBMEMCACHED)
12
+
13
+ #ifdef __cplusplus
14
+ extern "C" {
15
+ #endif
16
+
17
+ LIBMEMCACHED_LOCAL
18
+ void libmemcached_free(memcached_st *ptr, void *mem);
19
+ LIBMEMCACHED_LOCAL
20
+ void *libmemcached_malloc(memcached_st *ptr, const size_t size);
21
+ LIBMEMCACHED_LOCAL
22
+ void *libmemcached_realloc(memcached_st *ptr, void *mem, const size_t size);
23
+ LIBMEMCACHED_LOCAL
24
+ void *libmemcached_calloc(memcached_st *ptr, size_t nelem, size_t size);
25
+
26
+ #ifdef __cplusplus
27
+ }
28
+ #endif
29
+
30
+ #endif /* BUILDING_LIBMEMCACHED */
31
+ #endif /* LIBMEMCACHED_MEMCACHED_INTERNAL_H */
@@ -0,0 +1,594 @@
1
+ /*
2
+ Basic socket buffered IO
3
+ */
4
+
5
+ #include "common.h"
6
+ #include "memcached_io.h"
7
+ #include <sys/select.h>
8
+ #include <poll.h>
9
+
10
+ typedef enum {
11
+ MEM_READ,
12
+ MEM_WRITE
13
+ } memc_read_or_write;
14
+
15
+ static ssize_t io_flush(memcached_server_st *ptr, memcached_return *error);
16
+ static void increment_udp_message_id(memcached_server_st *ptr);
17
+
18
+ static memcached_return io_wait(memcached_server_st *ptr,
19
+ memc_read_or_write read_or_write)
20
+ {
21
+ struct pollfd fds[1];
22
+ short flags= 0;
23
+ int error;
24
+
25
+ if (read_or_write == MEM_WRITE) /* write */
26
+ flags= POLLOUT;
27
+ else
28
+ flags= POLLIN;
29
+
30
+ memset(&fds, 0, sizeof(struct pollfd));
31
+ fds[0].fd= ptr->fd;
32
+ fds[0].events= flags;
33
+
34
+ /*
35
+ ** We are going to block on write, but at least on Solaris we might block
36
+ ** on write if we haven't read anything from our input buffer..
37
+ ** Try to purge the input buffer if we don't do any flow control in the
38
+ ** application layer (just sending a lot of data etc)
39
+ ** The test is moved down in the purge function to avoid duplication of
40
+ ** the test.
41
+ */
42
+ if (read_or_write == MEM_WRITE)
43
+ {
44
+ memcached_return rc=memcached_purge(ptr);
45
+ if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STORED)
46
+ return MEMCACHED_FAILURE;
47
+ }
48
+
49
+ error= poll(fds, 1, ptr->root->poll_timeout);
50
+
51
+ if (error == 1)
52
+ return MEMCACHED_SUCCESS;
53
+ else if (error == 0)
54
+ {
55
+ return MEMCACHED_TIMEOUT;
56
+ }
57
+
58
+ /* Imposssible for anything other then -1 */
59
+ WATCHPOINT_ASSERT(error == -1);
60
+ memcached_quit_server(ptr, 1);
61
+
62
+ return MEMCACHED_FAILURE;
63
+
64
+ }
65
+
66
+ #ifdef UNUSED
67
+ void memcached_io_preread(memcached_st *ptr)
68
+ {
69
+ unsigned int x;
70
+
71
+ return;
72
+
73
+ for (x= 0; x < ptr->number_of_hosts; x++)
74
+ {
75
+ if (memcached_server_response_count(ptr, x) &&
76
+ ptr->hosts[x].read_data_length < MEMCACHED_MAX_BUFFER )
77
+ {
78
+ size_t data_read;
79
+
80
+ data_read= read(ptr->hosts[x].fd,
81
+ ptr->hosts[x].read_ptr + ptr->hosts[x].read_data_length,
82
+ MEMCACHED_MAX_BUFFER - ptr->hosts[x].read_data_length);
83
+ if (data_read == -1)
84
+ continue;
85
+
86
+ ptr->hosts[x].read_buffer_length+= data_read;
87
+ ptr->hosts[x].read_data_length+= data_read;
88
+ }
89
+ }
90
+ }
91
+ #endif
92
+
93
+ memcached_return memcached_io_read(memcached_server_st *ptr,
94
+ void *buffer, size_t length, ssize_t *nread)
95
+ {
96
+ char *buffer_ptr;
97
+ memcached_return rc;
98
+
99
+ buffer_ptr= buffer;
100
+
101
+ while (length)
102
+ {
103
+ if (!ptr->read_buffer_length)
104
+ {
105
+ ssize_t data_read;
106
+
107
+ while (1)
108
+ {
109
+ data_read= read(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER);
110
+ if (data_read > 0)
111
+ break;
112
+ else if (data_read == -1)
113
+ {
114
+ ptr->cached_errno= errno;
115
+ rc= MEMCACHED_UNKNOWN_READ_FAILURE;
116
+ switch (errno)
117
+ {
118
+ case EAGAIN:
119
+ case EINTR:
120
+ if ((rc= io_wait(ptr, MEM_READ)) == MEMCACHED_SUCCESS)
121
+ continue;
122
+ /* fall through */
123
+
124
+ default:
125
+ {
126
+ memcached_quit_server(ptr, 1);
127
+ *nread= -1;
128
+ return rc;
129
+ }
130
+ }
131
+ }
132
+ else
133
+ {
134
+ /*
135
+ EOF. Any data received so far is incomplete
136
+ so discard it. This always reads by byte in case of TCP
137
+ and protocol enforcement happens at memcached_response()
138
+ looking for '\n'. We do not care for UDB which requests 8 bytes
139
+ at once. Generally, this means that connection went away. Since
140
+ for blocking I/O we do not return 0 and for non-blocking case
141
+ it will return EGAIN if data is not immediatly available.
142
+ */
143
+ memcached_quit_server(ptr, 1);
144
+ *nread= -1;
145
+ return MEMCACHED_UNKNOWN_READ_FAILURE;
146
+ }
147
+ }
148
+
149
+ ptr->io_bytes_sent = 0;
150
+ ptr->read_data_length= (size_t) data_read;
151
+ ptr->read_buffer_length= (size_t) data_read;
152
+ ptr->read_ptr= ptr->read_buffer;
153
+ }
154
+
155
+ if (length > 1)
156
+ {
157
+ size_t difference;
158
+
159
+ difference= (length > ptr->read_buffer_length) ? ptr->read_buffer_length : length;
160
+
161
+ memcpy(buffer_ptr, ptr->read_ptr, difference);
162
+ length -= difference;
163
+ ptr->read_ptr+= difference;
164
+ ptr->read_buffer_length-= difference;
165
+ buffer_ptr+= difference;
166
+ }
167
+ else
168
+ {
169
+ *buffer_ptr= *ptr->read_ptr;
170
+ ptr->read_ptr++;
171
+ ptr->read_buffer_length--;
172
+ buffer_ptr++;
173
+ break;
174
+ }
175
+ }
176
+
177
+ ptr->server_failure_counter= 0;
178
+ *nread = (ssize_t)(buffer_ptr - (char*)buffer);
179
+ return MEMCACHED_SUCCESS;
180
+ }
181
+
182
+ static ssize_t _io_write(memcached_server_st *ptr,
183
+ const void *buffer, size_t length, char with_flush)
184
+ {
185
+ size_t original_length;
186
+ const char* buffer_ptr;
187
+
188
+ WATCHPOINT_ASSERT(ptr->fd != -1);
189
+
190
+ original_length= length;
191
+ buffer_ptr= buffer;
192
+
193
+ while (length)
194
+ {
195
+ char *write_ptr;
196
+ size_t should_write;
197
+ size_t buffer_end;
198
+
199
+ if (ptr->type == MEMCACHED_CONNECTION_UDP)
200
+ {
201
+ /* UDP does not support partial writes */
202
+ buffer_end= MAX_UDP_DATAGRAM_LENGTH;
203
+ should_write= length;
204
+ if (ptr->write_buffer_offset + should_write > buffer_end)
205
+ return -1;
206
+ }
207
+ else
208
+ {
209
+ buffer_end= MEMCACHED_MAX_BUFFER;
210
+ should_write= buffer_end - ptr->write_buffer_offset;
211
+ should_write= (should_write < length) ? should_write : length;
212
+ }
213
+
214
+ write_ptr= ptr->write_buffer + ptr->write_buffer_offset;
215
+ memcpy(write_ptr, buffer_ptr, should_write);
216
+ ptr->write_buffer_offset+= should_write;
217
+ buffer_ptr+= should_write;
218
+ length-= should_write;
219
+
220
+ if (ptr->write_buffer_offset == buffer_end && ptr->type != MEMCACHED_CONNECTION_UDP)
221
+ {
222
+ memcached_return rc;
223
+ ssize_t sent_length;
224
+
225
+ WATCHPOINT_ASSERT(ptr->fd != -1);
226
+ sent_length= io_flush(ptr, &rc);
227
+ if (sent_length == -1)
228
+ return -1;
229
+
230
+ /* If io_flush calls memcached_purge, sent_length may be 0 */
231
+ unlikely (sent_length != 0)
232
+ {
233
+ WATCHPOINT_ASSERT(sent_length == (ssize_t)buffer_end);
234
+ }
235
+ }
236
+ }
237
+
238
+ if (with_flush)
239
+ {
240
+ memcached_return rc;
241
+ WATCHPOINT_ASSERT(ptr->fd != -1);
242
+ if (io_flush(ptr, &rc) == -1)
243
+ return -1;
244
+ }
245
+
246
+ return (ssize_t) original_length;
247
+ }
248
+
249
+ ssize_t memcached_io_write(memcached_server_st *ptr,
250
+ const void *buffer, size_t length, char with_flush)
251
+ {
252
+ return _io_write(ptr, buffer, length, with_flush);
253
+ }
254
+
255
+ ssize_t memcached_io_writev(memcached_server_st *ptr,
256
+ const struct libmemcached_io_vector_st *vector,
257
+ size_t number_of, char with_flush)
258
+ {
259
+ ssize_t total = 0;
260
+ char f = (char)false;
261
+ size_t x;
262
+
263
+ for (x = 0; x < number_of; x++, vector++)
264
+ {
265
+ ssize_t returnable;
266
+ if ((returnable= _io_write(ptr, vector->buffer, vector->length, f)) == -1)
267
+ return -1;
268
+
269
+ total+= returnable;
270
+ }
271
+
272
+ if (with_flush && _io_write(ptr, NULL, 0, (char)true) == -1)
273
+ return -1;
274
+
275
+ return total;
276
+ }
277
+
278
+ memcached_return memcached_io_close(memcached_server_st *ptr)
279
+ {
280
+ int r;
281
+
282
+ if (ptr->fd == -1)
283
+ return MEMCACHED_SUCCESS;
284
+
285
+ /* in case of death shutdown to avoid blocking at close() */
286
+ if (1)
287
+ {
288
+ r= shutdown(ptr->fd, SHUT_RDWR);
289
+
290
+ #ifdef DEBUG
291
+ if (r && errno != ENOTCONN)
292
+ {
293
+ WATCHPOINT_NUMBER(ptr->fd);
294
+ WATCHPOINT_ERRNO(errno);
295
+ WATCHPOINT_ASSERT(errno);
296
+ }
297
+ #endif
298
+ }
299
+
300
+ r= close(ptr->fd);
301
+ #ifdef DEBUG
302
+ if (r != 0)
303
+ WATCHPOINT_ERRNO(errno);
304
+ #endif
305
+
306
+ return MEMCACHED_SUCCESS;
307
+ }
308
+
309
+ memcached_server_st *memcached_io_get_readable_server(memcached_st *memc)
310
+ {
311
+ #define MAX_SERVERS_TO_POLL 100
312
+ struct pollfd fds[MAX_SERVERS_TO_POLL];
313
+ unsigned int host_index= 0,
314
+ x,
315
+ y;
316
+ int err;
317
+
318
+ for (x= 0;
319
+ x< memc->number_of_hosts && host_index < MAX_SERVERS_TO_POLL;
320
+ ++x)
321
+ {
322
+ if (memc->hosts[x].read_buffer_length > 0) /* I have data in the buffer */
323
+ return &memc->hosts[x];
324
+
325
+ if (memcached_server_response_count(&memc->hosts[x]) > 0)
326
+ {
327
+ fds[host_index].events = POLLIN;
328
+ fds[host_index].revents = 0;
329
+ fds[host_index].fd = memc->hosts[x].fd;
330
+ ++host_index;
331
+ }
332
+ }
333
+
334
+ if (host_index < 2)
335
+ {
336
+ /* We have 0 or 1 server with pending events.. */
337
+ for (x= 0; x< memc->number_of_hosts; ++x)
338
+ if (memcached_server_response_count(&memc->hosts[x]) > 0)
339
+ return &memc->hosts[x];
340
+
341
+ return NULL;
342
+ }
343
+
344
+ err= poll(fds, host_index, memc->poll_timeout);
345
+ switch (err) {
346
+ case -1:
347
+ memc->cached_errno = errno;
348
+ /* FALLTHROUGH */
349
+ case 0:
350
+ break;
351
+ default:
352
+ for (x= 0; x < host_index; ++x)
353
+ if (fds[x].revents & POLLIN)
354
+ for (y= 0; y < memc->number_of_hosts; ++y)
355
+ if (memc->hosts[y].fd == fds[x].fd)
356
+ return &memc->hosts[y];
357
+ }
358
+
359
+ return NULL;
360
+ }
361
+
362
+ static ssize_t io_flush(memcached_server_st *ptr,
363
+ memcached_return *error)
364
+ {
365
+ ssize_t sent_length;
366
+ size_t return_length;
367
+ char *local_write_ptr;
368
+ size_t write_length;
369
+ int timeout_cnt;
370
+
371
+ /*
372
+ ** We might want to purge the input buffer if we haven't consumed
373
+ ** any output yet... The test for the limits is the purge is inline
374
+ ** in the purge function to avoid duplicating the logic..
375
+ */
376
+ {
377
+ memcached_return rc;
378
+ WATCHPOINT_ASSERT(ptr->fd != -1);
379
+ rc= memcached_purge(ptr);
380
+
381
+ if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STORED)
382
+ return -1;
383
+ }
384
+ local_write_ptr= ptr->write_buffer;
385
+ write_length= ptr->write_buffer_offset;
386
+
387
+ *error= MEMCACHED_SUCCESS;
388
+
389
+ WATCHPOINT_ASSERT(ptr->fd != -1);
390
+
391
+ /* UDP Sanity check, make sure that we are not sending somthing too big */
392
+ if (ptr->type == MEMCACHED_CONNECTION_UDP && write_length > MAX_UDP_DATAGRAM_LENGTH)
393
+ return -1;
394
+
395
+ if (ptr->write_buffer_offset == 0 || (ptr->type == MEMCACHED_CONNECTION_UDP
396
+ && ptr->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH))
397
+ return 0;
398
+
399
+ /* Looking for memory overflows */
400
+ #if defined(DEBUG)
401
+ if (write_length == MEMCACHED_MAX_BUFFER)
402
+ WATCHPOINT_ASSERT(ptr->write_buffer == local_write_ptr);
403
+ WATCHPOINT_ASSERT((ptr->write_buffer + MEMCACHED_MAX_BUFFER) >= (local_write_ptr + write_length));
404
+ #endif
405
+
406
+ return_length= 0;
407
+ timeout_cnt = 0;
408
+ while (write_length)
409
+ {
410
+ WATCHPOINT_ASSERT(ptr->fd != -1);
411
+ WATCHPOINT_ASSERT(write_length > 0);
412
+ sent_length= 0;
413
+ if (ptr->type == MEMCACHED_CONNECTION_UDP)
414
+ increment_udp_message_id(ptr);
415
+ sent_length= write(ptr->fd, local_write_ptr, write_length);
416
+
417
+ if (sent_length == -1)
418
+ {
419
+ ptr->cached_errno= errno;
420
+ switch (errno)
421
+ {
422
+ case ENOBUFS:
423
+ continue;
424
+ case EAGAIN:
425
+ {
426
+ memcached_return rc;
427
+ rc= io_wait(ptr, MEM_WRITE);
428
+
429
+ if (rc == MEMCACHED_SUCCESS)
430
+ continue;
431
+ else if (rc == MEMCACHED_TIMEOUT) {
432
+ if((ptr->root->poll_max_retries) && (timeout_cnt++ <= ptr->root->poll_max_retries))
433
+ continue;
434
+ }
435
+
436
+ memcached_quit_server(ptr, 1);
437
+ *error= MEMCACHED_TIMEOUT;
438
+ return -1;
439
+ }
440
+ default:
441
+ memcached_quit_server(ptr, 1);
442
+ *error= MEMCACHED_ERRNO;
443
+ return -1;
444
+ }
445
+ }
446
+
447
+ if (ptr->type == MEMCACHED_CONNECTION_UDP &&
448
+ (size_t)sent_length != write_length)
449
+ {
450
+ memcached_quit_server(ptr, 1);
451
+ return -1;
452
+ }
453
+
454
+ ptr->io_bytes_sent += (uint32_t) sent_length;
455
+
456
+ local_write_ptr+= sent_length;
457
+ write_length-= (uint32_t) sent_length;
458
+ return_length+= (uint32_t) sent_length;
459
+ }
460
+
461
+ WATCHPOINT_ASSERT(write_length == 0);
462
+ /*
463
+ * Need to study this assert() WATCHPOINT_ASSERT(return_length ==
464
+ * ptr->write_buffer_offset);
465
+ */
466
+
467
+ /*
468
+ * if we are a udp server, the begining of the buffer is reserverd for
469
+ * the upd frame header
470
+ */
471
+ if (ptr->type == MEMCACHED_CONNECTION_UDP)
472
+ ptr->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
473
+ else
474
+ ptr->write_buffer_offset= 0;
475
+
476
+ return (ssize_t) return_length;
477
+ }
478
+
479
+ /*
480
+ Eventually we will just kill off the server with the problem.
481
+ */
482
+ void memcached_io_reset(memcached_server_st *ptr)
483
+ {
484
+ memcached_quit_server(ptr, 1);
485
+ }
486
+
487
+ /**
488
+ * Read a given number of bytes from the server and place it into a specific
489
+ * buffer. Reset the IO channel on this server if an error occurs.
490
+ */
491
+ memcached_return memcached_safe_read(memcached_server_st *ptr,
492
+ void *dta,
493
+ size_t size)
494
+ {
495
+ size_t offset= 0;
496
+ char *data= dta;
497
+
498
+ while (offset < size)
499
+ {
500
+ ssize_t nread;
501
+ memcached_return rc= memcached_io_read(ptr, data + offset, size - offset,
502
+ &nread);
503
+ if (rc != MEMCACHED_SUCCESS)
504
+ return rc;
505
+
506
+ offset+= (size_t) nread;
507
+ }
508
+
509
+ return MEMCACHED_SUCCESS;
510
+ }
511
+
512
+ memcached_return memcached_io_readline(memcached_server_st *ptr,
513
+ char *buffer_ptr,
514
+ size_t size)
515
+ {
516
+ bool line_complete= false;
517
+ size_t total_nr= 0;
518
+
519
+ while (!line_complete)
520
+ {
521
+ if (ptr->read_buffer_length == 0)
522
+ {
523
+ /*
524
+ * We don't have any data in the buffer, so let's fill the read
525
+ * buffer. Call the standard read function to avoid duplicating
526
+ * the logic.
527
+ */
528
+ ssize_t nread;
529
+ memcached_return rc= memcached_io_read(ptr, buffer_ptr, 1, &nread);
530
+ if (rc != MEMCACHED_SUCCESS)
531
+ return rc;
532
+
533
+ if (*buffer_ptr == '\n')
534
+ line_complete= true;
535
+
536
+ ++buffer_ptr;
537
+ ++total_nr;
538
+ }
539
+
540
+ /* Now let's look in the buffer and copy as we go! */
541
+ while (ptr->read_buffer_length && total_nr < size && !line_complete)
542
+ {
543
+ *buffer_ptr = *ptr->read_ptr;
544
+ if (*buffer_ptr == '\n')
545
+ line_complete = true;
546
+ --ptr->read_buffer_length;
547
+ ++ptr->read_ptr;
548
+ ++total_nr;
549
+ ++buffer_ptr;
550
+ }
551
+
552
+ if (total_nr == size)
553
+ return MEMCACHED_PROTOCOL_ERROR;
554
+ }
555
+
556
+ return MEMCACHED_SUCCESS;
557
+ }
558
+
559
+ /*
560
+ * The udp request id consists of two seperate sections
561
+ * 1) The thread id
562
+ * 2) The message number
563
+ * The thread id should only be set when the memcached_st struct is created
564
+ * and should not be changed.
565
+ *
566
+ * The message num is incremented for each new message we send, this function
567
+ * extracts the message number from message_id, increments it and then
568
+ * writes the new value back into the header
569
+ */
570
+ static void increment_udp_message_id(memcached_server_st *ptr)
571
+ {
572
+ struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
573
+ uint16_t cur_req= get_udp_datagram_request_id(header);
574
+ int msg_num= get_msg_num_from_request_id(cur_req);
575
+ int thread_id= get_thread_id_from_request_id(cur_req);
576
+
577
+ if (((++msg_num) & UDP_REQUEST_ID_THREAD_MASK) != 0)
578
+ msg_num= 0;
579
+
580
+ header->request_id= htons((uint16_t) (thread_id | msg_num));
581
+ }
582
+
583
+ memcached_return memcached_io_init_udp_header(memcached_server_st *ptr, uint16_t thread_id)
584
+ {
585
+ if (thread_id > UDP_REQUEST_ID_MAX_THREAD_ID)
586
+ return MEMCACHED_FAILURE;
587
+
588
+ struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
589
+ header->request_id= htons((uint16_t) (generate_udp_request_thread_id(thread_id)));
590
+ header->num_datagrams= htons(1);
591
+ header->sequence_number= htons(0);
592
+
593
+ return MEMCACHED_SUCCESS;
594
+ }