Apache HTTPD
apr_redis.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_redis.h"
18#include "apr_poll.h"
19#include "apr_version.h"
20#include <stdlib.h>
21#include <string.h>
22
23#define BUFFER_SIZE 512
24#define LILBUFF_SIZE 64
36
37/* Strings for Client Commands */
38
39#define RC_EOL "\r\n"
40#define RC_EOL_LEN (sizeof(RC_EOL)-1)
41
42#define RC_WS " "
43#define RC_WS_LEN (sizeof(RC_WS)-1)
44
45#define RC_RESP_1 "*1\r\n"
46#define RC_RESP_1_LEN (sizeof(RC_RESP_1)-1)
47
48#define RC_RESP_2 "*2\r\n"
49#define RC_RESP_2_LEN (sizeof(RC_RESP_2)-1)
50
51#define RC_RESP_3 "*3\r\n"
52#define RC_RESP_3_LEN (sizeof(RC_RESP_3)-1)
53
54#define RC_RESP_4 "*4\r\n"
55#define RC_RESP_4_LEN (sizeof(RC_RESP_4)-1)
56
57#define RC_GET "GET\r\n"
58#define RC_GET_LEN (sizeof(RC_GET)-1)
59
60#define RC_GET_SIZE "$3\r\n"
61#define RC_GET_SIZE_LEN (sizeof(RC_GET_SIZE)-1)
62
63#define RC_SET "SET\r\n"
64#define RC_SET_LEN (sizeof(RC_SET)-1)
65
66#define RC_SET_SIZE "$3\r\n"
67#define RC_SET_SIZE_LEN (sizeof(RC_SET_SIZE)-1)
68
69#define RC_SETEX "SETEX\r\n"
70#define RC_SETEX_LEN (sizeof(RC_SETEX)-1)
71
72#define RC_SETEX_SIZE "$5\r\n"
73#define RC_SETEX_SIZE_LEN (sizeof(RC_SETEX_SIZE)-1)
74
75#define RC_DEL "DEL\r\n"
76#define RC_DEL_LEN (sizeof(RC_DEL)-1)
77
78#define RC_DEL_SIZE "$3\r\n"
79#define RC_DEL_SIZE_LEN (sizeof(RC_DEL_SIZE)-1)
80
81#define RC_QUIT "QUIT\r\n"
82#define RC_QUIT_LEN (sizeof(RC_QUIT)-1)
83
84#define RC_QUIT_SIZE "$4\r\n"
85#define RC_QUIT_SIZE_LEN (sizeof(RC_QUIT_SIZE)-1)
86
87#define RC_PING "PING\r\n"
88#define RC_PING_LEN (sizeof(RC_PING)-1)
89
90#define RC_PING_SIZE "$4\r\n"
91#define RC_PING_SIZE_LEN (sizeof(RC_PING_SIZE)-1)
92
93#define RC_INFO "INFO\r\n"
94#define RC_INFO_LEN (sizeof(RC_INFO)-1)
95
96#define RC_INFO_SIZE "$4\r\n"
97#define RC_INFO_SIZE_LEN (sizeof(RC_INFO_SIZE)-1)
98
99/* Strings for Server Replies */
100
101#define RS_STORED "+OK"
102#define RS_STORED_LEN (sizeof(RS_STORED)-1)
103
104#define RS_NOT_STORED "$-1"
105#define RS_NOT_STORED_LEN (sizeof(RS_NOT_STORED)-1)
106
107#define RS_DELETED ":1"
108#define RS_DELETED_LEN (sizeof(RS_DELETED)-1)
109
110#define RS_NOT_FOUND_GET "$-1"
111#define RS_NOT_FOUND_GET_LEN (sizeof(RS_NOT_FOUND_GET)-1)
112
113#define RS_NOT_FOUND_DEL ":0"
114#define RS_NOT_FOUND_DEL_LEN (sizeof(RS_NOT_FOUND_DEL)-1)
115
116#define RS_TYPE_STRING "$"
117#define RS_TYPE_STRING_LEN (sizeof(RS_TYPE_STRING)-1)
118
119#define RS_END "\r\n"
120#define RS_END_LEN (sizeof(RS_END)-1)
121
124{
125#if APR_HAS_THREADS
127#endif
129 rs->btime = apr_time_now();
130#if APR_HAS_THREADS
132#endif
133 return APR_SUCCESS;
134}
135
142
145{
147
148 if (rc->ntotal >= rc->nalloc) {
149 return APR_ENOMEM;
150 }
152 rc->ntotal++;
154 return rv;
155}
156
167
171{
173 apr_uint32_t h = hash ? hash : 1;
174 apr_uint32_t i = 0;
176
177 if (rc->ntotal == 0) {
178 return NULL;
179 }
180
181 do {
182 rs = rc->live_servers[h % rc->ntotal];
183 if (rs->status == APR_RC_SERVER_LIVE) {
184 break;
185 }
186 else {
187 if (curtime == 0) {
189 }
190#if APR_HAS_THREADS
192#endif
193 /* Try the dead server, every 5 seconds */
194 if (curtime - rs->btime > apr_time_from_sec(5)) {
195 rs->btime = curtime;
196 if (apr_redis_ping(rs) == APR_SUCCESS) {
198#if APR_HAS_THREADS
200#endif
201 break;
202 }
203 }
204#if APR_HAS_THREADS
206#endif
207 }
208 h++;
209 i++;
210 } while (i < rc->ntotal);
211
212 if (i == rc->ntotal) {
213 rs = NULL;
214 }
215
216 return rs;
217}
218
220 const char *host,
222{
223 int i;
224
225 for (i = 0; i < rc->ntotal; i++) {
226 if (strcmp(rc->live_servers[i]->host, host) == 0
227 && rc->live_servers[i]->port == port) {
228
229 return rc->live_servers[i];
230 }
231 }
232
233 return NULL;
234}
235
237 apr_redis_conn_t ** conn)
238{
239 apr_status_t rv;
241 apr_bucket *e;
242
243#if APR_HAS_THREADS
244 rv = apr_reslist_acquire(rs->conns, (void **) conn);
245#else
246 *conn = rs->conn;
247 rv = APR_SUCCESS;
248#endif
249
250 if (rv != APR_SUCCESS) {
251 return rv;
252 }
253
254 balloc = apr_bucket_alloc_create((*conn)->tp);
255 (*conn)->bb = apr_brigade_create((*conn)->tp, balloc);
256 (*conn)->tb = apr_brigade_create((*conn)->tp, balloc);
257
258 e = apr_bucket_socket_create((*conn)->sock, balloc);
259 APR_BRIGADE_INSERT_TAIL((*conn)->bb, e);
260
261 return rv;
262}
263
265 apr_redis_conn_t *conn)
266{
267#if APR_HAS_THREADS
268 return apr_reslist_invalidate(rs->conns, conn);
269#else
270 return APR_SUCCESS;
271#endif
272}
273
275 apr_redis_conn_t *conn)
276{
277 apr_pool_clear(conn->tp);
278#if APR_HAS_THREADS
279 return apr_reslist_release(rs->conns, conn);
280#else
281 return APR_SUCCESS;
282#endif
283}
284
287{
289
290 if (rs->status == APR_RC_SERVER_LIVE) {
291 return rv;
292 }
293 rv = make_server_live(rc, rs);
294 return rv;
295}
296
299{
300 return make_server_dead(rc, rs);
301}
302
304{
307#if APR_HAVE_SOCKADDR_UN
308 apr_int32_t family = conn->rs->host[0] != '/' ? APR_INET : APR_UNIX;
309#else
311#endif
312
313 rv = apr_sockaddr_info_get(&sa, conn->rs->host, family, conn->rs->port, 0,
314 conn->p);
315 if (rv != APR_SUCCESS) {
316 return rv;
317 }
318
320 if (rv != APR_SUCCESS) {
321 return rv;
322 }
323
324 rv = apr_socket_connect(conn->sock, sa);
325 if (rv != APR_SUCCESS) {
326 return rv;
327 }
328
329 rv = apr_socket_timeout_set(conn->sock,
330 conn->rs->rwto * APR_USEC_PER_SEC);
331 if (rv != APR_SUCCESS) {
332 return rv;
333 }
334
335 return rv;
336}
337
338static apr_status_t
340{
342 apr_redis_conn_t *conn;
343 apr_pool_t *np;
344 apr_pool_t *tp;
346#if APR_HAVE_SOCKADDR_UN
347 apr_int32_t family = rs->host[0] != '/' ? APR_INET : APR_UNIX;
348#else
350#endif
351
352 rv = apr_pool_create(&np, pool);
353 if (rv != APR_SUCCESS) {
354 return rv;
355 }
356
357 rv = apr_pool_create(&tp, np);
358 if (rv != APR_SUCCESS) {
360 return rv;
361 }
362
363 conn = apr_palloc(np, sizeof(apr_redis_conn_t));
364
365 conn->p = np;
366 conn->tp = tp;
367
368 rv = apr_socket_create(&conn->sock, family, SOCK_STREAM, 0, np);
369
370 if (rv != APR_SUCCESS) {
372 return rv;
373 }
374
375 conn->buffer = apr_palloc(conn->p, BUFFER_SIZE + 1);
376 conn->blen = 0;
377 conn->rs = rs;
378
379 rv = conn_connect(conn);
380 if (rv != APR_SUCCESS) {
382 }
383 else {
384 *conn_ = conn;
385 }
386
387 return rv;
388}
389
390#if APR_HAS_THREADS
391static apr_status_t
393{
395 struct iovec vec[3];
396 apr_size_t written;
397
398 /* send a quit message to the Redis server to be nice about it. */
399
400 /*
401 * RESP Command:
402 * *1
403 * $4
404 * QUIT
405 */
406 vec[0].iov_base = RC_RESP_1;
407 vec[0].iov_len = RC_RESP_1_LEN;
408
409 vec[1].iov_base = RC_QUIT_SIZE;
410 vec[1].iov_len = RC_QUIT_SIZE_LEN;
411
412 vec[2].iov_base = RC_QUIT;
413 vec[2].iov_len = RC_QUIT_LEN;
414
415 /* Return values not checked, since we just want to make it go away. */
416 apr_socket_sendv(conn->sock, vec, 3, &written);
417 apr_socket_close(conn->sock);
418
419 apr_pool_destroy(conn->p);
420
421 return APR_SUCCESS;
422}
423#endif
424
426 const char *host,
434{
437 apr_pool_t *np;
438
439 rv = apr_pool_create(&np, p);
440
442
443 server->p = np;
445 server->port = port;
447 server->rwto = rwto;
448 server->version.major = 0;
449 server->version.minor = 0;
450 server->version.patch = 0;
451
452#if APR_HAS_THREADS
454 if (rv != APR_SUCCESS) {
455 return rv;
456 }
457
458 rv = apr_reslist_create(&server->conns,
459 min, /* hard minimum */
460 smax, /* soft maximum */
461 max, /* hard maximum */
462 ttl, /* Time to live */
463 rc_conn_construct, /* Make a New Connection */
464 rc_conn_destruct, /* Kill Old Connection */
465 server, np);
466 if (rv != APR_SUCCESS) {
467 return rv;
468 }
469
471#else
472 rv = rc_conn_construct((void **) &(server->conn), server, np);
473 if (rv != APR_SUCCESS) {
474 return rv;
475 }
476#endif
477
478 *rs = server;
479
480 return rv;
481}
482
487{
490
491 rc = apr_palloc(p, sizeof(apr_redis_t));
492 rc->p = p;
494 rc->ntotal = 0;
496 apr_palloc(p, rc->nalloc * sizeof(struct apr_redis_server_t *));
497 rc->hash_func = NULL;
498 rc->hash_baton = NULL;
501 *redis = rc;
502 return rv;
503}
504
505
506/* The crc32 functions and data was originally written by Spencer
507 * Garrett <[email protected]> and was gleaned from the PostgreSQL source
508 * tree via the files contrib/ltree/crc32.[ch] and from FreeBSD at
509 * src/usr.bin/cksum/crc32.c.
510 */
511
512static const apr_uint32_t crc32tab[256] = {
513 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
514 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
515 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
516 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
517 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
518 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
519 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
520 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
521 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
522 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
523 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
524 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
525 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
526 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
527 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
528 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
529 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
530 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
531 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
532 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
533 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
534 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
535 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
536 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
537 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
538 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
539 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
540 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
541 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
542 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
543 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
544 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
545 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
546 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
547 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
548 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
549 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
550 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
551 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
552 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
553 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
554 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
555 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
556 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
557 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
558 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
559 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
560 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
561 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
562 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
563 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
564 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
565 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
566 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
567 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
568 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
569 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
570 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
571 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
572 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
573 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
574 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
575 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
576 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
577};
578
580 const char *data,
581 const apr_size_t data_len)
582{
584 apr_uint32_t crc;
585 crc = ~0;
586
587 for (i = 0; i < data_len; i++)
588 crc = (crc >> 8) ^ crc32tab[(crc ^ (data[i])) & 0xff];
589
590 return ~crc;
591}
592
594 const char *data,
595 const apr_size_t data_len)
596{
597 /* The default Perl Client doesn't actually use just crc32 -- it shifts it again
598 * like this....
599 */
600 return ((apr_redis_hash_crc32(baton, data, data_len) >> 16) & 0x7fff);
601}
602
604 const char *data,
605 const apr_size_t data_len)
606{
607 if (rc->hash_func) {
609 }
610 else {
612 }
613}
614
616{
619
620 rv = apr_brigade_split_line(conn->tb, conn->bb, APR_BLOCK_READ,
622
623 if (rv != APR_SUCCESS) {
624 return rv;
625 }
626
627 rv = apr_brigade_flatten(conn->tb, conn->buffer, &bsize);
628
629 if (rv != APR_SUCCESS) {
630 return rv;
631 }
632
633 conn->blen = bsize;
634 conn->buffer[bsize] = '\0';
635
636 return apr_brigade_cleanup(conn->tb);
637}
638
640 const char *key,
641 char *data,
642 const apr_size_t data_size,
644{
647 apr_redis_conn_t *conn;
648 apr_status_t rv;
649 apr_size_t written;
650 struct iovec vec[9];
654
655 klen = strlen(key);
657
659
660 if (rs == NULL)
661 return APR_NOTFOUND;
662
663 rv = rs_find_conn(rs, &conn);
664
665 if (rv != APR_SUCCESS) {
667 return rv;
668 }
669
670 /*
671 * RESP Command:
672 * *3
673 * $3
674 * SET
675 * $<keylen>
676 * key
677 * $<datalen>
678 * data
679 */
680
681 vec[0].iov_base = RC_RESP_3;
682 vec[0].iov_len = RC_RESP_3_LEN;
683
684 vec[1].iov_base = RC_SET_SIZE;
685 vec[1].iov_len = RC_SET_SIZE_LEN;
686
687 vec[2].iov_base = RC_SET;
688 vec[2].iov_len = RC_SET_LEN;
689
691 vec[3].iov_base = keysize_str;
692 vec[3].iov_len = len;
693
694 vec[4].iov_base = (void *) key;
695 vec[4].iov_len = klen;
696
697 vec[5].iov_base = RC_EOL;
698 vec[5].iov_len = RC_EOL_LEN;
699
701 data_size);
702 vec[6].iov_base = datasize_str;
703 vec[6].iov_len = len;
704
705 vec[7].iov_base = data;
706 vec[7].iov_len = data_size;
707
708 vec[8].iov_base = RC_EOL;
709 vec[8].iov_len = RC_EOL_LEN;
710
711 rv = apr_socket_sendv(conn->sock, vec, 9, &written);
712
713 if (rv != APR_SUCCESS) {
714 rs_bad_conn(rs, conn);
716 return rv;
717 }
718
719 rv = get_server_line(conn);
720 if (rv != APR_SUCCESS) {
721 rs_bad_conn(rs, conn);
723 return rv;
724 }
725
726 if (strcmp(conn->buffer, RS_STORED RC_EOL) == 0) {
727 rv = APR_SUCCESS;
728 }
729 else if (strcmp(conn->buffer, RS_NOT_STORED RC_EOL) == 0) {
730 rv = APR_EEXIST;
731 }
732 else {
733 rv = APR_EGENERAL;
734 }
735
736 rs_release_conn(rs, conn);
737 return rv;
738}
739
741 const char *key,
742 char *data,
743 const apr_size_t data_size,
746{
749 apr_redis_conn_t *conn;
750 apr_status_t rv;
751 apr_size_t written;
752 struct iovec vec[11];
758
759
760 klen = strlen(key);
762
764
765 if (rs == NULL)
766 return APR_NOTFOUND;
767
768 rv = rs_find_conn(rs, &conn);
769
770 if (rv != APR_SUCCESS) {
772 return rv;
773 }
774
775 /*
776 * RESP Command:
777 * *4
778 * $5
779 * SETEX
780 * $<keylen>
781 * key
782 * $<expirelen>
783 * expirey
784 * $<datalen>
785 * data
786 */
787
788 vec[0].iov_base = RC_RESP_4;
789 vec[0].iov_len = RC_RESP_4_LEN;
790
791 vec[1].iov_base = RC_SETEX_SIZE;
792 vec[1].iov_len = RC_SETEX_SIZE_LEN;
793
794 vec[2].iov_base = RC_SETEX;
795 vec[2].iov_len = RC_SETEX_LEN;
796
798 vec[3].iov_base = keysize_str;
799 vec[3].iov_len = len;
800
801 vec[4].iov_base = (void *) key;
802 vec[4].iov_len = klen;
803
804 vec[5].iov_base = RC_EOL;
805 vec[5].iov_len = RC_EOL_LEN;
806
809 expire_len - 2);
810 vec[6].iov_base = (void *) expiresize_str;
811 vec[6].iov_len = len;
812
813 vec[7].iov_base = (void *) expire_str;
814 vec[7].iov_len = expire_len;
815
817 data_size);
818 vec[8].iov_base = datasize_str;
819 vec[8].iov_len = len;
820
821 vec[9].iov_base = data;
822 vec[9].iov_len = data_size;
823
824 vec[10].iov_base = RC_EOL;
825 vec[10].iov_len = RC_EOL_LEN;
826
827 rv = apr_socket_sendv(conn->sock, vec, 11, &written);
828
829 if (rv != APR_SUCCESS) {
830 rs_bad_conn(rs, conn);
832 return rv;
833 }
834
835 rv = get_server_line(conn);
836 if (rv != APR_SUCCESS) {
837 rs_bad_conn(rs, conn);
839 return rv;
840 }
841
842 if (strcmp(conn->buffer, RS_STORED RC_EOL) == 0) {
843 rv = APR_SUCCESS;
844 }
845 else if (strcmp(conn->buffer, RS_NOT_STORED RC_EOL) == 0) {
846 rv = APR_EEXIST;
847 }
848 else {
849 rv = APR_EGENERAL;
850 }
851
852 rs_release_conn(rs, conn);
853 return rv;
854}
855
858 char **baton, apr_size_t *new_length)
859{
860 char *length;
861 char *last;
862 apr_status_t rv;
863 apr_size_t len = 0;
864 *new_length = 0;
865
866 length = apr_strtok(conn->buffer + 1, " ", &last);
867 if (length) {
868 len = strtol(length, (char **) NULL, 10);
869 }
870
871 if (len == 0) {
872 *new_length = 0;
873 *baton = NULL;
874 }
875 else {
877 apr_bucket *e;
878
879 /* eat the trailing \r\n */
880 rv = apr_brigade_partition(conn->bb, len + 2, &e);
881
882 if (rv != APR_SUCCESS) {
883 rs_bad_conn(rs, conn);
884 if (rc)
886 return rv;
887 }
888
889 bbb = apr_brigade_split(conn->bb, e);
890
891 rv = apr_brigade_pflatten(conn->bb, baton, &len, p);
892
893 if (rv != APR_SUCCESS) {
894 rs_bad_conn(rs, conn);
895 if (rc)
897 return rv;
898 }
899
900 rv = apr_brigade_destroy(conn->bb);
901 if (rv != APR_SUCCESS) {
902 rs_bad_conn(rs, conn);
903 if (rc)
905 return rv;
906 }
907
908 conn->bb = bbb;
909
910 *new_length = len - 2;
911 (*baton)[*new_length] = '\0';
912 }
913 return APR_SUCCESS;
914
915}
916
918 apr_pool_t *p,
919 const char *key,
920 char **baton,
923{
924 apr_status_t rv;
926 apr_redis_conn_t *conn;
928 apr_size_t written;
930 struct iovec vec[6];
932
933 klen = strlen(key);
936
937 if (rs == NULL)
938 return APR_NOTFOUND;
939
940 rv = rs_find_conn(rs, &conn);
941
942 if (rv != APR_SUCCESS) {
944 return rv;
945 }
946
947 /*
948 * RESP Command:
949 * *2
950 * $3
951 * GET
952 * $<keylen>
953 * key
954 */
955 vec[0].iov_base = RC_RESP_2;
956 vec[0].iov_len = RC_RESP_2_LEN;
957
958 vec[1].iov_base = RC_GET_SIZE;
959 vec[1].iov_len = RC_GET_SIZE_LEN;
960
961 vec[2].iov_base = RC_GET;
962 vec[2].iov_len = RC_GET_LEN;
963
965 klen);
966 vec[3].iov_base = keysize_str;
967 vec[3].iov_len = len;
968
969 vec[4].iov_base = (void *) key;
970 vec[4].iov_len = klen;
971
972 vec[5].iov_base = RC_EOL;
973 vec[5].iov_len = RC_EOL_LEN;
974
975 rv = apr_socket_sendv(conn->sock, vec, 6, &written);
976
977
978 if (rv != APR_SUCCESS) {
979 rs_bad_conn(rs, conn);
981 return rv;
982 }
983
984 rv = get_server_line(conn);
985 if (rv != APR_SUCCESS) {
986 rs_bad_conn(rs, conn);
988 return rv;
989 }
991 rv = APR_NOTFOUND;
992 }
993 else if (strncmp(RS_TYPE_STRING, conn->buffer, RS_TYPE_STRING_LEN) == 0) {
994 rv = grab_bulk_resp(rs, rc, conn, p, baton, new_length);
995 }
996 else {
997 rv = APR_EGENERAL;
998 }
999
1000 rs_release_conn(rs, conn);
1001 return rv;
1002}
1003
1006{
1007 apr_status_t rv;
1009 apr_redis_conn_t *conn;
1011 apr_size_t written;
1012 struct iovec vec[6];
1015
1016 klen = strlen(key);
1019 if (rs == NULL)
1020 return APR_NOTFOUND;
1021
1022 rv = rs_find_conn(rs, &conn);
1023
1024 if (rv != APR_SUCCESS) {
1026 return rv;
1027 }
1028
1029 /*
1030 * RESP Command:
1031 * *2
1032 * $3
1033 * DEL
1034 * $<keylen>
1035 * key
1036 */
1037 vec[0].iov_base = RC_RESP_2;
1038 vec[0].iov_len = RC_RESP_2_LEN;
1039
1040 vec[1].iov_base = RC_DEL_SIZE;
1041 vec[1].iov_len = RC_DEL_SIZE_LEN;
1042
1043 vec[2].iov_base = RC_DEL;
1044 vec[2].iov_len = RC_DEL_LEN;
1045
1047 klen);
1048 vec[3].iov_base = keysize_str;
1049 vec[3].iov_len = len;
1050
1051 vec[4].iov_base = (void *) key;
1052 vec[4].iov_len = klen;
1053
1054 vec[5].iov_base = RC_EOL;
1055 vec[5].iov_len = RC_EOL_LEN;
1056
1057 rv = apr_socket_sendv(conn->sock, vec, 6, &written);
1058
1059 if (rv != APR_SUCCESS) {
1060 rs_bad_conn(rs, conn);
1062 return rv;
1063 }
1064
1065 rv = get_server_line(conn);
1066 if (rv != APR_SUCCESS) {
1067 rs_bad_conn(rs, conn);
1069 return rv;
1070 }
1071
1072 if (strncmp(RS_DELETED, conn->buffer, RS_DELETED_LEN) == 0) {
1073 rv = APR_SUCCESS;
1074 }
1075 else if (strncmp(RS_NOT_FOUND_DEL, conn->buffer, RS_NOT_FOUND_DEL_LEN) == 0) {
1076 rv = APR_NOTFOUND;
1077 }
1078 else {
1079 rv = APR_EGENERAL;
1080 }
1081
1082 rs_release_conn(rs, conn);
1083 return rv;
1084}
1085
1088{
1089 apr_status_t rv;
1090 apr_size_t written;
1091 struct iovec vec[3];
1092 apr_redis_conn_t *conn;
1093
1094 rv = rs_find_conn(rs, &conn);
1095
1096 if (rv != APR_SUCCESS) {
1097 return rv;
1098 }
1099
1100 /*
1101 * RESP Command:
1102 * *1
1103 * $4
1104 * PING
1105 */
1106 vec[0].iov_base = RC_RESP_1;
1107 vec[0].iov_len = RC_RESP_1_LEN;
1108
1109 vec[1].iov_base = RC_PING_SIZE;
1110 vec[1].iov_len = RC_PING_SIZE_LEN;
1111
1112 vec[2].iov_base = RC_PING;
1113 vec[2].iov_len = RC_PING_LEN;
1114
1115 rv = apr_socket_sendv(conn->sock, vec, 3, &written);
1116
1117 if (rv != APR_SUCCESS) {
1118 rs_bad_conn(rs, conn);
1119 return rv;
1120 }
1121
1122 rv = get_server_line(conn);
1123 if (rv == APR_SUCCESS) {
1124 /* we got *something*. Was it Redis? */
1125 if (strncmp(conn->buffer, "+PONG", sizeof("+PONG")-1) != 0) {
1126 rv = APR_EGENERAL;
1127 }
1128 }
1129 rs_release_conn(rs, conn);
1130 return rv;
1131}
1132
1135{
1136 apr_status_t rv;
1137 apr_redis_conn_t *conn;
1138 apr_size_t written;
1139 struct iovec vec[3];
1140
1141 rv = rs_find_conn(rs, &conn);
1142
1143 if (rv != APR_SUCCESS) {
1144 return rv;
1145 }
1146
1147 /*
1148 * RESP Command:
1149 * *1
1150 * $4
1151 * INFO
1152 */
1153 vec[0].iov_base = RC_RESP_1;
1154 vec[0].iov_len = RC_RESP_1_LEN;
1155
1156 vec[1].iov_base = RC_INFO_SIZE;
1157 vec[1].iov_len = RC_INFO_SIZE_LEN;
1158
1159 vec[2].iov_base = RC_INFO;
1160 vec[2].iov_len = RC_INFO_LEN;
1161
1162 rv = apr_socket_sendv(conn->sock, vec, 3, &written);
1163
1164 if (rv != APR_SUCCESS) {
1165 rs_bad_conn(rs, conn);
1166 return rv;
1167 }
1168
1169 rv = get_server_line(conn);
1170 if (rv != APR_SUCCESS) {
1171 rs_bad_conn(rs, conn);
1172 return rv;
1173 }
1174
1175 if (strncmp(RS_TYPE_STRING, conn->buffer, RS_TYPE_STRING_LEN) == 0) {
1176 apr_size_t nl;
1177 rv = grab_bulk_resp(rs, NULL, conn, p, baton, &nl);
1178 } else {
1179 rs_bad_conn(rs, conn);
1180 rv = APR_EGENERAL;
1181 }
1182
1183 rs_release_conn(rs, conn);
1184 return rv;
1185}
1186
1187#define RV_FIELD "redis_version:"
1190{
1191 apr_status_t rv;
1192 char *ptr, *eptr;
1194
1195 /* Have we already obtained the version number? */
1196 if (rs->version.minor != 0) {
1197 if (baton)
1199 return APR_SUCCESS;
1200 }
1202 /* well, we tried */
1203 subpool = p;
1204 }
1206
1207 if (rv != APR_SUCCESS) {
1208 if (subpool != p) {
1210 }
1211 return rv;
1212 }
1213
1214 ptr = strstr(*baton, RV_FIELD);
1215 if (ptr) {
1216 rs->version.major = strtol(ptr + sizeof(RV_FIELD) - 1, &eptr, 10);
1217 ptr = eptr + 1;
1218 rs->version.minor = strtol(ptr, &eptr, 10);
1219 ptr = eptr + 1;
1220 rs->version.patch = strtol(ptr, &eptr, 10);
1221 rs->version.number = apr_psprintf(rs->p, "%d.%d.%d",
1223 rs->version.patch);
1224 }
1225 if (baton)
1227 if (subpool != p) {
1229 }
1230 return APR_SUCCESS;
1231}
1232
1234 int incr,
1235 const char *key,
1238{
1239 apr_status_t rv;
1241 apr_redis_conn_t *conn;
1243 apr_size_t written;
1245 struct iovec vec[12];
1247 char inc_str[LILBUFF_SIZE];
1249 int i = 0;
1250
1251 klen = strlen(key);
1254 if (rs == NULL)
1255 return APR_NOTFOUND;
1256
1257 rv = rs_find_conn(rs, &conn);
1258
1259 if (rv != APR_SUCCESS) {
1261 return rv;
1262 }
1263
1264 /*
1265 * RESP Command:
1266 * *2|*3
1267 * $4|$6
1268 * INCR/DECR|INCRBY/DECRBY
1269 * $<keylen>
1270 * key
1271 * <:inc>
1272 */
1273 if (inc == 1) {
1274 vec[i].iov_base = RC_RESP_2;
1275 vec[i].iov_len = RC_RESP_2_LEN;
1276 i++;
1277
1278 vec[i].iov_base = "$4\r\n";
1279 vec[i].iov_len = sizeof("$4\r\n")-1;
1280 i++;
1281
1282 if (incr)
1283 vec[i].iov_base = "INCR\r\n";
1284 else
1285 vec[i].iov_base = "DECR\r\n";
1286 vec[i].iov_len = sizeof("INCR\r\n")-1;
1287 i++;
1288 }
1289 else {
1290 vec[i].iov_base = RC_RESP_3;
1291 vec[i].iov_len = RC_RESP_3_LEN;
1292 i++;
1293
1294 vec[i].iov_base = "$6\r\n";
1295 vec[i].iov_len = sizeof("$6\r\n")-1;
1296 i++;
1297
1298 if (incr)
1299 vec[i].iov_base = "INCRBY\r\n";
1300 else
1301 vec[i].iov_base = "DECRBY\r\n";
1302 vec[i].iov_len = sizeof("INCRBY\r\n")-1;
1303 i++;
1304 }
1305
1307 klen);
1308 vec[i].iov_base = keysize_str;
1309 vec[i].iov_len = len;
1310 i++;
1311
1312 vec[i].iov_base = (void *) key;
1313 vec[i].iov_len = klen;
1314 i++;
1315
1316 vec[i].iov_base = RC_EOL;
1317 vec[i].iov_len = RC_EOL_LEN;
1318 i++;
1319
1320 if (inc != 1) {
1321 len = apr_snprintf(inc_str, LILBUFF_SIZE, "%d\r\n", inc);
1322 klen = apr_snprintf(inc_str_len, LILBUFF_SIZE, "$%d\r\n", (int)(len-2));
1323 vec[i].iov_base = inc_str_len;
1324 vec[i].iov_len = klen;
1325 i++;
1326
1327 vec[i].iov_base = inc_str;
1328 vec[i].iov_len = len;
1329 i++;
1330
1331 vec[i].iov_base = RC_EOL;
1332 vec[i].iov_len = RC_EOL_LEN;
1333 i++;
1334 }
1335
1336 rv = apr_socket_sendv(conn->sock, vec, i, &written);
1337
1338 if (rv != APR_SUCCESS) {
1339 rs_bad_conn(rs, conn);
1341 return rv;
1342 }
1343
1344 rv = get_server_line(conn);
1345 if (rv != APR_SUCCESS) {
1346 rs_bad_conn(rs, conn);
1348 return rv;
1349 }
1351 rv = APR_NOTFOUND;
1352 }
1353 else if (*conn->buffer == ':') {
1354 *new_value = atoi((const char *)(conn->buffer + 1));
1355 rv = APR_SUCCESS;
1356 }
1357 else {
1358 rv = APR_EGENERAL;
1359 }
1360 rs_release_conn(rs, conn);
1361 return rv;
1362}
1363
1369
1375
1384
1389#define STAT_process_id "process_id:"
1390#define STAT_process_id_LEN (sizeof(STAT_process_id)-1)
1391
1392#define STAT_uptime_in_seconds "uptime_in_seconds:"
1393#define STAT_uptime_in_seconds_LEN (sizeof(STAT_uptime_in_seconds)-1)
1394
1395#define STAT_arch_bits "arch_bits:"
1396#define STAT_arch_bits_LEN (sizeof(STAT_arch_bits)-1)
1397
1398#define STAT_connected_clients "connected_clients:"
1399#define STAT_connected_clients_LEN (sizeof(STAT_connected_clients)-1)
1400
1401#define STAT_blocked_clients "blocked_clients:"
1402#define STAT_blocked_clients_LEN (sizeof(STAT_blocked_clients)-1)
1403
1404#define STAT_maxmemory "maxmemory:"
1405#define STAT_maxmemory_LEN (sizeof(STAT_maxmemory)-1)
1406
1407#define STAT_used_memory "used_memory:"
1408#define STAT_used_memory_LEN (sizeof(STAT_used_memory)-1)
1409
1410#define STAT_total_system_memory "total_system_memory:"
1411#define STAT_total_system_memory_LEN (sizeof(STAT_total_system_memory)-1)
1412
1413#define STAT_total_connections_received "total_connections_received:"
1414#define STAT_total_connections_received_LEN (sizeof(STAT_total_connections_received)-1)
1415
1416#define STAT_total_commands_processed "total_commands_processed:"
1417#define STAT_total_commands_processed_LEN (sizeof(STAT_total_commands_processed)-1)
1418
1419#define STAT_rejected_connections "rejected_connections:"
1420#define STAT_rejected_connections_LEN (sizeof(STAT_rejected_connections)-1)
1421
1422#define STAT_total_net_input_bytes "total_net_input_bytes:"
1423#define STAT_total_net_input_bytes_LEN (sizeof(STAT_total_net_input_bytes)-1)
1424
1425#define STAT_total_net_output_bytes "total_net_output_bytes:"
1426#define STAT_total_net_output_bytes_LEN (sizeof(STAT_total_net_output_bytes)-1)
1427
1428#define STAT_keyspace_hits "keyspace_hits:"
1429#define STAT_keyspace_hits_LEN (sizeof(STAT_keyspace_hits)-1)
1430
1431#define STAT_keyspace_misses "keyspace_misses:"
1432#define STAT_keyspace_misses_LEN (sizeof(STAT_keyspace_misses)-1)
1433
1434#define STAT_connected_slaves "connected_slaves:"
1435#define STAT_connected_slaves_LEN (sizeof(STAT_connected_slaves)-1)
1436
1437#define STAT_used_cpu_sys "used_cpu_sys:"
1438#define STAT_used_cpu_sys_LEN (sizeof(STAT_used_cpu_sys)-1)
1439
1440#define STAT_used_cpu_user "used_cpu_user:"
1441#define STAT_used_cpu_user_LEN (sizeof(STAT_used_cpu_user)-1)
1442
1443#define STAT_cluster_enabled "cluster_enabled:"
1444#define STAT_cluster_enabled_LEN (sizeof(STAT_cluster_enabled)-1)
1445
1447{
1448 return atoi(buf);
1449}
1450
1452{
1453 return apr_atoi64(buf);
1454}
1455
1456#define rc_do_stat(name, type) \
1457 if ((ptr = strstr(info , STAT_ ## name )) != NULL ) { \
1458 char *str = ptr + (STAT_ ## name ## _LEN ); \
1459 stats-> name = stat_read_ ## type (str); \
1460 }
1461
1463{
1464 char *ptr;
1465
1466 rc_do_stat(process_id, uint32);
1467 rc_do_stat(uptime_in_seconds, uint32);
1468 rc_do_stat(arch_bits, uint32);
1469 rc_do_stat(connected_clients, uint32);
1470 rc_do_stat(blocked_clients, uint32);
1471 rc_do_stat(maxmemory, uint64);
1472 rc_do_stat(used_memory, uint64);
1473 rc_do_stat(total_system_memory, uint64);
1474 rc_do_stat(total_connections_received, uint64);
1475 rc_do_stat(total_commands_processed, uint64);
1476 rc_do_stat(rejected_connections, uint64);
1477 rc_do_stat(total_net_input_bytes, uint64);
1478 rc_do_stat(total_net_output_bytes, uint64);
1479 rc_do_stat(keyspace_hits, uint64);
1480 rc_do_stat(keyspace_misses, uint64);
1481 rc_do_stat(connected_slaves, uint32);
1482 rc_do_stat(used_cpu_sys, uint32);
1483 rc_do_stat(used_cpu_user, uint32);
1484 rc_do_stat(cluster_enabled, uint32);
1485}
1486
1489 apr_pool_t *p,
1491{
1492 apr_status_t rv;
1493 char *info;
1496 char *ptr;
1497
1499 /* well, we tried */
1500 subpool = p;
1501 }
1502 rv = apr_redis_info(rs, subpool, &info);
1503
1504 if (rv != APR_SUCCESS) {
1505 if (subpool != p) {
1507 }
1508 return rv;
1509 }
1510 ret = apr_pcalloc(p, sizeof(apr_redis_stats_t));
1511 /* Get the bulk of the stats */
1513
1514 /* Now the version number */
1515 if (rs->version.major != 0) {
1516 ret->major = rs->version.major;
1517 ret->minor = rs->version.minor;
1518 ret->patch = rs->version.patch;
1519 }
1520 else {
1521 char *eptr;
1522 ptr = strstr(info, RV_FIELD);
1523 if (ptr) {
1524 ret->major = rs->version.major = strtol(ptr + sizeof(RV_FIELD) - 1, &eptr, 10);
1525 ptr = eptr + 1;
1526 ret->minor = rs->version.minor = strtol(ptr, &eptr, 10);
1527 ptr = eptr + 1;
1528 ret->patch = rs->version.patch = strtol(ptr, &eptr, 10);
1529 }
1530 }
1531
1532 /* Finally, the role */
1533 ptr = strstr(info, "role:");
1534 if (!ptr) {
1535 ret->role = APR_RS_SERVER_UNKNOWN;
1536 }
1537 else if (!strncmp("master", ptr + sizeof("role:") - 1, sizeof("master")-1)) {
1538 ret->role = APR_RS_SERVER_MASTER;
1539 }
1540 else {
1541 ret->role = APR_RS_SERVER_SLAVE;
1542 }
1543 if (stats) {
1544 *stats = ret;
1545 }
1546
1547 return APR_SUCCESS;
1548}
const char apr_size_t len
Definition ap_regex.h:187
char * strstr(char *s1, char *s2)
APR Poll interface.
#define hash(h, r, b, n)
Definition apr_random.c:51
#define min(a, b)
Definition apr_random.c:32
#define RC_DEL_SIZE
Definition apr_redis.c:78
#define RC_QUIT
Definition apr_redis.c:81
#define RC_RESP_1
Definition apr_redis.c:45
#define RS_NOT_STORED
Definition apr_redis.c:104
#define RC_RESP_3
Definition apr_redis.c:51
#define rc_do_stat(name, type)
Definition apr_redis.c:1456
#define RC_INFO_LEN
Definition apr_redis.c:94
#define RC_SET
Definition apr_redis.c:63
#define RC_GET
Definition apr_redis.c:57
#define RC_SET_SIZE
Definition apr_redis.c:66
apr_redis_find_server_hash(apr_redis_t *rc, const apr_uint32_t hash)
Definition apr_redis.c:158
apr_redis_delete(apr_redis_t *rc, const char *key, apr_uint32_t timeout)
Definition apr_redis.c:1005
#define RC_GET_LEN
Definition apr_redis.c:58
static void update_stats(char *info, apr_redis_stats_t *stats)
Definition apr_redis.c:1462
#define RC_RESP_4
Definition apr_redis.c:54
#define RC_SETEX_SIZE_LEN
Definition apr_redis.c:73
#define RS_NOT_FOUND_GET
Definition apr_redis.c:110
#define RC_RESP_3_LEN
Definition apr_redis.c:52
#define RS_DELETED_LEN
Definition apr_redis.c:108
#define RC_INFO_SIZE_LEN
Definition apr_redis.c:97
apr_redis_multgetp(apr_redis_t *rc, apr_pool_t *temp_pool, apr_pool_t *data_pool, apr_hash_t *values)
Definition apr_redis.c:1377
static const apr_uint32_t crc32tab[256]
Definition apr_redis.c:512
#define RC_SETEX_LEN
Definition apr_redis.c:70
#define RC_PING_SIZE_LEN
Definition apr_redis.c:91
static apr_status_t rs_find_conn(apr_redis_server_t *rs, apr_redis_conn_t **conn)
Definition apr_redis.c:236
#define RC_SETEX_SIZE
Definition apr_redis.c:72
apr_redis_incr(apr_redis_t *rc, const char *key, apr_int32_t inc, apr_uint32_t *new_value)
Definition apr_redis.c:1365
#define RC_RESP_2_LEN
Definition apr_redis.c:49
#define RS_NOT_FOUND_GET_LEN
Definition apr_redis.c:111
#define RC_GET_SIZE_LEN
Definition apr_redis.c:61
#define RC_EOL_LEN
Definition apr_redis.c:40
#define RC_DEL_SIZE_LEN
Definition apr_redis.c:79
apr_redis_info(apr_redis_server_t *rs, apr_pool_t *p, char **baton)
Definition apr_redis.c:1134
#define BUFFER_SIZE
Definition apr_redis.c:23
#define RC_QUIT_LEN
Definition apr_redis.c:82
static apr_uint64_t stat_read_uint64(char *buf)
Definition apr_redis.c:1451
apr_redis_ping(apr_redis_server_t *rs)
Definition apr_redis.c:1087
#define RC_GET_SIZE
Definition apr_redis.c:60
#define RC_EOL
Definition apr_redis.c:39
static apr_status_t rc_conn_construct(void **conn_, void *params, apr_pool_t *pool)
Definition apr_redis.c:339
apr_redis_stats(apr_redis_server_t *rs, apr_pool_t *p, apr_redis_stats_t **stats)
Definition apr_redis.c:1488
#define RC_RESP_4_LEN
Definition apr_redis.c:55
static apr_status_t conn_connect(apr_redis_conn_t *conn)
Definition apr_redis.c:303
#define RC_QUIT_SIZE_LEN
Definition apr_redis.c:85
apr_redis_find_server_hash_default(void *baton, apr_redis_t *rc, const apr_uint32_t hash)
Definition apr_redis.c:169
#define RS_NOT_FOUND_DEL
Definition apr_redis.c:113
static apr_status_t make_server_live(apr_redis_t *rc, apr_redis_server_t *rs)
Definition apr_redis.c:136
#define RC_INFO_SIZE
Definition apr_redis.c:96
static apr_status_t get_server_line(apr_redis_conn_t *conn)
Definition apr_redis.c:615
#define RS_TYPE_STRING_LEN
Definition apr_redis.c:117
#define LILBUFF_SIZE
Definition apr_redis.c:24
#define RC_SET_SIZE_LEN
Definition apr_redis.c:67
static apr_uint32_t stat_read_uint32(char *buf)
Definition apr_redis.c:1446
static apr_status_t plus_minus(apr_redis_t *rc, int incr, const char *key, apr_int32_t inc, apr_uint32_t *new_value)
Definition apr_redis.c:1233
apr_redis_version(apr_redis_server_t *rs, apr_pool_t *p, char **baton)
Definition apr_redis.c:1189
#define RS_NOT_FOUND_DEL_LEN
Definition apr_redis.c:114
#define RC_PING
Definition apr_redis.c:87
#define RV_FIELD
Definition apr_redis.c:1187
#define RC_RESP_1_LEN
Definition apr_redis.c:46
static apr_status_t make_server_dead(apr_redis_t *rc, apr_redis_server_t *rs)
Definition apr_redis.c:122
#define RC_PING_SIZE
Definition apr_redis.c:90
#define RC_DEL_LEN
Definition apr_redis.c:76
#define RS_DELETED
Definition apr_redis.c:107
static apr_status_t rs_bad_conn(apr_redis_server_t *rs, apr_redis_conn_t *conn)
Definition apr_redis.c:264
#define RS_STORED
Definition apr_redis.c:101
apr_redis_decr(apr_redis_t *rc, const char *key, apr_int32_t inc, apr_uint32_t *new_value)
Definition apr_redis.c:1371
#define RC_PING_LEN
Definition apr_redis.c:88
static apr_status_t rs_release_conn(apr_redis_server_t *rs, apr_redis_conn_t *conn)
Definition apr_redis.c:274
#define RC_QUIT_SIZE
Definition apr_redis.c:84
#define RC_RESP_2
Definition apr_redis.c:48
#define RC_SETEX
Definition apr_redis.c:69
static apr_status_t grab_bulk_resp(apr_redis_server_t *rs, apr_redis_t *rc, apr_redis_conn_t *conn, apr_pool_t *p, char **baton, apr_size_t *new_length)
Definition apr_redis.c:856
#define RC_SET_LEN
Definition apr_redis.c:64
#define RC_INFO
Definition apr_redis.c:93
#define RS_TYPE_STRING
Definition apr_redis.c:116
#define RC_DEL
Definition apr_redis.c:75
Client interface for redis.
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_ENOTIMPL
Definition apr_errno.h:476
#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_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_pool_t apr_memcache_stats_t ** stats
apr_redis_t * rc
Definition apr_redis.h:173
apr_redis_server_t * rs
Definition apr_redis.h:205
const char apr_int32_t inc
Definition apr_redis.h:337
const char apr_port_t apr_uint32_t apr_uint32_t apr_uint32_t apr_uint32_t apr_uint32_t rwto
Definition apr_redis.h:237
@ APR_RS_SERVER_MASTER
Definition apr_redis.h:375
@ APR_RS_SERVER_UNKNOWN
Definition apr_redis.h:377
@ APR_RS_SERVER_SLAVE
Definition apr_redis.h:376
@ APR_RC_SERVER_LIVE
Definition apr_redis.h:66
@ APR_RC_SERVER_DEAD
Definition apr_redis.h:67
#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
#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 * data
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
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char char ** last
#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
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_memcache_server_status_t status
apr_memcache_conn_t * conn
apr_pool_t * p
Definition apr_redis.c:29
apr_pool_t * tp
Definition apr_redis.c:30
apr_bucket_brigade * tb
Definition apr_redis.c:33
apr_size_t blen
Definition apr_redis.c:28
apr_socket_t * sock
Definition apr_redis.c:31
apr_bucket_brigade * bb
Definition apr_redis.c:32
apr_redis_server_t * rs
Definition apr_redis.c:34
apr_pool_t * p
Definition apr_redis.h:85
apr_uint32_t rwto
Definition apr_redis.h:90
apr_time_t btime
Definition apr_redis.h:89
apr_redis_server_status_t status
Definition apr_redis.h:79
const char * host
Definition apr_redis.h:77
apr_redis_conn_t * conn
Definition apr_redis.h:83
struct apr_redis_server_t::@67 version
apr_port_t port
Definition apr_redis.h:78
void * hash_baton
Definition apr_redis.h:127
apr_uint16_t nalloc
Definition apr_redis.h:123
void * server_baton
Definition apr_redis.h:129
apr_pool_t * p
Definition apr_redis.h:126
apr_uint16_t ntotal
Definition apr_redis.h:124
apr_redis_hash_func hash_func
Definition apr_redis.h:128
apr_redis_server_func server_func
Definition apr_redis.h:130
apr_redis_server_t ** live_servers
Definition apr_redis.h:125
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
IN ULONG IN INT timeout
INT info