Merge lp://staging/~trond-norbye/libmemcached/bugparade into lp://staging/~tangent-org/libmemcached/trunk
- bugparade
- Merge into trunk
Proposed by
Trond Norbye
Status: | Merged | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | not available | ||||||||||||||||
Proposed branch: | lp://staging/~trond-norbye/libmemcached/bugparade | ||||||||||||||||
Merge into: | lp://staging/~tangent-org/libmemcached/trunk | ||||||||||||||||
Diff against target: |
1146 lines 7 files modified
clients/memcapable.c (+714/-41) libmemcached/memcached_delete.c (+1/-1) libmemcached/memcached_get.c (+5/-2) libmemcached/memcached_purge.c (+1/-1) libmemcached/memcached_response.c (+7/-1) libmemcached/memcached_stats.c (+2/-2) tests/function.c (+154/-0) |
||||||||||||||||
To merge this branch: | bzr merge lp://staging/~trond-norbye/libmemcached/bugparade | ||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brian Aker | Needs Fixing | ||
Review via email: mp+12895@code.staging.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Trond Norbye (trond-norbye) wrote : | # |
- 597. By Trond Norbye <tn202803@tor01>
-
Bug #434843: Large multigets with binary protocol may hang client
- 598. By Trond Norbye
-
Bug 421108: memstat reports same value for bytes, bytes_read and bytes_written
Revision history for this message
Brian Aker (brianaker) wrote : | # |
Build failure on gaz. Your const int does not compare directly to counter which is unsigned.
review:
Needs Fixing
- 599. By Trond Norbye
-
Fix compilation warnings reported by gcc
- 600. By Trond Norbye
-
Initial support for the ASCII protocol in memcapable
- 601. By Trond Norbye
-
Flush does not reset the bytes stat, so we have no idea of the value
- 602. By Trond Norbye <tn202803@tor01>
-
Merge Eric
- 603. By Trond Norbye <tn202803@tor01>
-
Bug #442914: 'delete noreply' may hang the client
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'clients/memcapable.c' |
2 | --- clients/memcapable.c 2009-09-28 22:25:10 +0000 |
3 | +++ clients/memcapable.c 2009-10-08 14:12:13 +0000 |
4 | @@ -19,6 +19,7 @@ |
5 | #include <stdbool.h> |
6 | #include <unistd.h> |
7 | #include <poll.h> |
8 | +#include <ctype.h> |
9 | |
10 | #include <libmemcached/memcached/protocol_binary.h> |
11 | #include <libmemcached/byteorder.h> |
12 | @@ -168,7 +169,7 @@ |
13 | ret= read(fd, buf, len); |
14 | |
15 | if (ret == -1 && errno == EWOULDBLOCK) { |
16 | - struct pollfd fds = { |
17 | + struct pollfd fds= { |
18 | .events= direction, |
19 | .fd= fd |
20 | }; |
21 | @@ -183,7 +184,7 @@ |
22 | } |
23 | else if (err == 0) |
24 | { |
25 | - errno = ETIMEDOUT; |
26 | + errno= ETIMEDOUT; |
27 | } |
28 | else |
29 | { |
30 | @@ -206,7 +207,7 @@ |
31 | if (!val) |
32 | { |
33 | if (verbose) |
34 | - fprintf(stderr, "%s:%u: %s\n", file, line, expression); |
35 | + fprintf(stderr, "\n%s:%u: %s", file, line, expression); |
36 | |
37 | if (do_core) |
38 | abort(); |
39 | @@ -639,7 +640,7 @@ |
40 | cmd.set.message.header.request.opcode= PROTOCOL_BINARY_CMD_SET; |
41 | execute(resend_packet(&cmd)); |
42 | execute(recv_packet(&rsp)); |
43 | - verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_SET, |
44 | + verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_SET, |
45 | PROTOCOL_BINARY_RESPONSE_SUCCESS)); |
46 | cmd.set.message.header.request.opcode= PROTOCOL_BINARY_CMD_SETQ; |
47 | } |
48 | @@ -720,7 +721,7 @@ |
49 | return test_binary_add_impl("test_binary_addq", PROTOCOL_BINARY_CMD_ADDQ); |
50 | } |
51 | |
52 | -static enum test_return set_item(const char *key, const char *value) |
53 | +static enum test_return binary_set_item(const char *key, const char *value) |
54 | { |
55 | command cmd; |
56 | response rsp; |
57 | @@ -761,7 +762,7 @@ |
58 | verify(validate_response_header(&rsp, cc, expected_result)); |
59 | |
60 | if (ii == 0) |
61 | - execute(set_item(key, key)); |
62 | + execute(binary_set_item(key, key)); |
63 | } |
64 | else |
65 | execute(test_binary_noop()); |
66 | @@ -810,7 +811,7 @@ |
67 | execute(send_packet(&cmd)); |
68 | execute(recv_packet(&rsp)); |
69 | verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT)); |
70 | - execute(set_item(key, key)); |
71 | + execute(binary_set_item(key, key)); |
72 | |
73 | /* The item should be present now, resend*/ |
74 | execute(resend_packet(&cmd)); |
75 | @@ -851,7 +852,7 @@ |
76 | else |
77 | execute(test_binary_noop()); |
78 | |
79 | - execute(set_item(key, key)); |
80 | + execute(binary_set_item(key, key)); |
81 | execute(resend_packet(&cmd)); |
82 | execute(recv_packet(&rsp)); |
83 | verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS)); |
84 | @@ -993,7 +994,7 @@ |
85 | |
86 | for (int ii= 0; ii < 2; ++ii) |
87 | { |
88 | - execute(set_item(key, key)); |
89 | + execute(binary_set_item(key, key)); |
90 | flush_command(&cmd, cc, 0, ii == 0); |
91 | execute(send_packet(&cmd)); |
92 | |
93 | @@ -1036,7 +1037,7 @@ |
94 | else |
95 | value=" world"; |
96 | |
97 | - execute(set_item(key, value)); |
98 | + execute(binary_set_item(key, value)); |
99 | |
100 | if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ) |
101 | value=" world"; |
102 | @@ -1117,7 +1118,650 @@ |
103 | ++cc; |
104 | } |
105 | |
106 | - return TEST_PASS; |
107 | + return TEST_PASS_RECONNECT; |
108 | +} |
109 | + |
110 | +static enum test_return send_string(const char *cmd) |
111 | +{ |
112 | + execute(retry_write(cmd, strlen(cmd))); |
113 | + return TEST_PASS; |
114 | +} |
115 | + |
116 | +static enum test_return receive_line(char *buffer, size_t size) |
117 | +{ |
118 | + size_t offset= 0; |
119 | + while (offset < size) |
120 | + { |
121 | + execute(retry_read(buffer + offset, 1)); |
122 | + if (buffer[offset] == '\n') |
123 | + { |
124 | + if (offset + 1 < size) |
125 | + { |
126 | + buffer[offset + 1]= '\0'; |
127 | + return TEST_PASS; |
128 | + } |
129 | + else |
130 | + return TEST_FAIL; |
131 | + } |
132 | + ++offset; |
133 | + } |
134 | + |
135 | + return TEST_FAIL; |
136 | +} |
137 | + |
138 | +static enum test_return receive_response(const char *msg) { |
139 | + char buffer[80]; |
140 | + execute(receive_line(buffer, sizeof(buffer))); |
141 | + verify(strcmp(msg, buffer) == 0); |
142 | + return TEST_PASS; |
143 | +} |
144 | + |
145 | +static enum test_return test_ascii_quit(void) |
146 | +{ |
147 | + /* Verify that quit handles unknown options */ |
148 | + execute(send_string("quit foo bar\r\n")); |
149 | + execute(receive_response("ERROR\r\n")); |
150 | + |
151 | + /* quit doesn't support noreply */ |
152 | + execute(send_string("quit noreply\r\n")); |
153 | + execute(receive_response("ERROR\r\n")); |
154 | + |
155 | + /* Verify that quit works */ |
156 | + execute(send_string("quit\r\n")); |
157 | + |
158 | + /* Socket should be closed now, read should return 0 */ |
159 | + char buffer[80]; |
160 | + verify(timeout_io_op(sock, POLLIN, buffer, sizeof(buffer)) == 0); |
161 | + return TEST_PASS_RECONNECT; |
162 | + |
163 | +} |
164 | + |
165 | +static enum test_return test_ascii_version(void) |
166 | +{ |
167 | + /* Verify that version command handles unknown options */ |
168 | + execute(send_string("version foo bar\r\n")); |
169 | + execute(receive_response("ERROR\r\n")); |
170 | + |
171 | + /* version doesn't support noreply */ |
172 | + execute(send_string("version noreply\r\n")); |
173 | + execute(receive_response("ERROR\r\n")); |
174 | + |
175 | + /* Verify that verify works */ |
176 | + execute(send_string("version\r\n")); |
177 | + char buffer[256]; |
178 | + execute(receive_line(buffer, sizeof(buffer))); |
179 | + verify(strncmp(buffer, "VERSION ", 8) == 0); |
180 | + |
181 | + return TEST_PASS; |
182 | +} |
183 | + |
184 | +static enum test_return test_ascii_verbosity(void) |
185 | +{ |
186 | + /* This command does not adhere to the spec! */ |
187 | + execute(send_string("verbosity foo bar my\r\n")); |
188 | + execute(receive_response("ERROR\r\n")); |
189 | + |
190 | + execute(send_string("verbosity noreply\r\n")); |
191 | + execute(test_ascii_version()); |
192 | + |
193 | + execute(send_string("verbosity 0 noreply\r\n")); |
194 | + execute(test_ascii_version()); |
195 | + |
196 | + execute(send_string("verbosity\r\n")); |
197 | + execute(receive_response("ERROR\r\n")); |
198 | + |
199 | + execute(send_string("verbosity 1\r\n")); |
200 | + execute(receive_response("OK\r\n")); |
201 | + |
202 | + execute(send_string("verbosity 0\r\n")); |
203 | + execute(receive_response("OK\r\n")); |
204 | + |
205 | + return TEST_PASS; |
206 | +} |
207 | + |
208 | + |
209 | + |
210 | +static enum test_return test_ascii_set_impl(const char* key, bool noreply) |
211 | +{ |
212 | + /* @todo add tests for bogus format! */ |
213 | + char buffer[1024]; |
214 | + sprintf(buffer, "set %s 0 0 5%s\r\nvalue\r\n", key, |
215 | + noreply ? " noreply" : ""); |
216 | + execute(send_string(buffer)); |
217 | + |
218 | + if (!noreply) |
219 | + execute(receive_response("STORED\r\n")); |
220 | + |
221 | + return test_ascii_version(); |
222 | +} |
223 | + |
224 | +static enum test_return test_ascii_set(void) |
225 | +{ |
226 | + return test_ascii_set_impl("test_ascii_set", false); |
227 | +} |
228 | + |
229 | +static enum test_return test_ascii_set_noreply(void) |
230 | +{ |
231 | + return test_ascii_set_impl("test_ascii_set_noreply", true); |
232 | +} |
233 | + |
234 | +static enum test_return test_ascii_add_impl(const char* key, bool noreply) |
235 | +{ |
236 | + /* @todo add tests for bogus format! */ |
237 | + char buffer[1024]; |
238 | + sprintf(buffer, "add %s 0 0 5%s\r\nvalue\r\n", key, |
239 | + noreply ? " noreply" : ""); |
240 | + execute(send_string(buffer)); |
241 | + |
242 | + if (!noreply) |
243 | + execute(receive_response("STORED\r\n")); |
244 | + |
245 | + execute(send_string(buffer)); |
246 | + |
247 | + if (!noreply) |
248 | + execute(receive_response("NOT_STORED\r\n")); |
249 | + |
250 | + return test_ascii_version(); |
251 | +} |
252 | + |
253 | +static enum test_return test_ascii_add(void) |
254 | +{ |
255 | + return test_ascii_add_impl("test_ascii_add", false); |
256 | +} |
257 | + |
258 | +static enum test_return test_ascii_add_noreply(void) |
259 | +{ |
260 | + return test_ascii_add_impl("test_ascii_add_noreply", true); |
261 | +} |
262 | + |
263 | +static enum test_return ascii_get_value(const char *key, const char *value) |
264 | +{ |
265 | + |
266 | + char buffer[1024]; |
267 | + size_t datasize= strlen(value); |
268 | + |
269 | + verify(datasize < sizeof(buffer)); |
270 | + execute(receive_line(buffer, sizeof(buffer))); |
271 | + verify(strncmp(buffer, "VALUE ", 6) == 0); |
272 | + verify(strncmp(buffer + 6, key, strlen(key)) == 0); |
273 | + char *ptr= buffer + 6 + strlen(key) + 1; |
274 | + char *end; |
275 | + |
276 | + unsigned long val= strtoul(ptr, &end, 10); /* flags */ |
277 | + verify(ptr != end); |
278 | + verify(val == 0); |
279 | + verify(end != NULL); |
280 | + val= strtoul(end, &end, 10); /* size */ |
281 | + verify(ptr != end); |
282 | + verify(val == datasize); |
283 | + verify(end != NULL); |
284 | + while (*end != '\n' && isspace(*end)) |
285 | + ++end; |
286 | + verify(*end == '\n'); |
287 | + |
288 | + execute(retry_read(buffer, datasize)); |
289 | + verify(memcmp(buffer, value, datasize) == 0); |
290 | + |
291 | + execute(retry_read(buffer, 2)); |
292 | + verify(memcmp(buffer, "\r\n", 2) == 0); |
293 | + |
294 | + return TEST_PASS; |
295 | +} |
296 | + |
297 | +static enum test_return ascii_get_item(const char *key, const char *value, |
298 | + bool exist) |
299 | +{ |
300 | + char buffer[1024]; |
301 | + size_t datasize= 0; |
302 | + if (value != NULL) |
303 | + datasize= strlen(value); |
304 | + |
305 | + verify(datasize < sizeof(buffer)); |
306 | + sprintf(buffer, "get %s\r\n", key); |
307 | + execute(send_string(buffer)); |
308 | + |
309 | + if (exist) |
310 | + execute(ascii_get_value(key, value)); |
311 | + |
312 | + execute(retry_read(buffer, 5)); |
313 | + verify(memcmp(buffer, "END\r\n", 5) == 0); |
314 | + |
315 | + return TEST_PASS; |
316 | +} |
317 | + |
318 | +static enum test_return ascii_gets_value(const char *key, const char *value, |
319 | + unsigned long *cas) |
320 | +{ |
321 | + |
322 | + char buffer[1024]; |
323 | + size_t datasize= strlen(value); |
324 | + |
325 | + verify(datasize < sizeof(buffer)); |
326 | + execute(receive_line(buffer, sizeof(buffer))); |
327 | + verify(strncmp(buffer, "VALUE ", 6) == 0); |
328 | + verify(strncmp(buffer + 6, key, strlen(key)) == 0); |
329 | + char *ptr= buffer + 6 + strlen(key) + 1; |
330 | + char *end; |
331 | + |
332 | + unsigned long val= strtoul(ptr, &end, 10); /* flags */ |
333 | + verify(ptr != end); |
334 | + verify(val == 0); |
335 | + verify(end != NULL); |
336 | + val= strtoul(end, &end, 10); /* size */ |
337 | + verify(ptr != end); |
338 | + verify(val == datasize); |
339 | + verify(end != NULL); |
340 | + *cas= strtoul(end, &end, 10); /* cas */ |
341 | + verify(ptr != end); |
342 | + verify(val == datasize); |
343 | + verify(end != NULL); |
344 | + |
345 | + while (*end != '\n' && isspace(*end)) |
346 | + ++end; |
347 | + verify(*end == '\n'); |
348 | + |
349 | + execute(retry_read(buffer, datasize)); |
350 | + verify(memcmp(buffer, value, datasize) == 0); |
351 | + |
352 | + execute(retry_read(buffer, 2)); |
353 | + verify(memcmp(buffer, "\r\n", 2) == 0); |
354 | + |
355 | + return TEST_PASS; |
356 | +} |
357 | + |
358 | +static enum test_return ascii_gets_item(const char *key, const char *value, |
359 | + bool exist, unsigned long *cas) |
360 | +{ |
361 | + char buffer[1024]; |
362 | + size_t datasize= 0; |
363 | + if (value != NULL) |
364 | + datasize= strlen(value); |
365 | + |
366 | + verify(datasize < sizeof(buffer)); |
367 | + sprintf(buffer, "gets %s\r\n", key); |
368 | + execute(send_string(buffer)); |
369 | + |
370 | + if (exist) |
371 | + execute(ascii_gets_value(key, value, cas)); |
372 | + |
373 | + execute(retry_read(buffer, 5)); |
374 | + verify(memcmp(buffer, "END\r\n", 5) == 0); |
375 | + |
376 | + return TEST_PASS; |
377 | +} |
378 | + |
379 | +static enum test_return ascii_set_item(const char *key, const char *value) |
380 | +{ |
381 | + char buffer[300]; |
382 | + size_t len= strlen(value); |
383 | + sprintf(buffer, "set %s 0 0 %u\r\n", key, (unsigned int)len); |
384 | + execute(send_string(buffer)); |
385 | + execute(retry_write(value, len)); |
386 | + execute(send_string("\r\n")); |
387 | + execute(receive_response("STORED\r\n")); |
388 | + return TEST_PASS; |
389 | +} |
390 | + |
391 | +static enum test_return test_ascii_replace_impl(const char* key, bool noreply) |
392 | +{ |
393 | + char buffer[1024]; |
394 | + sprintf(buffer, "replace %s 0 0 5%s\r\nvalue\r\n", key, |
395 | + noreply ? " noreply" : ""); |
396 | + execute(send_string(buffer)); |
397 | + |
398 | + if (noreply) |
399 | + execute(test_ascii_version()); |
400 | + else |
401 | + execute(receive_response("NOT_STORED\r\n")); |
402 | + |
403 | + execute(ascii_set_item(key, "value")); |
404 | + execute(ascii_get_item(key, "value", true)); |
405 | + |
406 | + |
407 | + execute(send_string(buffer)); |
408 | + |
409 | + if (noreply) |
410 | + execute(test_ascii_version()); |
411 | + else |
412 | + execute(receive_response("STORED\r\n")); |
413 | + |
414 | + return test_ascii_version(); |
415 | +} |
416 | + |
417 | +static enum test_return test_ascii_replace(void) |
418 | +{ |
419 | + return test_ascii_replace_impl("test_ascii_replace", false); |
420 | +} |
421 | + |
422 | +static enum test_return test_ascii_replace_noreply(void) |
423 | +{ |
424 | + return test_ascii_replace_impl("test_ascii_replace_noreply", true); |
425 | +} |
426 | + |
427 | +static enum test_return test_ascii_cas_impl(const char* key, bool noreply) |
428 | +{ |
429 | + char buffer[1024]; |
430 | + unsigned long cas; |
431 | + |
432 | + execute(ascii_set_item(key, "value")); |
433 | + execute(ascii_gets_item(key, "value", true, &cas)); |
434 | + |
435 | + sprintf(buffer, "cas %s 0 0 6 %lu%s\r\nvalue2\r\n", key, cas, |
436 | + noreply ? " noreply" : ""); |
437 | + execute(send_string(buffer)); |
438 | + |
439 | + if (noreply) |
440 | + execute(test_ascii_version()); |
441 | + else |
442 | + execute(receive_response("STORED\r\n")); |
443 | + |
444 | + /* reexecute the same command should fail due to illegal cas */ |
445 | + execute(send_string(buffer)); |
446 | + |
447 | + if (noreply) |
448 | + execute(test_ascii_version()); |
449 | + else |
450 | + execute(receive_response("EXISTS\r\n")); |
451 | + |
452 | + return test_ascii_version(); |
453 | +} |
454 | + |
455 | +static enum test_return test_ascii_cas(void) |
456 | +{ |
457 | + return test_ascii_cas_impl("test_ascii_cas", false); |
458 | +} |
459 | + |
460 | +static enum test_return test_ascii_cas_noreply(void) |
461 | +{ |
462 | + return test_ascii_cas_impl("test_ascii_cas_noreply", true); |
463 | +} |
464 | + |
465 | +static enum test_return test_ascii_delete_impl(const char *key, bool noreply) |
466 | +{ |
467 | + execute(ascii_set_item(key, "value")); |
468 | + |
469 | + execute(send_string("delete\r\n")); |
470 | + execute(receive_response("ERROR\r\n")); |
471 | + /* BUG: the server accepts delete a b */ |
472 | + execute(send_string("delete a b c d e\r\n")); |
473 | + execute(receive_response("ERROR\r\n")); |
474 | + |
475 | + char buffer[1024]; |
476 | + sprintf(buffer, "delete %s%s\r\n", key, noreply ? " noreply" : ""); |
477 | + execute(send_string(buffer)); |
478 | + |
479 | + if (noreply) |
480 | + execute(test_ascii_version()); |
481 | + else |
482 | + execute(receive_response("DELETED\r\n")); |
483 | + |
484 | + execute(ascii_get_item(key, "value", false)); |
485 | + execute(send_string(buffer)); |
486 | + if (noreply) |
487 | + execute(test_ascii_version()); |
488 | + else |
489 | + execute(receive_response("NOT_FOUND\r\n")); |
490 | + |
491 | + return TEST_PASS; |
492 | +} |
493 | + |
494 | +static enum test_return test_ascii_delete(void) |
495 | +{ |
496 | + return test_ascii_delete_impl("test_ascii_delete", false); |
497 | +} |
498 | + |
499 | +static enum test_return test_ascii_delete_noreply(void) |
500 | +{ |
501 | + return test_ascii_delete_impl("test_ascii_delete_noreply", true); |
502 | +} |
503 | + |
504 | +static enum test_return test_ascii_get(void) |
505 | +{ |
506 | + execute(ascii_set_item("test_ascii_get", "value")); |
507 | + |
508 | + execute(send_string("get\r\n")); |
509 | + execute(receive_response("ERROR\r\n")); |
510 | + execute(ascii_get_item("test_ascii_get", "value", true)); |
511 | + execute(ascii_get_item("test_ascii_get_notfound", "value", false)); |
512 | + |
513 | + return TEST_PASS; |
514 | +} |
515 | + |
516 | +static enum test_return test_ascii_gets(void) |
517 | +{ |
518 | + execute(ascii_set_item("test_ascii_gets", "value")); |
519 | + |
520 | + execute(send_string("gets\r\n")); |
521 | + execute(receive_response("ERROR\r\n")); |
522 | + unsigned long cas; |
523 | + execute(ascii_gets_item("test_ascii_gets", "value", true, &cas)); |
524 | + execute(ascii_gets_item("test_ascii_gets_notfound", "value", false, &cas)); |
525 | + |
526 | + return TEST_PASS; |
527 | +} |
528 | + |
529 | +static enum test_return test_ascii_mget(void) |
530 | +{ |
531 | + execute(ascii_set_item("test_ascii_mget1", "value")); |
532 | + execute(ascii_set_item("test_ascii_mget2", "value")); |
533 | + execute(ascii_set_item("test_ascii_mget3", "value")); |
534 | + execute(ascii_set_item("test_ascii_mget4", "value")); |
535 | + execute(ascii_set_item("test_ascii_mget5", "value")); |
536 | + |
537 | + execute(send_string("get test_ascii_mget1 test_ascii_mget2 test_ascii_mget3 " |
538 | + "test_ascii_mget4 test_ascii_mget5 " |
539 | + "test_ascii_mget6\r\n")); |
540 | + execute(ascii_get_value("test_ascii_mget1", "value")); |
541 | + execute(ascii_get_value("test_ascii_mget2", "value")); |
542 | + execute(ascii_get_value("test_ascii_mget3", "value")); |
543 | + execute(ascii_get_value("test_ascii_mget4", "value")); |
544 | + execute(ascii_get_value("test_ascii_mget5", "value")); |
545 | + |
546 | + char buffer[5]; |
547 | + execute(retry_read(buffer, 5)); |
548 | + verify(memcmp(buffer, "END\r\n", 5) == 0); |
549 | + return TEST_PASS; |
550 | +} |
551 | + |
552 | +static enum test_return test_ascii_incr_impl(const char* key, bool noreply) |
553 | +{ |
554 | + char cmd[300]; |
555 | + sprintf(cmd, "incr %s 1%s\r\n", key, noreply ? " noreply" : ""); |
556 | + |
557 | + execute(ascii_set_item(key, "0")); |
558 | + for (int x= 1; x < 11; ++x) |
559 | + { |
560 | + execute(send_string(cmd)); |
561 | + |
562 | + if (noreply) |
563 | + execute(test_ascii_version()); |
564 | + else |
565 | + { |
566 | + char buffer[80]; |
567 | + execute(receive_line(buffer, sizeof(buffer))); |
568 | + int val= atoi(buffer); |
569 | + verify(val == x); |
570 | + } |
571 | + } |
572 | + |
573 | + execute(ascii_get_item(key, "10", true)); |
574 | + |
575 | + return TEST_PASS; |
576 | +} |
577 | + |
578 | +static enum test_return test_ascii_incr(void) |
579 | +{ |
580 | + return test_ascii_incr_impl("test_ascii_incr", false); |
581 | +} |
582 | + |
583 | +static enum test_return test_ascii_incr_noreply(void) |
584 | +{ |
585 | + return test_ascii_incr_impl("test_ascii_incr_noreply", true); |
586 | +} |
587 | + |
588 | +static enum test_return test_ascii_decr_impl(const char* key, bool noreply) |
589 | +{ |
590 | + char cmd[300]; |
591 | + sprintf(cmd, "decr %s 1%s\r\n", key, noreply ? " noreply" : ""); |
592 | + |
593 | + execute(ascii_set_item(key, "9")); |
594 | + for (int x= 8; x > -1; --x) |
595 | + { |
596 | + execute(send_string(cmd)); |
597 | + |
598 | + if (noreply) |
599 | + execute(test_ascii_version()); |
600 | + else |
601 | + { |
602 | + char buffer[80]; |
603 | + execute(receive_line(buffer, sizeof(buffer))); |
604 | + int val= atoi(buffer); |
605 | + verify(val == x); |
606 | + } |
607 | + } |
608 | + |
609 | + execute(ascii_get_item(key, "0", true)); |
610 | + |
611 | + /* verify that it doesn't wrap */ |
612 | + execute(send_string(cmd)); |
613 | + if (noreply) |
614 | + execute(test_ascii_version()); |
615 | + else |
616 | + { |
617 | + char buffer[80]; |
618 | + execute(receive_line(buffer, sizeof(buffer))); |
619 | + } |
620 | + execute(ascii_get_item(key, "0", true)); |
621 | + |
622 | + return TEST_PASS; |
623 | +} |
624 | + |
625 | +static enum test_return test_ascii_decr(void) |
626 | +{ |
627 | + return test_ascii_decr_impl("test_ascii_decr", false); |
628 | +} |
629 | + |
630 | +static enum test_return test_ascii_decr_noreply(void) |
631 | +{ |
632 | + return test_ascii_decr_impl("test_ascii_decr_noreply", true); |
633 | +} |
634 | + |
635 | + |
636 | +static enum test_return test_ascii_flush_impl(const char *key, bool noreply) |
637 | +{ |
638 | +#if 0 |
639 | + /* Verify that the flush_all command handles unknown options */ |
640 | + /* Bug in the current memcached server! */ |
641 | + execute(send_string("flush_all foo bar\r\n")); |
642 | + execute(receive_response("ERROR\r\n")); |
643 | +#endif |
644 | + |
645 | + execute(ascii_set_item(key, key)); |
646 | + execute(ascii_get_item(key, key, true)); |
647 | + |
648 | + if (noreply) |
649 | + { |
650 | + execute(send_string("flush_all noreply\r\n")); |
651 | + execute(test_ascii_version()); |
652 | + } |
653 | + else |
654 | + { |
655 | + execute(send_string("flush_all\r\n")); |
656 | + execute(receive_response("OK\r\n")); |
657 | + } |
658 | + |
659 | + execute(ascii_get_item(key, key, false)); |
660 | + |
661 | + return TEST_PASS; |
662 | +} |
663 | + |
664 | +static enum test_return test_ascii_flush(void) |
665 | +{ |
666 | + return test_ascii_flush_impl("test_ascii_flush", false); |
667 | +} |
668 | + |
669 | +static enum test_return test_ascii_flush_noreply(void) |
670 | +{ |
671 | + return test_ascii_flush_impl("test_ascii_flush_noreply", true); |
672 | +} |
673 | + |
674 | +static enum test_return test_ascii_concat_impl(const char *key, |
675 | + bool append, |
676 | + bool noreply) |
677 | +{ |
678 | + const char *value; |
679 | + |
680 | + if (append) |
681 | + value="hello"; |
682 | + else |
683 | + value=" world"; |
684 | + |
685 | + execute(ascii_set_item(key, value)); |
686 | + |
687 | + if (append) |
688 | + value=" world"; |
689 | + else |
690 | + value="hello"; |
691 | + |
692 | + char cmd[400]; |
693 | + sprintf(cmd, "%s %s 0 0 %u%s\r\n%s\r\n", |
694 | + append ? "append" : "prepend", |
695 | + key, (unsigned int)strlen(value), noreply ? " noreply" : "", |
696 | + value); |
697 | + execute(send_string(cmd)); |
698 | + |
699 | + if (noreply) |
700 | + execute(test_ascii_version()); |
701 | + else |
702 | + execute(receive_response("STORED\r\n")); |
703 | + |
704 | + execute(ascii_get_item(key, "hello world", true)); |
705 | + |
706 | + sprintf(cmd, "%s %s_notfound 0 0 %u%s\r\n%s\r\n", |
707 | + append ? "append" : "prepend", |
708 | + key, (unsigned int)strlen(value), noreply ? " noreply" : "", |
709 | + value); |
710 | + execute(send_string(cmd)); |
711 | + |
712 | + if (noreply) |
713 | + execute(test_ascii_version()); |
714 | + else |
715 | + execute(receive_response("NOT_STORED\r\n")); |
716 | + |
717 | + return TEST_PASS; |
718 | +} |
719 | + |
720 | +static enum test_return test_ascii_append(void) |
721 | +{ |
722 | + return test_ascii_concat_impl("test_ascii_append", true, false); |
723 | +} |
724 | + |
725 | +static enum test_return test_ascii_prepend(void) |
726 | +{ |
727 | + return test_ascii_concat_impl("test_ascii_prepend", false, false); |
728 | +} |
729 | + |
730 | +static enum test_return test_ascii_append_noreply(void) |
731 | +{ |
732 | + return test_ascii_concat_impl("test_ascii_append_noreply", true, true); |
733 | +} |
734 | + |
735 | +static enum test_return test_ascii_prepend_noreply(void) |
736 | +{ |
737 | + return test_ascii_concat_impl("test_ascii_prepend_noreply", false, true); |
738 | +} |
739 | + |
740 | +static enum test_return test_ascii_stat(void) |
741 | +{ |
742 | + execute(send_string("stats noreply\r\n")); |
743 | + execute(receive_response("ERROR\r\n")); |
744 | + execute(send_string("stats\r\n")); |
745 | + char buffer[1024]; |
746 | + do { |
747 | + execute(receive_line(buffer, sizeof(buffer))); |
748 | + } while (strcmp(buffer, "END\r\n") != 0); |
749 | + |
750 | + return TEST_PASS_RECONNECT; |
751 | } |
752 | |
753 | typedef enum test_return(*TEST_FUNC)(void); |
754 | @@ -1129,34 +1773,61 @@ |
755 | }; |
756 | |
757 | struct testcase testcases[]= { |
758 | - { "noop", test_binary_noop}, |
759 | - { "quit", test_binary_quit}, |
760 | - { "quitq", test_binary_quitq}, |
761 | - { "set", test_binary_set}, |
762 | - { "setq", test_binary_setq}, |
763 | - { "flush", test_binary_flush}, |
764 | - { "flushq", test_binary_flushq}, |
765 | - { "add", test_binary_add}, |
766 | - { "addq", test_binary_addq}, |
767 | - { "replace", test_binary_replace}, |
768 | - { "replaceq", test_binary_replaceq}, |
769 | - { "delete", test_binary_delete}, |
770 | - { "deleteq", test_binary_deleteq}, |
771 | - { "get", test_binary_get}, |
772 | - { "getq", test_binary_getq}, |
773 | - { "getk", test_binary_getk}, |
774 | - { "getkq", test_binary_getkq}, |
775 | - { "incr", test_binary_incr}, |
776 | - { "incrq", test_binary_incrq}, |
777 | - { "decr", test_binary_decr}, |
778 | - { "decrq", test_binary_decrq}, |
779 | - { "version", test_binary_version}, |
780 | - { "append", test_binary_append}, |
781 | - { "appendq", test_binary_appendq}, |
782 | - { "prepend", test_binary_prepend}, |
783 | - { "prependq", test_binary_prependq}, |
784 | - { "stat", test_binary_stat}, |
785 | - { "illegal", test_binary_illegal}, |
786 | + { "ascii quit", test_ascii_quit }, |
787 | + { "ascii version", test_ascii_version }, |
788 | + { "ascii verbosity", test_ascii_verbosity }, |
789 | + { "ascii set", test_ascii_set }, |
790 | + { "ascii set noreply", test_ascii_set_noreply }, |
791 | + { "ascii get", test_ascii_get }, |
792 | + { "ascii gets", test_ascii_gets }, |
793 | + { "ascii mget", test_ascii_mget }, |
794 | + { "ascii flush", test_ascii_flush }, |
795 | + { "ascii flush noreply", test_ascii_flush_noreply }, |
796 | + { "ascii add", test_ascii_add }, |
797 | + { "ascii add noreply", test_ascii_add_noreply }, |
798 | + { "ascii replace", test_ascii_replace }, |
799 | + { "ascii replace noreply", test_ascii_replace_noreply }, |
800 | + { "ascii cas", test_ascii_cas }, |
801 | + { "ascii cas noreply", test_ascii_cas_noreply }, |
802 | + { "ascii delete", test_ascii_delete }, |
803 | + { "ascii delete noreply", test_ascii_delete_noreply }, |
804 | + { "ascii incr", test_ascii_incr }, |
805 | + { "ascii incr noreply", test_ascii_incr_noreply }, |
806 | + { "ascii decr", test_ascii_decr }, |
807 | + { "ascii decr noreply", test_ascii_decr_noreply }, |
808 | + { "ascii append", test_ascii_append }, |
809 | + { "ascii append noreply", test_ascii_append_noreply }, |
810 | + { "ascii prepend", test_ascii_prepend }, |
811 | + { "ascii prepend noreply", test_ascii_prepend_noreply }, |
812 | + { "ascii stat", test_ascii_stat }, |
813 | + { "binary noop", test_binary_noop }, |
814 | + { "binary quit", test_binary_quit }, |
815 | + { "binary quitq", test_binary_quitq }, |
816 | + { "binary set", test_binary_set }, |
817 | + { "binary setq", test_binary_setq }, |
818 | + { "binary flush", test_binary_flush }, |
819 | + { "binary flushq", test_binary_flushq }, |
820 | + { "binary add", test_binary_add }, |
821 | + { "binary addq", test_binary_addq }, |
822 | + { "binary replace", test_binary_replace }, |
823 | + { "binary replaceq", test_binary_replaceq }, |
824 | + { "binary delete", test_binary_delete }, |
825 | + { "binary deleteq", test_binary_deleteq }, |
826 | + { "binary get", test_binary_get }, |
827 | + { "binary getq", test_binary_getq }, |
828 | + { "binary getk", test_binary_getk }, |
829 | + { "binary getkq", test_binary_getkq }, |
830 | + { "binary incr", test_binary_incr }, |
831 | + { "binary incrq", test_binary_incrq }, |
832 | + { "binary decr", test_binary_decr }, |
833 | + { "binary decrq", test_binary_decrq }, |
834 | + { "binary version", test_binary_version }, |
835 | + { "binary append", test_binary_append }, |
836 | + { "binary appendq", test_binary_appendq }, |
837 | + { "binary prepend", test_binary_prepend }, |
838 | + { "binary prependq", test_binary_prependq }, |
839 | + { "binary stat", test_binary_stat }, |
840 | + { "binary illegal", test_binary_illegal }, |
841 | { NULL, NULL} |
842 | }; |
843 | |
844 | @@ -1209,20 +1880,22 @@ |
845 | for (int ii= 0; testcases[ii].description != NULL; ++ii) |
846 | { |
847 | ++total; |
848 | - fprintf(stdout, "%s\t\t", testcases[ii].description); |
849 | + fprintf(stdout, "%-40s", testcases[ii].description); |
850 | fflush(stdout); |
851 | |
852 | bool reconnect= false; |
853 | enum test_return ret= testcases[ii].function(); |
854 | - fprintf(stderr, "%s\n", status_msg[ret]); |
855 | if (ret == TEST_FAIL) |
856 | { |
857 | reconnect= true; |
858 | ++failed; |
859 | + if (verbose) |
860 | + fprintf(stderr, "\n"); |
861 | } |
862 | else if (ret == TEST_PASS_RECONNECT) |
863 | reconnect= true; |
864 | |
865 | + fprintf(stderr, "%s\n", status_msg[ret]); |
866 | if (reconnect) |
867 | { |
868 | (void) close(sock); |
869 | |
870 | === modified file 'libmemcached/memcached_delete.c' |
871 | --- libmemcached/memcached_delete.c 2009-07-18 17:09:59 +0000 |
872 | +++ libmemcached/memcached_delete.c 2009-10-08 14:12:13 +0000 |
873 | @@ -36,7 +36,7 @@ |
874 | return MEMCACHED_NO_SERVERS; |
875 | |
876 | server_key= memcached_generate_hash(ptr, master_key, master_key_length); |
877 | - to_write= (uint8_t) (ptr->flags & MEM_BUFFER_REQUESTS) ? 0 : 1; |
878 | + to_write= (uint8_t)((ptr->flags & MEM_BUFFER_REQUESTS) ? 0 : 1); |
879 | bool no_reply= (ptr->flags & MEM_NOREPLY); |
880 | |
881 | if (ptr->flags & MEM_BINARY_PROTOCOL) |
882 | |
883 | === modified file 'libmemcached/memcached_get.c' |
884 | --- libmemcached/memcached_get.c 2009-09-19 12:24:37 +0000 |
885 | +++ libmemcached/memcached_get.c 2009-10-08 14:12:13 +0000 |
886 | @@ -338,6 +338,9 @@ |
887 | rc= MEMCACHED_SOME_ERRORS; |
888 | continue; |
889 | } |
890 | + |
891 | + /* We just want one pending response per server */ |
892 | + memcached_server_response_reset(&ptr->hosts[server_key]); |
893 | memcached_server_response_increment(&ptr->hosts[server_key]); |
894 | if ((x > 0 && x == ptr->io_key_prefetch) && |
895 | memcached_flush_buffers(ptr) != MEMCACHED_SUCCESS) |
896 | @@ -371,7 +374,6 @@ |
897 | memcached_io_reset(&ptr->hosts[x]); |
898 | rc= MEMCACHED_SOME_ERRORS; |
899 | } |
900 | - memcached_server_response_increment(&ptr->hosts[x]); |
901 | } |
902 | } |
903 | |
904 | @@ -438,6 +440,8 @@ |
905 | success= false; |
906 | continue; |
907 | } |
908 | + /* we just want one pending response per server */ |
909 | + memcached_server_response_reset(&ptr->hosts[server]); |
910 | memcached_server_response_increment(&ptr->hosts[server]); |
911 | } |
912 | |
913 | @@ -461,7 +465,6 @@ |
914 | dead_servers[x]= true; |
915 | success= false; |
916 | } |
917 | - memcached_server_response_increment(&ptr->hosts[x]); |
918 | |
919 | /* mark all of the messages bound for this server as sent! */ |
920 | for (x= 0; x < number_of_keys; ++x) |
921 | |
922 | === modified file 'libmemcached/memcached_purge.c' |
923 | --- libmemcached/memcached_purge.c 2009-07-18 17:37:40 +0000 |
924 | +++ libmemcached/memcached_purge.c 2009-10-08 14:12:13 +0000 |
925 | @@ -10,7 +10,7 @@ |
926 | if (ptr->root->purging || /* already purging */ |
927 | (memcached_server_response_count(ptr) < ptr->root->io_msg_watermark && |
928 | ptr->io_bytes_sent < ptr->root->io_bytes_watermark) || |
929 | - (ptr->io_bytes_sent > ptr->root->io_bytes_watermark && |
930 | + (ptr->io_bytes_sent >= ptr->root->io_bytes_watermark && |
931 | memcached_server_response_count(ptr) < 2)) |
932 | { |
933 | return MEMCACHED_SUCCESS; |
934 | |
935 | === modified file 'libmemcached/memcached_response.c' |
936 | --- libmemcached/memcached_response.c 2009-09-22 08:26:38 +0000 |
937 | +++ libmemcached/memcached_response.c 2009-10-08 14:12:13 +0000 |
938 | @@ -356,8 +356,14 @@ |
939 | { |
940 | switch (header.response.opcode) |
941 | { |
942 | + case PROTOCOL_BINARY_CMD_GETKQ: |
943 | + /* |
944 | + * We didn't increment the response counter for the GETKQ packet |
945 | + * (only the final NOOP), so we need to increment the counter again. |
946 | + */ |
947 | + memcached_server_response_increment(ptr); |
948 | + /* FALLTHROUGH */ |
949 | case PROTOCOL_BINARY_CMD_GETK: |
950 | - case PROTOCOL_BINARY_CMD_GETKQ: |
951 | { |
952 | uint16_t keylen= header.response.keylen; |
953 | memcached_result_reset(result); |
954 | |
955 | === modified file 'libmemcached/memcached_stats.c' |
956 | --- libmemcached/memcached_stats.c 2009-07-18 17:37:40 +0000 |
957 | +++ libmemcached/memcached_stats.c 2009-10-08 14:12:13 +0000 |
958 | @@ -185,8 +185,6 @@ |
959 | length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->curr_items); |
960 | else if (!memcmp("total_items", key, strlen("total_items"))) |
961 | length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->total_items); |
962 | - else if (!memcmp("bytes", key, strlen("bytes"))) |
963 | - length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes); |
964 | else if (!memcmp("curr_connections", key, strlen("curr_connections"))) |
965 | length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->curr_connections); |
966 | else if (!memcmp("total_connections", key, strlen("total_connections"))) |
967 | @@ -207,6 +205,8 @@ |
968 | length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes_read); |
969 | else if (!memcmp("bytes_written", key, strlen("bytes_written"))) |
970 | length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes_written); |
971 | + else if (!memcmp("bytes", key, strlen("bytes"))) |
972 | + length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes); |
973 | else if (!memcmp("limit_maxbytes", key, strlen("limit_maxbytes"))) |
974 | length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->limit_maxbytes); |
975 | else if (!memcmp("threads", key, strlen("threads"))) |
976 | |
977 | === modified file 'tests/function.c' |
978 | --- tests/function.c 2009-10-05 21:04:26 +0000 |
979 | +++ tests/function.c 2009-10-08 14:12:13 +0000 |
980 | @@ -4505,6 +4505,156 @@ |
981 | return TEST_SUCCESS; |
982 | } |
983 | |
984 | +static test_return regression_bug_434843(memcached_st *memc) |
985 | +{ |
986 | + if (pre_binary(memc) != TEST_SUCCESS) |
987 | + return TEST_SUCCESS; |
988 | + |
989 | + memcached_return rc; |
990 | + unsigned int counter= 0; |
991 | + memcached_execute_function callbacks[1]= { [0]= &callback_counter }; |
992 | + |
993 | + /* |
994 | + * I only want to hit only _one_ server so I know the number of requests I'm |
995 | + * sending in the pipleine to the server. Let's try to do a multiget of |
996 | + * 10240 (that should satisfy most users don't you tink?) |
997 | + */ |
998 | + uint32_t number_of_hosts= memc->number_of_hosts; |
999 | + memc->number_of_hosts= 1; |
1000 | + const size_t max_keys= 10240; |
1001 | + char **keys= calloc(max_keys, sizeof(char*)); |
1002 | + size_t *key_length=calloc(max_keys, sizeof(size_t)); |
1003 | + |
1004 | + for (int x= 0; x < (int)max_keys; ++x) |
1005 | + { |
1006 | + char k[251]; |
1007 | + key_length[x]= (size_t)snprintf(k, sizeof(k), "0200%u", x); |
1008 | + keys[x]= strdup(k); |
1009 | + assert(keys[x] != NULL); |
1010 | + } |
1011 | + |
1012 | + /* |
1013 | + * Run two times.. the first time we should have 100% cache miss, |
1014 | + * and the second time we should have 100% cache hits |
1015 | + */ |
1016 | + for (int y= 0; y < 2; ++y) |
1017 | + { |
1018 | + rc= memcached_mget(memc, (const char**)keys, key_length, max_keys); |
1019 | + assert(rc == MEMCACHED_SUCCESS); |
1020 | + rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); |
1021 | + if (y == 0) |
1022 | + { |
1023 | + /* The first iteration should give me a 100% cache miss. verify that*/ |
1024 | + assert(counter == 0); |
1025 | + char blob[1024]; |
1026 | + for (int x= 0; x < (int)max_keys; ++x) |
1027 | + { |
1028 | + rc= memcached_add(memc, keys[x], key_length[x], |
1029 | + blob, sizeof(blob), 0, 0); |
1030 | + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); |
1031 | + } |
1032 | + } |
1033 | + else |
1034 | + { |
1035 | + /* Verify that we received all of the key/value pairs */ |
1036 | + assert(counter == (unsigned int)max_keys); |
1037 | + } |
1038 | + } |
1039 | + |
1040 | + /* Release allocated resources */ |
1041 | + for (size_t x= 0; x < max_keys; ++x) |
1042 | + free(keys[x]); |
1043 | + free(keys); |
1044 | + free(key_length); |
1045 | + |
1046 | + memc->number_of_hosts= number_of_hosts; |
1047 | + return TEST_SUCCESS; |
1048 | +} |
1049 | + |
1050 | +static test_return regression_bug_434843_buffered(memcached_st *memc) |
1051 | +{ |
1052 | + memcached_return rc; |
1053 | + rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1); |
1054 | + assert(rc == MEMCACHED_SUCCESS); |
1055 | + |
1056 | + return regression_bug_434843(memc); |
1057 | +} |
1058 | + |
1059 | +static test_return regression_bug_421108(memcached_st *memc) |
1060 | +{ |
1061 | + memcached_return rc; |
1062 | + memcached_stat_st *memc_stat= memcached_stat(memc, NULL, &rc); |
1063 | + assert(rc == MEMCACHED_SUCCESS); |
1064 | + |
1065 | + char *bytes= memcached_stat_get_value(memc, memc_stat, "bytes", &rc); |
1066 | + assert(rc == MEMCACHED_SUCCESS); |
1067 | + assert(bytes != NULL); |
1068 | + char *bytes_read= memcached_stat_get_value(memc, memc_stat, |
1069 | + "bytes_read", &rc); |
1070 | + assert(rc == MEMCACHED_SUCCESS); |
1071 | + assert(bytes_read != NULL); |
1072 | + |
1073 | + char *bytes_written= memcached_stat_get_value(memc, memc_stat, |
1074 | + "bytes_written", &rc); |
1075 | + assert(rc == MEMCACHED_SUCCESS); |
1076 | + assert(bytes_written != NULL); |
1077 | + |
1078 | + assert(strcmp(bytes, bytes_read) != 0); |
1079 | + assert(strcmp(bytes, bytes_written) != 0); |
1080 | + |
1081 | + /* Release allocated resources */ |
1082 | + free(bytes); |
1083 | + free(bytes_read); |
1084 | + free(bytes_written); |
1085 | + memcached_stat_free(NULL, memc_stat); |
1086 | + return TEST_SUCCESS; |
1087 | +} |
1088 | + |
1089 | +/* |
1090 | + * The test case isn't obvious so I should probably document why |
1091 | + * it works the way it does. Bug 442914 was caused by a bug |
1092 | + * in the logic in memcached_purge (it did not handle the case |
1093 | + * where the number of bytes sent was equal to the watermark). |
1094 | + * In this test case, create messages so that we hit that case |
1095 | + * and then disable noreply mode and issue a new command to |
1096 | + * verify that it isn't stuck. If we change the format for the |
1097 | + * delete command or the watermarks, we need to update this |
1098 | + * test.... |
1099 | + */ |
1100 | +static test_return regression_bug_442914(memcached_st *memc) |
1101 | +{ |
1102 | + memcached_return rc; |
1103 | + rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1); |
1104 | + assert(rc == MEMCACHED_SUCCESS); |
1105 | + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); |
1106 | + |
1107 | + uint32_t number_of_hosts= memc->number_of_hosts; |
1108 | + memc->number_of_hosts= 1; |
1109 | + |
1110 | + char k[250]; |
1111 | + size_t len; |
1112 | + |
1113 | + for (int x= 0; x < 250; ++x) |
1114 | + { |
1115 | + len= (size_t)snprintf(k, sizeof(k), "%0250u", x); |
1116 | + rc= memcached_delete(memc, k, len, 0); |
1117 | + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); |
1118 | + } |
1119 | + |
1120 | + len= (size_t)snprintf(k, sizeof(k), "%037u", 251); |
1121 | + rc= memcached_delete(memc, k, len, 0); |
1122 | + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); |
1123 | + |
1124 | + rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 0); |
1125 | + assert(rc == MEMCACHED_SUCCESS); |
1126 | + rc= memcached_delete(memc, k, len, 0); |
1127 | + assert(rc == MEMCACHED_NOTFOUND); |
1128 | + |
1129 | + memc->number_of_hosts= number_of_hosts; |
1130 | + |
1131 | + return TEST_SUCCESS; |
1132 | +} |
1133 | + |
1134 | test_st udp_setup_server_tests[] ={ |
1135 | {"set_udp_behavior_test", 0, set_udp_behavior_test}, |
1136 | {"add_tcp_server_udp_client_test", 0, add_tcp_server_udp_client_test}, |
1137 | @@ -4666,6 +4816,10 @@ |
1138 | */ |
1139 | test_st regression_tests[]= { |
1140 | {"lp:434484", 1, regression_bug_434484 }, |
1141 | + {"lp:434843", 1, regression_bug_434843 }, |
1142 | + {"lp:434843 buffered", 1, regression_bug_434843_buffered }, |
1143 | + {"lp:421108", 1, regression_bug_421108 }, |
1144 | + {"lp:442914", 1, regression_bug_442914 }, |
1145 | {0, 0, 0} |
1146 | }; |
1147 |
596. By Trond Norbye 11 minutes ago
Create workaround for warnings generated by a broken C99 compiler
Some of the flags to turn on extra analysis and warnings in gcc contains
various bugs related to struct initializations (see section 6.7.8 in C99)
causing bogus warnings to be generated. Due to the fact that we compile
with warning == error, this is a showstopper for us. We cannot expect all
users to be running the latest compilers, so we have to create the workaround
in our code.
595. By Trond Norbye 1 hour ago
Fix return type from test functions (should be TEST_SUCCESS and not 0)
594. By Trond Norbye 1 hour ago
Strip trailing whitespaces
593. By Trond Norbye 1 hour ago
Update protocol due to review comments:
* Typedef the structs in the public interface
* Removed the EVENT enum, and replaced it with a bitmask of it's own type
* Added support for PAUSE events in the _binary_ protocol. ASCII is on the
todo list :-)
592. By Trond Norbye 3 hours ago
Move libmemcachedutil to libmemcached/util where it belongs
591. By Trond Norbye 4 hours ago
Fix compilation failure on 32 bit systems caused by macro redefinition