Apache HTTPD
apr_memcache.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr_memcache.h"
18#include "apr_poll.h"
19#include "apr_version.h"
20#include <stdlib.h>
21
22#define BUFFER_SIZE 512
34
35/* Strings for Client Commands */
36
37#define MC_EOL "\r\n"
38#define MC_EOL_LEN (sizeof(MC_EOL)-1)
39
40#define MC_WS " "
41#define MC_WS_LEN (sizeof(MC_WS)-1)
42
43#define MC_GET "get "
44#define MC_GET_LEN (sizeof(MC_GET)-1)
45
46#define MC_SET "set "
47#define MC_SET_LEN (sizeof(MC_SET)-1)
48
49#define MC_ADD "add "
50#define MC_ADD_LEN (sizeof(MC_ADD)-1)
51
52#define MC_REPLACE "replace "
53#define MC_REPLACE_LEN (sizeof(MC_REPLACE)-1)
54
55#define MC_DELETE "delete "
56#define MC_DELETE_LEN (sizeof(MC_DELETE)-1)
57
58#define MC_INCR "incr "
59#define MC_INCR_LEN (sizeof(MC_INCR)-1)
60
61#define MC_DECR "decr "
62#define MC_DECR_LEN (sizeof(MC_DECR)-1)
63
64#define MC_VERSION "version"
65#define MC_VERSION_LEN (sizeof(MC_VERSION)-1)
66
67#define MC_STATS "stats"
68#define MC_STATS_LEN (sizeof(MC_STATS)-1)
69
70#define MC_QUIT "quit"
71#define MC_QUIT_LEN (sizeof(MC_QUIT)-1)
72
73/* Strings for Server Replies */
74
75#define MS_STORED "STORED"
76#define MS_STORED_LEN (sizeof(MS_STORED)-1)
77
78#define MS_NOT_STORED "NOT_STORED"
79#define MS_NOT_STORED_LEN (sizeof(MS_NOT_STORED)-1)
80
81#define MS_DELETED "DELETED"
82#define MS_DELETED_LEN (sizeof(MS_DELETED)-1)
83
84#define MS_NOT_FOUND "NOT_FOUND"
85#define MS_NOT_FOUND_LEN (sizeof(MS_NOT_FOUND)-1)
86
87#define MS_VALUE "VALUE"
88#define MS_VALUE_LEN (sizeof(MS_VALUE)-1)
89
90#define MS_ERROR "ERROR"
91#define MS_ERROR_LEN (sizeof(MS_ERROR)-1)
92
93#define MS_VERSION "VERSION"
94#define MS_VERSION_LEN (sizeof(MS_VERSION)-1)
95
96#define MS_STAT "STAT"
97#define MS_STAT_LEN (sizeof(MS_STAT)-1)
98
99#define MS_END "END"
100#define MS_END_LEN (sizeof(MS_END)-1)
101
109
110#define MULT_GET_TIMEOUT 50000
111
113{
114#if APR_HAS_THREADS
116#endif
118 ms->btime = apr_time_now();
119#if APR_HAS_THREADS
121#endif
122 return APR_SUCCESS;
123}
124
130
131
133{
135
136 if(mc->ntotal >= mc->nalloc) {
137 return APR_ENOMEM;
138 }
139
141 mc->ntotal++;
143 return rv;
144}
145
147
158
162{
164 apr_uint32_t h = hash ? hash : 1;
165 apr_uint32_t i = 0;
167
168 if(mc->ntotal == 0) {
169 return NULL;
170 }
171
172 do {
173 ms = mc->live_servers[h % mc->ntotal];
175 break;
176 }
177 else {
178 if (curtime == 0) {
180 }
181#if APR_HAS_THREADS
183#endif
184 /* Try the dead server, every 5 seconds */
185 if (curtime - ms->btime > apr_time_from_sec(5)) {
186 ms->btime = curtime;
189#if APR_HAS_THREADS
191#endif
192 break;
193 }
194 }
195#if APR_HAS_THREADS
197#endif
198 }
199 h++;
200 i++;
201 } while(i < mc->ntotal);
202
203 if (i == mc->ntotal) {
204 ms = NULL;
205 }
206
207 return ms;
208}
209
211{
212 int i;
213
214 for (i = 0; i < mc->ntotal; i++) {
215 if (strcmp(mc->live_servers[i]->host, host) == 0
216 && mc->live_servers[i]->port == port) {
217
218 return mc->live_servers[i];
219 }
220 }
221
222 return NULL;
223}
224
226{
227 apr_status_t rv;
229 apr_bucket *e;
230
231#if APR_HAS_THREADS
232 rv = apr_reslist_acquire(ms->conns, (void **)conn);
233#else
234 *conn = ms->conn;
235 rv = APR_SUCCESS;
236#endif
237
238 if (rv != APR_SUCCESS) {
239 return rv;
240 }
241
242 balloc = apr_bucket_alloc_create((*conn)->tp);
243 (*conn)->bb = apr_brigade_create((*conn)->tp, balloc);
244 (*conn)->tb = apr_brigade_create((*conn)->tp, balloc);
245
246 e = apr_bucket_socket_create((*conn)->sock, balloc);
247 APR_BRIGADE_INSERT_TAIL((*conn)->bb, e);
248
249 return rv;
250}
251
253{
254#if APR_HAS_THREADS
255 return apr_reslist_invalidate(ms->conns, conn);
256#else
257 return APR_SUCCESS;
258#endif
259}
260
262{
263 apr_pool_clear(conn->tp);
264#if APR_HAS_THREADS
265 return apr_reslist_release(ms->conns, conn);
266#else
267 return APR_SUCCESS;
268#endif
269}
270
272{
274
275 if (ms->status == APR_MC_SERVER_LIVE) {
276 return rv;
277 }
278
279 rv = make_server_live(mc, ms);
280 return rv;
281}
282
284{
285 return make_server_dead(mc, ms);
286}
287
289{
292#if APR_HAVE_SOCKADDR_UN
293 apr_int32_t family = conn->ms->host[0] != '/' ? APR_INET : APR_UNIX;
294#else
296#endif
297
298 rv = apr_sockaddr_info_get(&sa, conn->ms->host, family, conn->ms->port, 0, conn->p);
299 if (rv != APR_SUCCESS) {
300 return rv;
301 }
302
304 if (rv != APR_SUCCESS) {
305 return rv;
306 }
307
308 rv = apr_socket_connect(conn->sock, sa);
309 if (rv != APR_SUCCESS) {
310 return rv;
311 }
312
313 rv = apr_socket_timeout_set(conn->sock, -1);
314 if (rv != APR_SUCCESS) {
315 return rv;
316 }
317
318 return rv;
319}
320
321
322static apr_status_t
324{
327 apr_pool_t *np;
328 apr_pool_t *tp;
330#if APR_HAVE_SOCKADDR_UN
331 apr_int32_t family = ms->host[0] != '/' ? APR_INET : APR_UNIX;
332#else
334#endif
335
336 rv = apr_pool_create(&np, pool);
337 if (rv != APR_SUCCESS) {
338 return rv;
339 }
340
341 rv = apr_pool_create(&tp, np);
342 if (rv != APR_SUCCESS) {
344 return rv;
345 }
346
347 conn = apr_palloc(np, sizeof( apr_memcache_conn_t ));
348
349 conn->p = np;
350 conn->tp = tp;
351
352 rv = apr_socket_create(&conn->sock, family, SOCK_STREAM, 0, np);
353
354 if (rv != APR_SUCCESS) {
356 return rv;
357 }
358
359 conn->buffer = apr_palloc(conn->p, BUFFER_SIZE + 1);
360 conn->blen = 0;
361 conn->ms = ms;
362
363 rv = conn_connect(conn);
364 if (rv != APR_SUCCESS) {
366 }
367 else {
368 *conn_ = conn;
369 }
370
371 return rv;
372}
373
374#if APR_HAS_THREADS
375static apr_status_t
377{
379 struct iovec vec[2];
380 apr_size_t written;
381
382 /* send a quit message to the memcached server to be nice about it. */
383 vec[0].iov_base = MC_QUIT;
384 vec[0].iov_len = MC_QUIT_LEN;
385
386 vec[1].iov_base = MC_EOL;
387 vec[1].iov_len = MC_EOL_LEN;
388
389 /* Return values not checked, since we just want to make it go away. */
390 apr_socket_sendv(conn->sock, vec, 2, &written);
391 apr_socket_close(conn->sock);
392
393 apr_pool_destroy(conn->p);
394
395 return APR_SUCCESS;
396}
397#endif
398
400 const char *host, apr_port_t port,
404{
407 apr_pool_t *np;
408
409 rv = apr_pool_create(&np, p);
410
412
413 server->p = np;
415 server->port = port;
417#if APR_HAS_THREADS
419 if (rv != APR_SUCCESS) {
420 return rv;
421 }
422
423 rv = apr_reslist_create(&server->conns,
424 min, /* hard minimum */
425 smax, /* soft maximum */
426 max, /* hard maximum */
427 ttl, /* Time to live */
428 mc_conn_construct, /* Make a New Connection */
429 mc_conn_destruct, /* Kill Old Connection */
430 server, np);
431 if (rv != APR_SUCCESS) {
432 return rv;
433 }
434
436#else
437 rv = mc_conn_construct((void**)&(server->conn), server, np);
438 if (rv != APR_SUCCESS) {
439 return rv;
440 }
441#endif
442
443 *ms = server;
444
445 return rv;
446}
447
451{
454
455 mc = apr_palloc(p, sizeof(apr_memcache_t));
456 mc->p = p;
458 mc->ntotal = 0;
459 mc->live_servers = apr_palloc(p, mc->nalloc * sizeof(struct apr_memcache_server_t *));
460 mc->hash_func = NULL;
461 mc->hash_baton = NULL;
464 *memcache = mc;
465 return rv;
466}
467
468
469/* The crc32 functions and data was originally written by Spencer
470 * Garrett <[email protected]> and was gleaned from the PostgreSQL source
471 * tree via the files contrib/ltree/crc32.[ch] and from FreeBSD at
472 * src/usr.bin/cksum/crc32.c.
473 */
474
475static const apr_uint32_t crc32tab[256] = {
476 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
477 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
478 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
479 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
480 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
481 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
482 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
483 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
484 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
485 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
486 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
487 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
488 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
489 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
490 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
491 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
492 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
493 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
494 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
495 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
496 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
497 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
498 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
499 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
500 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
501 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
502 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
503 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
504 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
505 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
506 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
507 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
508 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
509 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
510 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
511 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
512 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
513 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
514 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
515 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
516 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
517 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
518 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
519 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
520 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
521 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
522 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
523 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
524 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
525 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
526 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
527 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
528 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
529 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
530 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
531 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
532 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
533 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
534 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
535 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
536 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
537 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
538 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
539 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
540};
541
543 const char *data,
544 const apr_size_t data_len)
545{
547 apr_uint32_t crc;
548 crc = ~0;
549
550 for (i = 0; i < data_len; i++)
551 crc = (crc >> 8) ^ crc32tab[(crc ^ (data[i])) & 0xff];
552
553 return ~crc;
554}
555
557 const char *data,
558 const apr_size_t data_len)
559{
560 /* The default Perl Client doesn't actually use just crc32 -- it shifts it again
561 * like this....
562 */
563 return ((apr_memcache_hash_crc32(baton, data, data_len) >> 16) & 0x7fff);
564}
565
567 const char *data,
568 const apr_size_t data_len)
569{
570 if (mc->hash_func) {
572 }
573 else {
575 }
576}
577
579{
582
584
585 if (rv != APR_SUCCESS) {
586 return rv;
587 }
588
589 rv = apr_brigade_flatten(conn->tb, conn->buffer, &bsize);
590
591 if (rv != APR_SUCCESS) {
592 return rv;
593 }
594
595 conn->blen = bsize;
596 conn->buffer[bsize] = '\0';
597
598 return apr_brigade_cleanup(conn->tb);
599}
600
602 char *cmd,
603 const apr_size_t cmd_size,
604 const char *key,
605 char *data,
606 const apr_size_t data_size,
609{
613 apr_status_t rv;
614 apr_size_t written;
615 struct iovec vec[5];
617
618 apr_size_t key_size = strlen(key);
619
621
623
624 if (ms == NULL)
625 return APR_NOTFOUND;
626
627 rv = ms_find_conn(ms, &conn);
628
629 if (rv != APR_SUCCESS) {
631 return rv;
632 }
633
634 /* <command name> <key> <flags> <exptime> <bytes>\r\n<data>\r\n */
635
636 vec[0].iov_base = cmd;
637 vec[0].iov_len = cmd_size;
638
639 vec[1].iov_base = (void*)key;
640 vec[1].iov_len = key_size;
641
642 klen = apr_snprintf(conn->buffer, BUFFER_SIZE, " %u %u %" APR_SIZE_T_FMT " " MC_EOL,
644
645 vec[2].iov_base = conn->buffer;
646 vec[2].iov_len = klen;
647
648 vec[3].iov_base = data;
649 vec[3].iov_len = data_size;
650
651 vec[4].iov_base = MC_EOL;
652 vec[4].iov_len = MC_EOL_LEN;
653
654 rv = apr_socket_sendv(conn->sock, vec, 5, &written);
655
656 if (rv != APR_SUCCESS) {
657 ms_bad_conn(ms, conn);
659 return rv;
660 }
661
662 rv = get_server_line(conn);
663
664 if (rv != APR_SUCCESS) {
665 ms_bad_conn(ms, conn);
667 return rv;
668 }
669
670 if (strcmp(conn->buffer, MS_STORED MC_EOL) == 0) {
671 rv = APR_SUCCESS;
672 }
673 else if (strcmp(conn->buffer, MS_NOT_STORED MC_EOL) == 0) {
674 rv = APR_EEXIST;
675 }
676 else {
677 rv = APR_EGENERAL;
678 }
679
680 ms_release_conn(ms, conn);
681
682 return rv;
683}
684
699
714
730
731/*
732 * Parses a decimal size from size_str, returning the value in *size.
733 * Returns 1 if parsing was successful, 0 if parsing failed.
734 */
735static int parse_size(const char *size_str, apr_size_t *size)
736{
737 char *endptr;
738 long size_as_long;
739
740 errno = 0;
742 if ((size_as_long < 0) || (errno != 0) || (endptr == size_str) ||
743 (endptr[0] != ' ' && (endptr[0] != '\r' || endptr[1] != '\n'))) {
744 return 0;
745 }
746
747 *size = (unsigned long)size_as_long;
748 return 1;
749}
750
753 apr_pool_t *p,
754 const char *key,
755 char **baton,
758{
759 apr_status_t rv;
763 apr_size_t written;
764 apr_size_t klen = strlen(key);
765 struct iovec vec[3];
766
769 if (ms == NULL)
770 return APR_NOTFOUND;
771
772 rv = ms_find_conn(ms, &conn);
773
774 if (rv != APR_SUCCESS) {
776 return rv;
777 }
778
779 /* get <key>[ <key>[...]]\r\n */
780 vec[0].iov_base = MC_GET;
781 vec[0].iov_len = MC_GET_LEN;
782
783 vec[1].iov_base = (void*)key;
784 vec[1].iov_len = klen;
785
786 vec[2].iov_base = MC_EOL;
787 vec[2].iov_len = MC_EOL_LEN;
788
789 rv = apr_socket_sendv(conn->sock, vec, 3, &written);
790
791 if (rv != APR_SUCCESS) {
792 ms_bad_conn(ms, conn);
794 return rv;
795 }
796
797 rv = get_server_line(conn);
798 if (rv != APR_SUCCESS) {
799 ms_bad_conn(ms, conn);
801 return rv;
802 }
803
804 if (strncmp(MS_VALUE, conn->buffer, MS_VALUE_LEN) == 0) {
805 char *flags;
806 char *length;
807 char *last;
808 apr_size_t len = 0;
809
810 flags = apr_strtok(conn->buffer, " ", &last);
811 flags = apr_strtok(NULL, " ", &last);
812 flags = apr_strtok(NULL, " ", &last);
813
814 if (flags_) {
815 *flags_ = atoi(flags);
816 }
817
818 length = apr_strtok(NULL, " ", &last);
819 if (!length || !parse_size(length, &len)) {
820 ms_bad_conn(ms, conn);
822 return APR_EGENERAL;
823 }
824 else {
826 apr_bucket *e;
827
828 /* eat the trailing \r\n */
829 rv = apr_brigade_partition(conn->bb, len+2, &e);
830 if (rv != APR_SUCCESS) {
831 ms_bad_conn(ms, conn);
833 return rv;
834 }
835
836 bbb = apr_brigade_split(conn->bb, e);
837
838 rv = apr_brigade_pflatten(conn->bb, baton, &len, p);
839 if (rv != APR_SUCCESS) {
840 ms_bad_conn(ms, conn);
841 return rv;
842 }
843
844 rv = apr_brigade_destroy(conn->bb);
845 if (rv != APR_SUCCESS) {
846 ms_bad_conn(ms, conn);
847 return rv;
848 }
849
850 conn->bb = bbb;
851
852 *new_length = len - 2;
853 (*baton)[*new_length] = '\0';
854 }
855
856 rv = get_server_line(conn);
857 if (rv != APR_SUCCESS) {
858 ms_bad_conn(ms, conn);
860 return rv;
861 }
862
863 if (strncmp(MS_END, conn->buffer, MS_END_LEN) != 0) {
864 ms_bad_conn(ms, conn);
866 return APR_EGENERAL;
867 }
868 }
869 else if (strncmp(MS_END, conn->buffer, MS_END_LEN) == 0) {
870 rv = APR_NOTFOUND;
871 }
872 else {
873 ms_bad_conn(ms, conn);
875 return APR_EGENERAL;
876 }
877
878 ms_release_conn(ms, conn);
879
880 return rv;
881}
882
885 const char *key,
887{
888 apr_status_t rv;
892 apr_size_t written;
893 struct iovec vec[3];
894 apr_size_t klen = strlen(key);
895
898 if (ms == NULL)
899 return APR_NOTFOUND;
900
901 rv = ms_find_conn(ms, &conn);
902
903 if (rv != APR_SUCCESS) {
905 return rv;
906 }
907
908 /* delete <key> <time>\r\n */
909 vec[0].iov_base = MC_DELETE;
910 vec[0].iov_len = MC_DELETE_LEN;
911
912 vec[1].iov_base = (void*)key;
913 vec[1].iov_len = klen;
914
916
917 vec[2].iov_base = conn->buffer;
918 vec[2].iov_len = klen;
919
920 rv = apr_socket_sendv(conn->sock, vec, 3, &written);
921
922 if (rv != APR_SUCCESS) {
923 ms_bad_conn(ms, conn);
925 return rv;
926 }
927
928 rv = get_server_line(conn);
929 if (rv != APR_SUCCESS) {
930 ms_bad_conn(ms, conn);
932 return rv;
933 }
934
935 if (strncmp(MS_DELETED, conn->buffer, MS_DELETED_LEN) == 0) {
936 rv = APR_SUCCESS;
937 }
938 else if (strncmp(MS_NOT_FOUND, conn->buffer, MS_NOT_FOUND_LEN) == 0) {
939 rv = APR_NOTFOUND;
940 }
941 else {
942 rv = APR_EGENERAL;
943 }
944
945 ms_release_conn(ms, conn);
946
947 return rv;
948}
949
951 char *cmd,
953 const char *key,
954 const apr_int32_t inc,
956{
957 apr_status_t rv;
961 apr_size_t written;
962 struct iovec vec[3];
963 apr_size_t klen = strlen(key);
964
967 if (ms == NULL)
968 return APR_NOTFOUND;
969
970 rv = ms_find_conn(ms, &conn);
971
972 if (rv != APR_SUCCESS) {
974 return rv;
975 }
976
977 /* <cmd> <key> <value>\r\n */
978 vec[0].iov_base = cmd;
979 vec[0].iov_len = cmd_size;
980
981 vec[1].iov_base = (void*)key;
982 vec[1].iov_len = klen;
983
984 klen = apr_snprintf(conn->buffer, BUFFER_SIZE, " %u" MC_EOL, inc);
985
986 vec[2].iov_base = conn->buffer;
987 vec[2].iov_len = klen;
988
989 rv = apr_socket_sendv(conn->sock, vec, 3, &written);
990
991 if (rv != APR_SUCCESS) {
992 ms_bad_conn(ms, conn);
994 return rv;
995 }
996
997 rv = get_server_line(conn);
998 if (rv != APR_SUCCESS) {
999 ms_bad_conn(ms, conn);
1001 return rv;
1002 }
1003
1004 if (strncmp(MS_ERROR, conn->buffer, MS_ERROR_LEN) == 0) {
1005 rv = APR_EGENERAL;
1006 }
1007 else if (strncmp(MS_NOT_FOUND, conn->buffer, MS_NOT_FOUND_LEN) == 0) {
1008 rv = APR_NOTFOUND;
1009 }
1010 else {
1011 if (new_value) {
1012 *new_value = atoi(conn->buffer);
1013 }
1014 rv = APR_SUCCESS;
1015 }
1016
1017 ms_release_conn(ms, conn);
1018
1019 return rv;
1020}
1021
1024 const char *key,
1027{
1028 return num_cmd_write(mc,
1029 MC_INCR,
1031 key,
1032 inc,
1033 new_value);
1034}
1035
1036
1039 const char *key,
1042{
1043 return num_cmd_write(mc,
1044 MC_DECR,
1046 key,
1047 inc,
1048 new_value);
1049}
1050
1051
1052
1055 apr_pool_t *p,
1056 char **baton)
1057{
1058 apr_status_t rv;
1059 apr_memcache_conn_t *conn;
1060 apr_size_t written;
1061 struct iovec vec[2];
1062
1063 rv = ms_find_conn(ms, &conn);
1064
1065 if (rv != APR_SUCCESS) {
1066 return rv;
1067 }
1068
1069 /* version\r\n */
1070 vec[0].iov_base = MC_VERSION;
1071 vec[0].iov_len = MC_VERSION_LEN;
1072
1073 vec[1].iov_base = MC_EOL;
1074 vec[1].iov_len = MC_EOL_LEN;
1075
1076 rv = apr_socket_sendv(conn->sock, vec, 2, &written);
1077
1078 if (rv != APR_SUCCESS) {
1079 ms_bad_conn(ms, conn);
1080 return rv;
1081 }
1082
1083 rv = get_server_line(conn);
1084 if (rv != APR_SUCCESS) {
1085 ms_bad_conn(ms, conn);
1086 return rv;
1087 }
1088
1089 if (strncmp(MS_VERSION, conn->buffer, MS_VERSION_LEN) == 0) {
1091 conn->blen - MS_VERSION_LEN - 2);
1092 rv = APR_SUCCESS;
1093 }
1094 else {
1095 rv = APR_EGENERAL;
1096 }
1097
1098 ms_release_conn(ms, conn);
1099
1100 return rv;
1101}
1102
1104{
1105 apr_status_t rv;
1106 apr_size_t written;
1107 struct iovec vec[2];
1108 apr_memcache_conn_t *conn;
1109
1110 rv = ms_find_conn(ms, &conn);
1111
1112 if (rv != APR_SUCCESS) {
1113 return rv;
1114 }
1115
1116 /* version\r\n */
1117 vec[0].iov_base = MC_VERSION;
1118 vec[0].iov_len = MC_VERSION_LEN;
1119
1120 vec[1].iov_base = MC_EOL;
1121 vec[1].iov_len = MC_EOL_LEN;
1122
1123 rv = apr_socket_sendv(conn->sock, vec, 2, &written);
1124
1125 if (rv != APR_SUCCESS) {
1126 ms_bad_conn(ms, conn);
1127 return rv;
1128 }
1129
1130 rv = get_server_line(conn);
1131 ms_release_conn(ms, conn);
1132 return rv;
1133}
1134
1135
1136APU_DECLARE(void)
1138 const char* key,
1140{
1142 apr_size_t klen = strlen(key);
1143
1144 /* create the value hash if need be */
1145 if (!*values) {
1147 }
1148
1149 /* init key and add it to the value hash */
1151
1152 value->status = APR_NOTFOUND;
1153 value->key = apr_pstrdup(data_pool, key);
1154
1156}
1157
1159 int connup,
1160 apr_status_t rv,
1163 apr_memcache_conn_t *conn,
1167{
1168 apr_int32_t j;
1170
1171 apr_hash_set(server_queries, &ms, sizeof(ms), NULL);
1172
1173 if (connup) {
1174 ms_release_conn(ms, conn);
1175 } else {
1176 ms_bad_conn(ms, conn);
1177
1178 if (!serverup) {
1180 }
1181 }
1182
1183 for (j = 1; j < server_query->query_vec_count ; j+=2) {
1184 if (server_query->query_vec[j].iov_base) {
1185 value = apr_hash_get(values, server_query->query_vec[j].iov_base,
1186 strlen(server_query->query_vec[j].iov_base));
1187
1188 if (value->status == APR_NOTFOUND) {
1189 value->status = rv;
1190 }
1191 }
1192 }
1193}
1194
1200{
1201 apr_status_t rv;
1203 apr_memcache_conn_t* conn;
1205 apr_size_t written;
1207
1210
1211 /* this is a little over aggresive, but beats multiple loops
1212 * to figure out how long each vector needs to be per-server.
1213 */
1214 apr_int32_t veclen = 2 + 2 * apr_hash_count(values) - 1; /* get <key>[<space><key>...]\r\n */
1215 apr_int32_t i, j;
1218
1222
1224 const apr_pollfd_t* activefds;
1226
1227
1228 /* build all the queries */
1230 while (value_hash_index) {
1231 void *v;
1233 value = v;
1235 klen = strlen(value->key);
1236
1239 if (ms == NULL) {
1240 continue;
1241 }
1242
1244
1245 if (!server_query) {
1246 rv = ms_find_conn(ms, &conn);
1247
1248 if (rv != APR_SUCCESS) {
1250 value->status = rv;
1251 continue;
1252 }
1253
1255
1257
1258 server_query->ms = ms;
1260 server_query->query_vec = apr_pcalloc(temp_pool, sizeof(struct iovec)*veclen);
1261
1262 /* set up the first key */
1263 server_query->query_vec[0].iov_base = MC_GET;
1264 server_query->query_vec[0].iov_len = MC_GET_LEN;
1265
1266 server_query->query_vec[1].iov_base = (void*)(value->key);
1267 server_query->query_vec[1].iov_len = klen;
1268
1269 server_query->query_vec[2].iov_base = MC_EOL;
1270 server_query->query_vec[2].iov_len = MC_EOL_LEN;
1271
1272 server_query->query_vec_count = 3;
1273 }
1274 else {
1275 j = server_query->query_vec_count - 1;
1276
1277 server_query->query_vec[j].iov_base = MC_WS;
1278 server_query->query_vec[j].iov_len = MC_WS_LEN;
1279 j++;
1280
1281 server_query->query_vec[j].iov_base = (void*)(value->key);
1282 server_query->query_vec[j].iov_len = klen;
1283 j++;
1284
1285 server_query->query_vec[j].iov_base = MC_EOL;
1286 server_query->query_vec[j].iov_len = MC_EOL_LEN;
1287 j++;
1288
1289 server_query->query_vec_count = j;
1290 }
1291 }
1292
1293 /* create polling structures */
1295
1297
1298 if (rv != APR_SUCCESS) {
1300
1301 while (query_hash_index) {
1302 void *v;
1304 server_query = v;
1306
1309 }
1310
1311 return rv;
1312 }
1313
1314 /* send all the queries */
1315 queries_sent = 0;
1317
1318 while (query_hash_index) {
1319 void *v;
1321 server_query = v;
1323
1324 conn = server_query->conn;
1325 ms = server_query->ms;
1326
1327 for (i = 0, rv = APR_SUCCESS; i < veclen && rv == APR_SUCCESS; i += APR_MAX_IOVEC_SIZE) {
1328 rv = apr_socket_sendv(conn->sock, &(server_query->query_vec[i]),
1330 }
1331
1332 if (rv != APR_SUCCESS) {
1335 continue;
1336 }
1337
1339 pollfds[queries_sent].reqevents = APR_POLLIN;
1341 pollfds[queries_sent].desc.s = conn->sock;
1342 pollfds[queries_sent].client_data = (void *)server_query;
1344
1345 queries_sent++;
1346 }
1347
1348 while (queries_sent) {
1350
1351 if (rv != APR_SUCCESS) {
1352 /* timeout */
1353 queries_sent = 0;
1354 continue;
1355 }
1356 for (i = 0; i < queries_recvd; i++) {
1357 server_query = activefds[i].client_data;
1358 conn = server_query->conn;
1359 ms = server_query->ms;
1360
1361 rv = get_server_line(conn);
1362
1363 if (rv != APR_SUCCESS) {
1367 queries_sent--;
1368 continue;
1369 }
1370
1371 if (strncmp(MS_VALUE, conn->buffer, MS_VALUE_LEN) == 0) {
1372 char *key;
1373 char *flags;
1374 char *length;
1375 char *last;
1376 char *data;
1377 apr_size_t len = 0;
1378 apr_bucket *e = NULL;
1379
1380 key = apr_strtok(conn->buffer, " ", &last); /* just the VALUE, ignore */
1381 key = apr_strtok(NULL, " ", &last);
1382 flags = apr_strtok(NULL, " ", &last);
1383 length = apr_strtok(NULL, " ", &last);
1384
1385 if (!length || !parse_size(length, &len)) {
1386 rv = APR_EGENERAL;
1387 }
1388 else {
1389 /* eat the trailing \r\n */
1390 rv = apr_brigade_partition(conn->bb, len+2, &e);
1391 }
1392 if (rv != APR_SUCCESS) {
1396 queries_sent--;
1397 continue;
1398 }
1399
1400 value = apr_hash_get(values, key, strlen(key));
1401 if (value) {
1403
1405
1407 if (rv != APR_SUCCESS) {
1411 queries_sent--;
1412 continue;
1413 }
1414
1416 if (rv != APR_SUCCESS) {
1420 queries_sent--;
1421 continue;
1422 }
1423
1424 conn->bb = bbb;
1425
1426 value->len = len - 2;
1427 data[value->len] = '\0';
1428 value->data = data;
1429
1430 value->status = rv;
1431 value->flags = atoi(flags);
1432
1433 /* stay on the server */
1434 i--;
1435 }
1436 else {
1437 /* Server Sent back a key I didn't ask for or my
1438 * hash is corrupt */
1439 rv = APR_EGENERAL;
1440 }
1441 }
1442 else if (strncmp(MS_END, conn->buffer, MS_END_LEN) == 0) {
1443 /* this connection is done */
1446 apr_hash_set(server_queries, &ms, sizeof(ms), NULL);
1447 queries_sent--;
1448 }
1449 else {
1450 /* unknown reply? */
1451 rv = APR_EGENERAL;
1452 }
1453 if (rv != APR_SUCCESS) {
1457 queries_sent--;
1458 }
1459 } /* /for */
1460 } /* /while */
1461
1463 while (query_hash_index) {
1464 void *v;
1466 server_query = v;
1468
1469 conn = server_query->conn;
1470 ms = server_query->ms;
1471
1472 mget_conn_result(TRUE, (rv == APR_SUCCESS), rv, mc, ms, conn,
1474 continue;
1475 }
1476
1479 return APR_SUCCESS;
1480
1481}
1482
1483
1484
1489#define STAT_pid MS_STAT " pid "
1490#define STAT_pid_LEN (sizeof(STAT_pid)-1)
1491
1492#define STAT_uptime MS_STAT " uptime "
1493#define STAT_uptime_LEN (sizeof(STAT_uptime)-1)
1494
1495#define STAT_time MS_STAT " time "
1496#define STAT_time_LEN (sizeof(STAT_time)-1)
1497
1498#define STAT_version MS_STAT " version "
1499#define STAT_version_LEN (sizeof(STAT_version)-1)
1500
1501#define STAT_pointer_size MS_STAT " pointer_size "
1502#define STAT_pointer_size_LEN (sizeof(STAT_pointer_size)-1)
1503
1504#define STAT_rusage_user MS_STAT " rusage_user "
1505#define STAT_rusage_user_LEN (sizeof(STAT_rusage_user)-1)
1506
1507#define STAT_rusage_system MS_STAT " rusage_system "
1508#define STAT_rusage_system_LEN (sizeof(STAT_rusage_system)-1)
1509
1510#define STAT_curr_items MS_STAT " curr_items "
1511#define STAT_curr_items_LEN (sizeof(STAT_curr_items)-1)
1512
1513#define STAT_total_items MS_STAT " total_items "
1514#define STAT_total_items_LEN (sizeof(STAT_total_items)-1)
1515
1516#define STAT_bytes MS_STAT " bytes "
1517#define STAT_bytes_LEN (sizeof(STAT_bytes)-1)
1518
1519#define STAT_curr_connections MS_STAT " curr_connections "
1520#define STAT_curr_connections_LEN (sizeof(STAT_curr_connections)-1)
1521
1522#define STAT_total_connections MS_STAT " total_connections "
1523#define STAT_total_connections_LEN (sizeof(STAT_total_connections)-1)
1524
1525#define STAT_connection_structures MS_STAT " connection_structures "
1526#define STAT_connection_structures_LEN (sizeof(STAT_connection_structures)-1)
1527
1528#define STAT_cmd_get MS_STAT " cmd_get "
1529#define STAT_cmd_get_LEN (sizeof(STAT_cmd_get)-1)
1530
1531#define STAT_cmd_set MS_STAT " cmd_set "
1532#define STAT_cmd_set_LEN (sizeof(STAT_cmd_set)-1)
1533
1534#define STAT_get_hits MS_STAT " get_hits "
1535#define STAT_get_hits_LEN (sizeof(STAT_get_hits)-1)
1536
1537#define STAT_get_misses MS_STAT " get_misses "
1538#define STAT_get_misses_LEN (sizeof(STAT_get_misses)-1)
1539
1540#define STAT_evictions MS_STAT " evictions "
1541#define STAT_evictions_LEN (sizeof(STAT_evictions)-1)
1542
1543#define STAT_bytes_read MS_STAT " bytes_read "
1544#define STAT_bytes_read_LEN (sizeof(STAT_bytes_read)-1)
1545
1546#define STAT_bytes_written MS_STAT " bytes_written "
1547#define STAT_bytes_written_LEN (sizeof(STAT_bytes_written)-1)
1548
1549#define STAT_limit_maxbytes MS_STAT " limit_maxbytes "
1550#define STAT_limit_maxbytes_LEN (sizeof(STAT_limit_maxbytes)-1)
1551
1552#define STAT_threads MS_STAT " threads "
1553#define STAT_threads_LEN (sizeof(STAT_threads)-1)
1554
1555static const char *stat_read_string(apr_pool_t *p, char *buf, apr_size_t len)
1556{
1557 /* remove trailing \r\n and null char */
1558 return apr_pstrmemdup(p, buf, len-2);
1559}
1560
1562{
1563 buf[len-2] = '\0';
1564 return atoi(buf);
1565}
1566
1568{
1569 buf[len-2] = '\0';
1570 return apr_atoi64(buf);
1571}
1572
1574{
1575 buf[len-2] = '\0';
1576 return apr_time_from_sec(atoi(buf));
1577}
1578
1580{
1581 char *tok;
1582 char *secs;
1583 char *usecs;
1584 const char *sep = ":.";
1585
1586 buf[len-2] = '\0';
1587
1588 secs = apr_strtok(buf, sep, &tok);
1589 usecs = apr_strtok(NULL, sep, &tok);
1590 if (secs && usecs) {
1591 return apr_time_make(atoi(secs), atoi(usecs));
1592 }
1593 else {
1594 return apr_time_make(0, 0);
1595 }
1596}
1597
1604#define mc_stat_cmp(name) \
1605 strncmp(STAT_ ## name, conn->buffer, STAT_ ## name ## _LEN) == 0
1606
1607#define mc_stat_str(name) \
1608 stat_read_string(p, conn->buffer + name, \
1609 conn->blen - name)
1610
1611#define mc_stat_uint32(name) \
1612 stat_read_uint32(p, conn->buffer + name, \
1613 conn->blen - name)
1614
1615#define mc_stat_uint64(name) \
1616 stat_read_uint64(p, conn->buffer + name, \
1617 conn->blen - name)
1618
1619#define mc_stat_time(name) \
1620 stat_read_time(p, conn->buffer + name, \
1621 conn->blen - name)
1622
1623#define mc_stat_rtime(name) \
1624 stat_read_rtime(p, conn->buffer + name, \
1625 conn->blen - name)
1626
1627
1628#define mc_do_stat(name, type) \
1629 if (mc_stat_cmp(name)) { \
1630 stats-> name = mc_stat_ ## type ((STAT_ ## name ## _LEN)); \
1631 }
1632
1635{
1636
1637 mc_do_stat(version, str)
1638 else mc_do_stat(pid, uint32)
1639 else mc_do_stat(uptime, uint32)
1640 else mc_do_stat(pointer_size, uint32)
1641 else mc_do_stat(time, time)
1642 else mc_do_stat(rusage_user, rtime)
1643 else mc_do_stat(rusage_system, rtime)
1644 else mc_do_stat(curr_items, uint32)
1645 else mc_do_stat(total_items, uint32)
1646 else mc_do_stat(bytes, uint64)
1647 else mc_do_stat(curr_connections, uint32)
1648 else mc_do_stat(total_connections, uint32)
1649 else mc_do_stat(connection_structures, uint32)
1650 else mc_do_stat(cmd_get, uint32)
1651 else mc_do_stat(cmd_set, uint32)
1652 else mc_do_stat(get_hits, uint32)
1653 else mc_do_stat(get_misses, uint32)
1654 else mc_do_stat(evictions, uint64)
1657 else mc_do_stat(limit_maxbytes, uint32)
1658 else mc_do_stat(threads, uint32)
1659}
1660
1663 apr_pool_t *p,
1665{
1667 apr_status_t rv;
1669 apr_size_t written;
1670 struct iovec vec[2];
1671
1672 rv = ms_find_conn(ms, &conn);
1673
1674 if (rv != APR_SUCCESS) {
1675 return rv;
1676 }
1677
1678 /* version\r\n */
1679 vec[0].iov_base = MC_STATS;
1680 vec[0].iov_len = MC_STATS_LEN;
1681
1682 vec[1].iov_base = MC_EOL;
1683 vec[1].iov_len = MC_EOL_LEN;
1684
1685 rv = apr_socket_sendv(conn->sock, vec, 2, &written);
1686
1687 if (rv != APR_SUCCESS) {
1688 ms_bad_conn(ms, conn);
1689 return rv;
1690 }
1691
1693
1694 do {
1695 rv = get_server_line(conn);
1696 if (rv != APR_SUCCESS) {
1697 ms_bad_conn(ms, conn);
1698 return rv;
1699 }
1700
1701 if (strncmp(MS_END, conn->buffer, MS_END_LEN) == 0) {
1702 rv = APR_SUCCESS;
1703 break;
1704 }
1705 else if (strncmp(MS_STAT, conn->buffer, MS_STAT_LEN) == 0) {
1706 update_stats(p, conn, ret);
1707 continue;
1708 }
1709 else {
1710 rv = APR_EGENERAL;
1711 break;
1712 }
1713
1714 } while(1);
1715
1716 ms_release_conn(ms, conn);
1717
1718 if (stats) {
1719 *stats = ret;
1720 }
1721
1722 return rv;
1723}
1724
const char apr_size_t len
Definition ap_regex.h:187
#define TRUE
Definition abts.h:38
#define FALSE
Definition abts.h:35
#define MC_QUIT
static apr_status_t num_cmd_write(apr_memcache_t *mc, char *cmd, const apr_uint32_t cmd_size, const char *key, const apr_int32_t inc, apr_uint32_t *new_value)
#define MS_END_LEN
apr_memcache_version(apr_memcache_server_t *ms, apr_pool_t *p, char **baton)
#define MC_INCR_LEN
#define MS_DELETED
#define MC_WS_LEN
apr_memcache_multgetp(apr_memcache_t *mc, apr_pool_t *temp_pool, apr_pool_t *data_pool, apr_hash_t *values)
#define MS_DELETED_LEN
#define MS_VERSION
static apr_status_t make_server_dead(apr_memcache_t *mc, apr_memcache_server_t *ms)
#define MC_GET
#define MC_VERSION_LEN
apr_memcache_find_server_hash(apr_memcache_t *mc, const apr_uint32_t hash)
#define MULT_GET_TIMEOUT
#define MC_WS
#define MC_QUIT_LEN
static apr_status_t conn_connect(apr_memcache_conn_t *conn)
static const apr_uint32_t crc32tab[256]
#define MC_DECR
static apr_status_t mc_version_ping(apr_memcache_server_t *ms)
#define MC_EOL_LEN
#define MC_ADD
#define MC_SET_LEN
static apr_status_t mc_conn_construct(void **conn_, void *params, apr_pool_t *pool)
#define MS_NOT_STORED
static apr_time_t stat_read_rtime(apr_pool_t *p, char *buf, apr_size_t len)
apr_memcache_add(apr_memcache_t *mc, const char *key, char *data, const apr_size_t data_size, apr_uint32_t timeout, apr_uint16_t flags)
#define BUFFER_SIZE
static apr_status_t ms_find_conn(apr_memcache_server_t *ms, apr_memcache_conn_t **conn)
#define MC_DELETE_LEN
static apr_status_t ms_bad_conn(apr_memcache_server_t *ms, apr_memcache_conn_t *conn)
apr_memcache_add_multget_key(apr_pool_t *data_pool, const char *key, apr_hash_t **values)
static apr_status_t storage_cmd_write(apr_memcache_t *mc, char *cmd, const apr_size_t cmd_size, const char *key, char *data, const apr_size_t data_size, apr_uint32_t timeout, apr_uint16_t flags)
#define MC_REPLACE_LEN
apr_memcache_incr(apr_memcache_t *mc, const char *key, apr_int32_t inc, apr_uint32_t *new_value)
#define mc_do_stat(name, type)
#define MC_DELETE
#define MC_STATS_LEN
#define MS_NOT_FOUND
#define MC_VERSION
#define MS_ERROR_LEN
static apr_status_t make_server_live(apr_memcache_t *mc, apr_memcache_server_t *ms)
apr_memcache_set(apr_memcache_t *mc, const char *key, char *data, const apr_size_t data_size, apr_uint32_t timeout, apr_uint16_t flags)
#define MC_DECR_LEN
#define MC_ADD_LEN
#define MC_EOL
#define MC_REPLACE
#define MS_END
static int parse_size(const char *size_str, apr_size_t *size)
static void mget_conn_result(int serverup, int connup, apr_status_t rv, apr_memcache_t *mc, apr_memcache_server_t *ms, apr_memcache_conn_t *conn, struct cache_server_query_t *server_query, apr_hash_t *values, apr_hash_t *server_queries)
#define MS_VERSION_LEN
apr_memcache_delete(apr_memcache_t *mc, const char *key, apr_uint32_t timeout)
apr_memcache_decr(apr_memcache_t *mc, const char *key, apr_int32_t inc, apr_uint32_t *new_value)
#define MC_STATS
apr_memcache_find_server_hash_default(void *baton, apr_memcache_t *mc, const apr_uint32_t hash)
static apr_status_t ms_release_conn(apr_memcache_server_t *ms, apr_memcache_conn_t *conn)
#define MC_SET
apr_memcache_replace(apr_memcache_t *mc, const char *key, char *data, const apr_size_t data_size, apr_uint32_t timeout, apr_uint16_t flags)
static apr_uint64_t stat_read_uint64(apr_pool_t *p, char *buf, apr_size_t len)
#define MS_VALUE_LEN
#define MS_STAT
#define MC_INCR
#define MS_ERROR
#define MS_STORED
#define MS_NOT_FOUND_LEN
static const char * stat_read_string(apr_pool_t *p, char *buf, apr_size_t len)
apr_memcache_getp(apr_memcache_t *mc, apr_pool_t *p, const char *key, char **baton, apr_size_t *new_length, apr_uint16_t *flags_)
apr_memcache_stats(apr_memcache_server_t *ms, apr_pool_t *p, apr_memcache_stats_t **stats)
static void update_stats(apr_pool_t *p, apr_memcache_conn_t *conn, apr_memcache_stats_t *stats)
#define MS_VALUE
static apr_status_t get_server_line(apr_memcache_conn_t *conn)
static apr_uint32_t stat_read_uint32(apr_pool_t *p, char *buf, apr_size_t len)
#define MC_GET_LEN
#define MS_STAT_LEN
static apr_time_t stat_read_time(apr_pool_t *p, char *buf, apr_size_t len)
Client interface for memcached.
APR Poll interface.
#define hash(h, r, b, n)
Definition apr_random.c:51
#define min(a, b)
Definition apr_random.c:32
APU_DECLARE(void)
Computes SipHash-2-4, producing a 64bit (APR_SIPHASH_DSIZE) hash from a message and a 128bit (APR_SIP...
Definition apr_sha1.c:206
APR Versioning Interface.
const unsigned char * buf
Definition util_md5.h:50
const char apr_port_t port
Definition http_vhost.h:125
ap_vhost_iterate_conn_cb void * baton
Definition http_vhost.h:87
const char * host
Definition http_vhost.h:124
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_ENOMEM
Definition apr_errno.h:683
#define APR_NOTFOUND
Definition apr_errno.h:463
#define APR_EEXIST
Definition apr_errno.h:648
#define APR_BRIGADE_INSERT_TAIL(b, e)
apr_bucket * e
int apr_off_t * length
@ APR_BLOCK_READ
Definition apr_buckets.h:58
apr_pool_t const char * params
Definition apr_dbd.h:141
const char apr_ssize_t int flags
Definition apr_encode.h:168
apr_memcache_t * mc
apr_pool_t apr_pool_t * data_pool
const char const apr_size_t data_len
const char apr_port_t apr_uint32_t apr_uint32_t smax
const char apr_hash_t ** values
const char char const apr_size_t data_size
const char apr_int32_t apr_uint32_t * new_value
apr_memcache_server_t * server
apr_pool_t * temp_pool
apr_memcache_server_t * ms
apr_pool_t apr_memcache_stats_t ** stats
@ APR_MC_SERVER_LIVE
@ APR_MC_SERVER_DEAD
const char apr_int32_t inc
Definition apr_redis.h:337
#define APR_RESLIST_CLEANUP_FIRST
Definition apr_reslist.h:64
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
const char * key
const struct iovec * vec
void apr_size_t apr_size_t * bytes_read
void * data
const void apr_size_t apr_size_t * bytes_written
#define APR_MAX_IOVEC_SIZE
const apr_hash_t * h
Definition apr_hash.h:97
apr_ssize_t * klen
Definition apr_hash.h:71
apr_byte_t ttl
int family
apr_sockaddr_t * sa
#define APR_UNIX
apr_uint16_t apr_port_t
#define APR_INET
@ APR_POLL_SOCKET
Definition apr_poll.h:93
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const void apr_size_t bytes
Definition apr_random.h:91
const char * sep
const char char ** last
apr_cmdtype_e cmd
#define apr_time_make(sec, usec)
Definition apr_time.h:81
#define APR_USEC_PER_SEC
Definition apr_time.h:60
apr_size_t apr_size_t max
Definition apr_time.h:220
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_from_sec(sec)
Definition apr_time.h:78
#define APR_POLLIN
Definition apr_poll.h:49
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
static int max_servers
Definition mod_status.c:89
apr_bucket_brigade * tb
apr_bucket_brigade * bb
apr_socket_t * sock
apr_memcache_server_t * ms
apr_memcache_server_status_t status
apr_memcache_conn_t * conn
apr_memcache_server_func server_func
apr_pool_t * p
apr_memcache_server_t ** live_servers
apr_uint16_t ntotal
apr_uint16_t nalloc
apr_memcache_hash_func hash_func
apr_memcache_conn_t * conn
apr_memcache_server_t * ms
struct iovec * query_vec
apr_int32_t query_vec_count
static apr_pollset_t * pollset
Definition testpoll.c:41
apr_status_t apr_socket_sendv(apr_socket_t *sock, const struct iovec *vec, apr_int32_t nvec, apr_size_t *len)
Definition sendrecv.c:194
apr_status_t apr_socket_close(apr_socket_t *thesocket)
Definition sockets.c:211
apr_status_t apr_socket_connect(apr_socket_t *sock, apr_sockaddr_t *sa)
Definition sockets.c:388
apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type, int protocol, apr_pool_t *cont)
Definition sockets.c:116
apr_status_t apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
Definition sockopt.c:75
#define str
IN ULONG IN INT timeout