Lines Matching refs:c
66 static void drive_machine(conn *c);
68 static int try_read_command(conn *c);
77 static enum try_read_result try_read_network(conn *c);
78 static enum try_read_result try_read_udp(conn *c);
80 static void conn_set_state(conn *c, enum conn_states state);
85 static void server_stats(ADD_STAT add_stats, conn *c);
86 static void process_stat_settings(ADD_STAT add_stats, void *c);
87 static void conn_to_str(const conn *c, char *buf);
95 static void conn_close(conn *c);
97 static bool update_event(conn *c, const int new_flags);
98 static void complete_nread(conn *c);
99 static void process_command(conn *c, char *command);
100 static void write_and_free(conn *c, char *buf, int bytes);
101 static int ensure_iov_space(conn *c);
102 static int add_iov(conn *c, const void *buf, int len);
103 static int add_chunked_item_iovs(conn *c, item *it, int len);
104 static int add_msghdr(conn *c);
105 static void write_bin_error(conn *c, protocol_binary_response_status err,
108 static void conn_free(conn *c);
132 static enum transmit_result transmit(conn *c);
256 static int add_msghdr(conn *c) in add_msghdr() argument
260 assert(c != NULL); in add_msghdr()
262 if (c->msgsize == c->msgused) { in add_msghdr()
263 msg = realloc(c->msglist, c->msgsize * 2 * sizeof(struct msghdr)); in add_msghdr()
270 c->msglist = msg; in add_msghdr()
271 c->msgsize *= 2; in add_msghdr()
274 msg = c->msglist + c->msgused; in add_msghdr()
280 msg->msg_iov = &c->iov[c->iovused]; in add_msghdr()
282 if (IS_UDP(c->transport) && c->request_addr_size > 0) { in add_msghdr()
283 msg->msg_name = &c->request_addr; in add_msghdr()
284 msg->msg_namelen = c->request_addr_size; in add_msghdr()
287 c->msgbytes = 0; in add_msghdr()
288 c->msgused++; in add_msghdr()
290 if (IS_UDP(c->transport)) { in add_msghdr()
292 return add_iov(c, NULL, UDP_HEADER_SIZE); in add_msghdr()
307 conn *c; in conn_timeout_thread() local
330 c = conns[i]; in conn_timeout_thread()
332 if (!IS_TCP(c->transport)) in conn_timeout_thread()
335 if (c->state != conn_new_cmd && c->state != conn_read) in conn_timeout_thread()
338 if ((current_time - c->last_cmd_time) > settings.idle_timeout) { in conn_timeout_thread()
341 if (write(c->thread->notify_send_fd, buf, TIMEOUT_MSG_SIZE) in conn_timeout_thread()
345 if (c->last_cmd_time < oldest_last_cmd) in conn_timeout_thread()
346 oldest_last_cmd = c->last_cmd_time; in conn_timeout_thread()
432 void conn_close_idle(conn *c) { in conn_close_idle() argument
434 (current_time - c->last_cmd_time) > settings.idle_timeout) { in conn_close_idle()
435 if (c->state != conn_new_cmd && c->state != conn_read) { in conn_close_idle()
438 "fd %d wants to timeout, but isn't in read state", c->sfd); in conn_close_idle()
443 fprintf(stderr, "Closing idle fd %d\n", c->sfd); in conn_close_idle()
445 c->thread->stats.idle_kicks++; in conn_close_idle()
447 conn_set_state(c, conn_closing); in conn_close_idle()
448 drive_machine(c); in conn_close_idle()
456 conn *c; in conn_new() local
459 c = conns[sfd]; in conn_new()
461 if (NULL == c) { in conn_new()
462 if (!(c = (conn *)calloc(1, sizeof(conn)))) { in conn_new()
469 MEMCACHED_CONN_CREATE(c); in conn_new()
471 c->rbuf = c->wbuf = 0; in conn_new()
472 c->ilist = 0; in conn_new()
473 c->suffixlist = 0; in conn_new()
474 c->iov = 0; in conn_new()
475 c->msglist = 0; in conn_new()
476 c->hdrbuf = 0; in conn_new()
478 c->rsize = read_buffer_size; in conn_new()
479 c->wsize = DATA_BUFFER_SIZE; in conn_new()
480 c->isize = ITEM_LIST_INITIAL; in conn_new()
481 c->suffixsize = SUFFIX_LIST_INITIAL; in conn_new()
482 c->iovsize = IOV_LIST_INITIAL; in conn_new()
483 c->msgsize = MSG_LIST_INITIAL; in conn_new()
484 c->hdrsize = 0; in conn_new()
486 c->rbuf = (char *)malloc((size_t)c->rsize); in conn_new()
487 c->wbuf = (char *)malloc((size_t)c->wsize); in conn_new()
488 c->ilist = (item **)malloc(sizeof(item *) * c->isize); in conn_new()
489 c->suffixlist = (char **)malloc(sizeof(char *) * c->suffixsize); in conn_new()
490 c->iov = (struct iovec *)malloc(sizeof(struct iovec) * c->iovsize); in conn_new()
491 c->msglist = (struct msghdr *)malloc(sizeof(struct msghdr) * c->msgsize); in conn_new()
493 if (c->rbuf == 0 || c->wbuf == 0 || c->ilist == 0 || c->iov == 0 || in conn_new()
494 c->msglist == 0 || c->suffixlist == 0) { in conn_new()
495 conn_free(c); in conn_new()
507 c->sfd = sfd; in conn_new()
508 conns[sfd] = c; in conn_new()
511 c->transport = transport; in conn_new()
512 c->protocol = settings.binding_protocol; in conn_new()
518 c->request_addr_size = sizeof(c->request_addr); in conn_new()
520 c->request_addr_size = 0; in conn_new()
524 if (getpeername(sfd, (struct sockaddr *) &c->request_addr, in conn_new()
525 &c->request_addr_size)) { in conn_new()
527 memset(&c->request_addr, 0, sizeof(c->request_addr)); in conn_new()
534 prot_text(c->protocol)); in conn_new()
537 } else if (c->protocol == negotiating_prot) { in conn_new()
540 } else if (c->protocol == ascii_prot) { in conn_new()
542 } else if (c->protocol == binary_prot) { in conn_new()
546 sfd, c->protocol); in conn_new()
551 c->state = init_state; in conn_new()
552 c->rlbytes = 0; in conn_new()
553 c->cmd = -1; in conn_new()
554 c->rbytes = c->wbytes = 0; in conn_new()
555 c->wcurr = c->wbuf; in conn_new()
556 c->rcurr = c->rbuf; in conn_new()
557 c->ritem = 0; in conn_new()
558 c->icurr = c->ilist; in conn_new()
559 c->suffixcurr = c->suffixlist; in conn_new()
560 c->ileft = 0; in conn_new()
561 c->suffixleft = 0; in conn_new()
562 c->iovused = 0; in conn_new()
563 c->msgcurr = 0; in conn_new()
564 c->msgused = 0; in conn_new()
565 c->authenticated = false; in conn_new()
566 c->last_cmd_time = current_time; /* initialize for idle kicker */ in conn_new()
568 c->write_and_go = init_state; in conn_new()
569 c->write_and_free = 0; in conn_new()
570 c->item = 0; in conn_new()
572 c->noreply = false; in conn_new()
574 event_set(&c->event, sfd, event_flags, event_handler, (void *)c); in conn_new()
575 event_base_set(base, &c->event); in conn_new()
576 c->ev_flags = event_flags; in conn_new()
578 if (event_add(&c->event, 0) == -1) { in conn_new()
588 MEMCACHED_CONN_ALLOCATE(c->sfd); in conn_new()
590 return c; in conn_new()
593 static void conn_release_items(conn *c) { in conn_release_items() argument
594 assert(c != NULL); in conn_release_items()
596 if (c->item) { in conn_release_items()
597 item_remove(c->item); in conn_release_items()
598 c->item = 0; in conn_release_items()
601 while (c->ileft > 0) { in conn_release_items()
602 item *it = *(c->icurr); in conn_release_items()
605 c->icurr++; in conn_release_items()
606 c->ileft--; in conn_release_items()
609 if (c->suffixleft != 0) { in conn_release_items()
610 for (; c->suffixleft > 0; c->suffixleft--, c->suffixcurr++) { in conn_release_items()
611 cache_free(c->thread->suffix_cache, *(c->suffixcurr)); in conn_release_items()
615 c->icurr = c->ilist; in conn_release_items()
616 c->suffixcurr = c->suffixlist; in conn_release_items()
619 static void conn_cleanup(conn *c) { in conn_cleanup() argument
620 assert(c != NULL); in conn_cleanup()
622 conn_release_items(c); in conn_cleanup()
624 if (c->write_and_free) { in conn_cleanup()
625 free(c->write_and_free); in conn_cleanup()
626 c->write_and_free = 0; in conn_cleanup()
629 if (c->sasl_conn) { in conn_cleanup()
631 sasl_dispose(&c->sasl_conn); in conn_cleanup()
632 c->sasl_conn = NULL; in conn_cleanup()
635 if (IS_UDP(c->transport)) { in conn_cleanup()
636 conn_set_state(c, conn_read); in conn_cleanup()
643 void conn_free(conn *c) { in conn_free() argument
644 if (c) { in conn_free()
645 assert(c != NULL); in conn_free()
646 assert(c->sfd >= 0 && c->sfd < max_fds); in conn_free()
648 MEMCACHED_CONN_DESTROY(c); in conn_free()
649 conns[c->sfd] = NULL; in conn_free()
650 if (c->hdrbuf) in conn_free()
651 free(c->hdrbuf); in conn_free()
652 if (c->msglist) in conn_free()
653 free(c->msglist); in conn_free()
654 if (c->rbuf) in conn_free()
655 free(c->rbuf); in conn_free()
656 if (c->wbuf) in conn_free()
657 free(c->wbuf); in conn_free()
658 if (c->ilist) in conn_free()
659 free(c->ilist); in conn_free()
660 if (c->suffixlist) in conn_free()
661 free(c->suffixlist); in conn_free()
662 if (c->iov) in conn_free()
663 free(c->iov); in conn_free()
664 free(c); in conn_free()
668 static void conn_close(conn *c) { in conn_close() argument
669 assert(c != NULL); in conn_close()
672 event_del(&c->event); in conn_close()
675 fprintf(stderr, "<%d connection closed.\n", c->sfd); in conn_close()
677 conn_cleanup(c); in conn_close()
679 MEMCACHED_CONN_RELEASE(c->sfd); in conn_close()
680 conn_set_state(c, conn_closed); in conn_close()
681 close(c->sfd); in conn_close()
702 static void conn_shrink(conn *c) { in conn_shrink() argument
703 assert(c != NULL); in conn_shrink()
705 if (IS_UDP(c->transport)) in conn_shrink()
708 if (c->rsize > READ_BUFFER_HIGHWAT && c->rbytes < DATA_BUFFER_SIZE) { in conn_shrink()
711 if (c->rcurr != c->rbuf) in conn_shrink()
712 memmove(c->rbuf, c->rcurr, (size_t)c->rbytes); in conn_shrink()
714 newbuf = (char *)realloc((void *)c->rbuf, DATA_BUFFER_SIZE); in conn_shrink()
717 c->rbuf = newbuf; in conn_shrink()
718 c->rsize = DATA_BUFFER_SIZE; in conn_shrink()
721 c->rcurr = c->rbuf; in conn_shrink()
724 if (c->isize > ITEM_LIST_HIGHWAT) { in conn_shrink()
725 item **newbuf = (item**) realloc((void *)c->ilist, ITEM_LIST_INITIAL * sizeof(c->ilist[0])); in conn_shrink()
727 c->ilist = newbuf; in conn_shrink()
728 c->isize = ITEM_LIST_INITIAL; in conn_shrink()
733 if (c->msgsize > MSG_LIST_HIGHWAT) { in conn_shrink()
734 …truct msghdr *newbuf = (struct msghdr *) realloc((void *)c->msglist, MSG_LIST_INITIAL * sizeof(c->… in conn_shrink()
736 c->msglist = newbuf; in conn_shrink()
737 c->msgsize = MSG_LIST_INITIAL; in conn_shrink()
742 if (c->iovsize > IOV_LIST_HIGHWAT) { in conn_shrink()
743 …struct iovec *newbuf = (struct iovec *) realloc((void *)c->iov, IOV_LIST_INITIAL * sizeof(c->iov[0… in conn_shrink()
745 c->iov = newbuf; in conn_shrink()
746 c->iovsize = IOV_LIST_INITIAL; in conn_shrink()
776 static void conn_set_state(conn *c, enum conn_states state) { in conn_set_state() argument
777 assert(c != NULL); in conn_set_state()
780 if (state != c->state) { in conn_set_state()
783 c->sfd, state_text(c->state), in conn_set_state()
788 MEMCACHED_PROCESS_COMMAND_END(c->sfd, c->wbuf, c->wbytes); in conn_set_state()
790 c->state = state; in conn_set_state()
800 static int ensure_iov_space(conn *c) { in ensure_iov_space() argument
801 assert(c != NULL); in ensure_iov_space()
803 if (c->iovused >= c->iovsize) { in ensure_iov_space()
805 struct iovec *new_iov = (struct iovec *)realloc(c->iov, in ensure_iov_space()
806 (c->iovsize * 2) * sizeof(struct iovec)); in ensure_iov_space()
813 c->iov = new_iov; in ensure_iov_space()
814 c->iovsize *= 2; in ensure_iov_space()
817 for (i = 0, iovnum = 0; i < c->msgused; i++) { in ensure_iov_space()
818 c->msglist[i].msg_iov = &c->iov[iovnum]; in ensure_iov_space()
819 iovnum += c->msglist[i].msg_iovlen; in ensure_iov_space()
834 static int add_iov(conn *c, const void *buf, int len) { in add_iov() argument
839 assert(c != NULL); in add_iov()
842 m = &c->msglist[c->msgused - 1]; in add_iov()
848 limit_to_mtu = IS_UDP(c->transport) || (1 == c->msgused); in add_iov()
852 (limit_to_mtu && c->msgbytes >= UDP_MAX_PAYLOAD_SIZE)) { in add_iov()
853 add_msghdr(c); in add_iov()
854 m = &c->msglist[c->msgused - 1]; in add_iov()
857 if (ensure_iov_space(c) != 0) in add_iov()
861 if (limit_to_mtu && len + c->msgbytes > UDP_MAX_PAYLOAD_SIZE) { in add_iov()
862 leftover = len + c->msgbytes - UDP_MAX_PAYLOAD_SIZE; in add_iov()
868 m = &c->msglist[c->msgused - 1]; in add_iov()
872 c->msgbytes += len; in add_iov()
873 c->iovused++; in add_iov()
883 static int add_chunked_item_iovs(conn *c, item *it, int len) { in add_chunked_item_iovs() argument
888 if (add_iov(c, ch->data, todo) != 0) { in add_chunked_item_iovs()
900 static int build_udp_headers(conn *c) { in build_udp_headers() argument
904 assert(c != NULL); in build_udp_headers()
906 if (c->msgused > c->hdrsize) { in build_udp_headers()
908 if (c->hdrbuf) { in build_udp_headers()
909 new_hdrbuf = realloc(c->hdrbuf, c->msgused * 2 * UDP_HEADER_SIZE); in build_udp_headers()
911 new_hdrbuf = malloc(c->msgused * 2 * UDP_HEADER_SIZE); in build_udp_headers()
920 c->hdrbuf = (unsigned char *)new_hdrbuf; in build_udp_headers()
921 c->hdrsize = c->msgused * 2; in build_udp_headers()
924 hdr = c->hdrbuf; in build_udp_headers()
925 for (i = 0; i < c->msgused; i++) { in build_udp_headers()
926 c->msglist[i].msg_iov[0].iov_base = (void*)hdr; in build_udp_headers()
927 c->msglist[i].msg_iov[0].iov_len = UDP_HEADER_SIZE; in build_udp_headers()
928 *hdr++ = c->request_id / 256; in build_udp_headers()
929 *hdr++ = c->request_id % 256; in build_udp_headers()
932 *hdr++ = c->msgused / 256; in build_udp_headers()
933 *hdr++ = c->msgused % 256; in build_udp_headers()
936 assert((void *) hdr == (caddr_t)c->msglist[i].msg_iov[0].iov_base + UDP_HEADER_SIZE); in build_udp_headers()
943 static void out_string(conn *c, const char *str) { in out_string() argument
946 assert(c != NULL); in out_string()
948 if (c->noreply) { in out_string()
950 fprintf(stderr, ">%d NOREPLY %s\n", c->sfd, str); in out_string()
951 c->noreply = false; in out_string()
952 conn_set_state(c, conn_new_cmd); in out_string()
957 fprintf(stderr, ">%d %s\n", c->sfd, str); in out_string()
960 c->msgcurr = 0; in out_string()
961 c->msgused = 0; in out_string()
962 c->iovused = 0; in out_string()
963 add_msghdr(c); in out_string()
966 if ((len + 2) > c->wsize) { in out_string()
972 memcpy(c->wbuf, str, len); in out_string()
973 memcpy(c->wbuf + len, "\r\n", 2); in out_string()
974 c->wbytes = len + 2; in out_string()
975 c->wcurr = c->wbuf; in out_string()
977 conn_set_state(c, conn_write); in out_string()
978 c->write_and_go = conn_new_cmd; in out_string()
986 static void out_of_memory(conn *c, char *ascii_error) { in out_of_memory() argument
990 if (c->protocol == binary_prot) { in out_of_memory()
995 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, ascii_error, 0); in out_of_memory()
997 out_string(c, ascii_error); in out_of_memory()
1005 static void complete_nread_ascii(conn *c) { in complete_nread_ascii() argument
1006 assert(c != NULL); in complete_nread_ascii()
1008 item *it = c->item; in complete_nread_ascii()
1009 int comm = c->cmd; in complete_nread_ascii()
1013 pthread_mutex_lock(&c->thread->stats.mutex); in complete_nread_ascii()
1014 c->thread->stats.slab_stats[ITEM_clsid(it)].set_cmds++; in complete_nread_ascii()
1015 pthread_mutex_unlock(&c->thread->stats.mutex); in complete_nread_ascii()
1024 item_chunk *ch = (item_chunk *) c->ritem; in complete_nread_ascii()
1046 out_string(c, "CLIENT_ERROR bad data chunk"); in complete_nread_ascii()
1048 ret = store_item(it, comm, c); in complete_nread_ascii()
1052 switch (c->cmd) { in complete_nread_ascii()
1054 MEMCACHED_COMMAND_ADD(c->sfd, ITEM_key(it), it->nkey, in complete_nread_ascii()
1058 MEMCACHED_COMMAND_REPLACE(c->sfd, ITEM_key(it), it->nkey, in complete_nread_ascii()
1062 MEMCACHED_COMMAND_APPEND(c->sfd, ITEM_key(it), it->nkey, in complete_nread_ascii()
1066 MEMCACHED_COMMAND_PREPEND(c->sfd, ITEM_key(it), it->nkey, in complete_nread_ascii()
1070 MEMCACHED_COMMAND_SET(c->sfd, ITEM_key(it), it->nkey, in complete_nread_ascii()
1074 MEMCACHED_COMMAND_CAS(c->sfd, ITEM_key(it), it->nkey, it->nbytes, in complete_nread_ascii()
1082 out_string(c, "STORED"); in complete_nread_ascii()
1085 out_string(c, "EXISTS"); in complete_nread_ascii()
1088 out_string(c, "NOT_FOUND"); in complete_nread_ascii()
1091 out_string(c, "NOT_STORED"); in complete_nread_ascii()
1094 out_string(c, "SERVER_ERROR Unhandled storage type."); in complete_nread_ascii()
1099 item_remove(c->item); /* release the c->item reference */ in complete_nread_ascii()
1100 c->item = 0; in complete_nread_ascii()
1106 static void* binary_get_request(conn *c) { in binary_get_request() argument
1107 char *ret = c->rcurr; in binary_get_request()
1108 ret -= (sizeof(c->binary_header) + c->binary_header.request.keylen + in binary_get_request()
1109 c->binary_header.request.extlen); in binary_get_request()
1111 assert(ret >= c->rbuf); in binary_get_request()
1118 static char* binary_get_key(conn *c) { in binary_get_key() argument
1119 return c->rcurr - (c->binary_header.request.keylen); in binary_get_key()
1122 static void add_bin_header(conn *c, uint16_t err, uint8_t hdr_len, uint16_t key_len, uint32_t body_… in add_bin_header() argument
1125 assert(c); in add_bin_header()
1127 c->msgcurr = 0; in add_bin_header()
1128 c->msgused = 0; in add_bin_header()
1129 c->iovused = 0; in add_bin_header()
1130 if (add_msghdr(c) != 0) { in add_bin_header()
1134 out_of_memory(c, "SERVER_ERROR out of memory adding binary header"); in add_bin_header()
1138 header = (protocol_binary_response_header *)c->wbuf; in add_bin_header()
1141 header->response.opcode = c->binary_header.request.opcode; in add_bin_header()
1149 header->response.opaque = c->opaque; in add_bin_header()
1150 header->response.cas = htonll(c->cas); in add_bin_header()
1154 fprintf(stderr, ">%d Writing bin response:", c->sfd); in add_bin_header()
1157 fprintf(stderr, "\n>%d ", c->sfd); in add_bin_header()
1164 add_iov(c, c->wbuf, sizeof(header->response)); in add_bin_header()
1172 static void write_bin_error(conn *c, protocol_binary_response_status err, in write_bin_error() argument
1208 fprintf(stderr, ">%d UNHANDLED ERROR: %d\n", c->sfd, err); in write_bin_error()
1213 fprintf(stderr, ">%d Writing an error: %s\n", c->sfd, errstr); in write_bin_error()
1217 add_bin_header(c, err, 0, 0, len); in write_bin_error()
1219 add_iov(c, errstr, len); in write_bin_error()
1221 conn_set_state(c, conn_mwrite); in write_bin_error()
1223 c->sbytes = swallow; in write_bin_error()
1224 c->write_and_go = conn_swallow; in write_bin_error()
1226 c->write_and_go = conn_new_cmd; in write_bin_error()
1231 static void write_bin_response(conn *c, void *d, int hlen, int keylen, int dlen) { in write_bin_response() argument
1232 if (!c->noreply || c->cmd == PROTOCOL_BINARY_CMD_GET || in write_bin_response()
1233 c->cmd == PROTOCOL_BINARY_CMD_GETK) { in write_bin_response()
1234 add_bin_header(c, 0, hlen, keylen, dlen); in write_bin_response()
1236 add_iov(c, d, dlen); in write_bin_response()
1238 conn_set_state(c, conn_mwrite); in write_bin_response()
1239 c->write_and_go = conn_new_cmd; in write_bin_response()
1241 conn_set_state(c, conn_new_cmd); in write_bin_response()
1245 static void complete_incr_bin(conn *c) { in complete_incr_bin() argument
1253 protocol_binary_response_incr* rsp = (protocol_binary_response_incr*)c->wbuf; in complete_incr_bin()
1254 protocol_binary_request_incr* req = binary_get_request(c); in complete_incr_bin()
1256 assert(c != NULL); in complete_incr_bin()
1257 assert(c->wsize >= sizeof(*rsp)); in complete_incr_bin()
1263 key = binary_get_key(c); in complete_incr_bin()
1264 nkey = c->binary_header.request.keylen; in complete_incr_bin()
1279 if (c->binary_header.request.cas != 0) { in complete_incr_bin()
1280 cas = c->binary_header.request.cas; in complete_incr_bin()
1282 switch(add_delta(c, key, nkey, c->cmd == PROTOCOL_BINARY_CMD_INCREMENT, in complete_incr_bin()
1288 c->cas = cas; in complete_incr_bin()
1290 write_bin_response(c, &rsp->message.body, 0, 0, in complete_incr_bin()
1294 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_DELTA_BADVAL, NULL, 0); in complete_incr_bin()
1297 out_of_memory(c, "SERVER_ERROR Out of memory incrementing value"); in complete_incr_bin()
1314 if (store_item(it, NREAD_ADD, c)) { in complete_incr_bin()
1315 c->cas = ITEM_get_cas(it); in complete_incr_bin()
1316 … write_bin_response(c, &rsp->message.body, 0, 0, sizeof(rsp->message.body.value)); in complete_incr_bin()
1318 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_NOT_STORED, in complete_incr_bin()
1323 out_of_memory(c, in complete_incr_bin()
1327 pthread_mutex_lock(&c->thread->stats.mutex); in complete_incr_bin()
1328 if (c->cmd == PROTOCOL_BINARY_CMD_INCREMENT) { in complete_incr_bin()
1329 c->thread->stats.incr_misses++; in complete_incr_bin()
1331 c->thread->stats.decr_misses++; in complete_incr_bin()
1333 pthread_mutex_unlock(&c->thread->stats.mutex); in complete_incr_bin()
1335 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, NULL, 0); in complete_incr_bin()
1339 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS, NULL, 0); in complete_incr_bin()
1344 static void complete_update_bin(conn *c) { in complete_update_bin() argument
1347 assert(c != NULL); in complete_update_bin()
1349 item *it = c->item; in complete_update_bin()
1351 pthread_mutex_lock(&c->thread->stats.mutex); in complete_update_bin()
1352 c->thread->stats.slab_stats[ITEM_clsid(it)].set_cmds++; in complete_update_bin()
1353 pthread_mutex_unlock(&c->thread->stats.mutex); in complete_update_bin()
1361 assert(c->ritem); in complete_update_bin()
1362 item_chunk *ch = (item_chunk *) c->ritem; in complete_update_bin()
1378 ret = store_item(it, c->cmd, c); in complete_update_bin()
1382 switch (c->cmd) { in complete_update_bin()
1384 MEMCACHED_COMMAND_ADD(c->sfd, ITEM_key(it), it->nkey, in complete_update_bin()
1388 MEMCACHED_COMMAND_REPLACE(c->sfd, ITEM_key(it), it->nkey, in complete_update_bin()
1392 MEMCACHED_COMMAND_APPEND(c->sfd, ITEM_key(it), it->nkey, in complete_update_bin()
1396 MEMCACHED_COMMAND_PREPEND(c->sfd, ITEM_key(it), it->nkey, in complete_update_bin()
1400 MEMCACHED_COMMAND_SET(c->sfd, ITEM_key(it), it->nkey, in complete_update_bin()
1409 write_bin_response(c, NULL, 0, 0, 0); in complete_update_bin()
1412 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS, NULL, 0); in complete_update_bin()
1415 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, NULL, 0); in complete_update_bin()
1420 if (c->cmd == NREAD_ADD) { in complete_update_bin()
1422 } else if(c->cmd == NREAD_REPLACE) { in complete_update_bin()
1427 write_bin_error(c, eno, NULL, 0); in complete_update_bin()
1430 item_remove(c->item); /* release the c->item reference */ in complete_update_bin()
1431 c->item = 0; in complete_update_bin()
1434 static void process_bin_get_or_touch(conn *c) { in process_bin_get_or_touch() argument
1437 protocol_binary_response_get* rsp = (protocol_binary_response_get*)c->wbuf; in process_bin_get_or_touch()
1438 char* key = binary_get_key(c); in process_bin_get_or_touch()
1439 size_t nkey = c->binary_header.request.keylen; in process_bin_get_or_touch()
1440 int should_touch = (c->cmd == PROTOCOL_BINARY_CMD_TOUCH || in process_bin_get_or_touch()
1441 c->cmd == PROTOCOL_BINARY_CMD_GAT || in process_bin_get_or_touch()
1442 c->cmd == PROTOCOL_BINARY_CMD_GATK); in process_bin_get_or_touch()
1443 int should_return_key = (c->cmd == PROTOCOL_BINARY_CMD_GETK || in process_bin_get_or_touch()
1444 c->cmd == PROTOCOL_BINARY_CMD_GATK); in process_bin_get_or_touch()
1445 int should_return_value = (c->cmd != PROTOCOL_BINARY_CMD_TOUCH); in process_bin_get_or_touch()
1448 fprintf(stderr, "<%d %s ", c->sfd, should_touch ? "TOUCH" : "GET"); in process_bin_get_or_touch()
1454 protocol_binary_request_touch *t = binary_get_request(c); in process_bin_get_or_touch()
1457 it = item_touch(key, nkey, realtime(exptime), c); in process_bin_get_or_touch()
1459 it = item_get(key, nkey, c); in process_bin_get_or_touch()
1468 pthread_mutex_lock(&c->thread->stats.mutex); in process_bin_get_or_touch()
1470 c->thread->stats.touch_cmds++; in process_bin_get_or_touch()
1471 c->thread->stats.slab_stats[ITEM_clsid(it)].touch_hits++; in process_bin_get_or_touch()
1473 c->thread->stats.get_cmds++; in process_bin_get_or_touch()
1474 c->thread->stats.slab_stats[ITEM_clsid(it)].get_hits++; in process_bin_get_or_touch()
1476 pthread_mutex_unlock(&c->thread->stats.mutex); in process_bin_get_or_touch()
1479 MEMCACHED_COMMAND_TOUCH(c->sfd, ITEM_key(it), it->nkey, in process_bin_get_or_touch()
1482 MEMCACHED_COMMAND_GET(c->sfd, ITEM_key(it), it->nkey, in process_bin_get_or_touch()
1486 if (c->cmd == PROTOCOL_BINARY_CMD_TOUCH) { in process_bin_get_or_touch()
1493 add_bin_header(c, 0, sizeof(rsp->message.body), keylen, bodylen); in process_bin_get_or_touch()
1498 add_iov(c, &rsp->message.body, sizeof(rsp->message.body)); in process_bin_get_or_touch()
1501 add_iov(c, ITEM_key(it), nkey); in process_bin_get_or_touch()
1507 add_iov(c, ITEM_data(it), it->nbytes - 2); in process_bin_get_or_touch()
1509 add_chunked_item_iovs(c, it, it->nbytes - 2); in process_bin_get_or_touch()
1513 conn_set_state(c, conn_mwrite); in process_bin_get_or_touch()
1514 c->write_and_go = conn_new_cmd; in process_bin_get_or_touch()
1516 c->item = it; in process_bin_get_or_touch()
1518 pthread_mutex_lock(&c->thread->stats.mutex); in process_bin_get_or_touch()
1520 c->thread->stats.touch_cmds++; in process_bin_get_or_touch()
1521 c->thread->stats.touch_misses++; in process_bin_get_or_touch()
1523 c->thread->stats.get_cmds++; in process_bin_get_or_touch()
1524 c->thread->stats.get_misses++; in process_bin_get_or_touch()
1526 pthread_mutex_unlock(&c->thread->stats.mutex); in process_bin_get_or_touch()
1529 MEMCACHED_COMMAND_TOUCH(c->sfd, key, nkey, -1, 0); in process_bin_get_or_touch()
1531 MEMCACHED_COMMAND_GET(c->sfd, key, nkey, -1, 0); in process_bin_get_or_touch()
1534 if (c->noreply) { in process_bin_get_or_touch()
1535 conn_set_state(c, conn_new_cmd); in process_bin_get_or_touch()
1538 char *ofs = c->wbuf + sizeof(protocol_binary_response_header); in process_bin_get_or_touch()
1539 add_bin_header(c, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, in process_bin_get_or_touch()
1542 add_iov(c, ofs, nkey); in process_bin_get_or_touch()
1543 conn_set_state(c, conn_mwrite); in process_bin_get_or_touch()
1544 c->write_and_go = conn_new_cmd; in process_bin_get_or_touch()
1546 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, in process_bin_get_or_touch()
1559 conn *c) { in append_bin_stats() argument
1560 char *buf = c->stats.buffer + c->stats.offset; in append_bin_stats()
1568 .response.opaque = c->opaque in append_bin_stats()
1583 c->stats.offset += sizeof(header.response) + bodylen; in append_bin_stats()
1588 conn *c) { in append_ascii_stats() argument
1589 char *pos = c->stats.buffer + c->stats.offset; in append_ascii_stats()
1591 int remaining = c->stats.size - c->stats.offset; in append_ascii_stats()
1602 c->stats.offset += nbytes; in append_ascii_stats()
1605 static bool grow_stats_buf(conn *c, size_t needed) { in grow_stats_buf() argument
1606 size_t nsize = c->stats.size; in grow_stats_buf()
1607 size_t available = nsize - c->stats.offset; in grow_stats_buf()
1611 if (c->stats.buffer == NULL) { in grow_stats_buf()
1613 available = c->stats.size = c->stats.offset = 0; in grow_stats_buf()
1619 available = nsize - c->stats.offset; in grow_stats_buf()
1622 if (nsize != c->stats.size) { in grow_stats_buf()
1623 char *ptr = realloc(c->stats.buffer, nsize); in grow_stats_buf()
1625 c->stats.buffer = ptr; in grow_stats_buf()
1626 c->stats.size = nsize; in grow_stats_buf()
1647 conn *c = (conn*)cookie; in append_stats() local
1649 if (c->protocol == binary_prot) { in append_stats()
1651 if (!grow_stats_buf(c, needed)) { in append_stats()
1654 append_bin_stats(key, klen, val, vlen, c); in append_stats()
1657 if (!grow_stats_buf(c, needed)) { in append_stats()
1660 append_ascii_stats(key, klen, val, vlen, c); in append_stats()
1663 assert(c->stats.offset <= c->stats.size); in append_stats()
1666 static void process_bin_stat(conn *c) { in process_bin_stat() argument
1667 char *subcommand = binary_get_key(c); in process_bin_stat()
1668 size_t nkey = c->binary_header.request.keylen; in process_bin_stat()
1672 fprintf(stderr, "<%d STATS ", c->sfd); in process_bin_stat()
1681 server_stats(&append_stats, c); in process_bin_stat()
1682 (void)get_stats(NULL, 0, &append_stats, c); in process_bin_stat()
1686 process_stat_settings(&append_stats, c); in process_bin_stat()
1693 out_of_memory(c, "SERVER_ERROR Out of memory generating stats"); in process_bin_stat()
1696 append_stats("detailed", strlen("detailed"), dump_buf, len, c); in process_bin_stat()
1704 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, NULL, 0); in process_bin_stat()
1708 if (get_stats(subcommand, nkey, &append_stats, c)) { in process_bin_stat()
1709 if (c->stats.buffer == NULL) { in process_bin_stat()
1710 out_of_memory(c, "SERVER_ERROR Out of memory generating stats"); in process_bin_stat()
1712 write_and_free(c, c->stats.buffer, c->stats.offset); in process_bin_stat()
1713 c->stats.buffer = NULL; in process_bin_stat()
1716 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, NULL, 0); in process_bin_stat()
1723 append_stats(NULL, 0, NULL, 0, c); in process_bin_stat()
1724 if (c->stats.buffer == NULL) { in process_bin_stat()
1725 out_of_memory(c, "SERVER_ERROR Out of memory preparing to send stats"); in process_bin_stat()
1727 write_and_free(c, c->stats.buffer, c->stats.offset); in process_bin_stat()
1728 c->stats.buffer = NULL; in process_bin_stat()
1732 static void bin_read_key(conn *c, enum bin_substates next_substate, int extra) { in bin_read_key() argument
1733 assert(c); in bin_read_key()
1734 c->substate = next_substate; in bin_read_key()
1735 c->rlbytes = c->keylen + extra; in bin_read_key()
1738 ptrdiff_t offset = c->rcurr + sizeof(protocol_binary_request_header) - c->rbuf; in bin_read_key()
1739 if (c->rlbytes > c->rsize - offset) { in bin_read_key()
1740 size_t nsize = c->rsize; in bin_read_key()
1741 size_t size = c->rlbytes + sizeof(protocol_binary_request_header); in bin_read_key()
1747 if (nsize != c->rsize) { in bin_read_key()
1750 c->sfd, (unsigned long)c->rsize, (unsigned long)nsize); in bin_read_key()
1752 char *newm = realloc(c->rbuf, nsize); in bin_read_key()
1759 c->sfd); in bin_read_key()
1761 conn_set_state(c, conn_closing); in bin_read_key()
1765 c->rbuf= newm; in bin_read_key()
1767 c->rcurr = c->rbuf + offset - sizeof(protocol_binary_request_header); in bin_read_key()
1768 c->rsize = nsize; in bin_read_key()
1770 if (c->rbuf != c->rcurr) { in bin_read_key()
1771 memmove(c->rbuf, c->rcurr, c->rbytes); in bin_read_key()
1772 c->rcurr = c->rbuf; in bin_read_key()
1774 fprintf(stderr, "%d: Repack input buffer\n", c->sfd); in bin_read_key()
1780 c->ritem = c->rcurr + sizeof(protocol_binary_request_header); in bin_read_key()
1781 conn_set_state(c, conn_nread); in bin_read_key()
1785 static void handle_binary_protocol_error(conn *c) { in handle_binary_protocol_error() argument
1786 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_EINVAL, NULL, 0); in handle_binary_protocol_error()
1789 c->binary_header.request.opcode, c->sfd); in handle_binary_protocol_error()
1791 c->write_and_go = conn_closing; in handle_binary_protocol_error()
1794 static void init_sasl_conn(conn *c) { in init_sasl_conn() argument
1795 assert(c); in init_sasl_conn()
1800 c->authenticated = false; in init_sasl_conn()
1802 if (!c->sasl_conn) { in init_sasl_conn()
1807 NULL, 0, &c->sasl_conn); in init_sasl_conn()
1812 c->sasl_conn = NULL; in init_sasl_conn()
1817 static void bin_list_sasl_mechs(conn *c) { in bin_list_sasl_mechs() argument
1820 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND, NULL, in bin_list_sasl_mechs()
1821 c->binary_header.request.bodylen in bin_list_sasl_mechs()
1822 - c->binary_header.request.keylen); in bin_list_sasl_mechs()
1826 init_sasl_conn(c); in bin_list_sasl_mechs()
1829 int result=sasl_listmech(c->sasl_conn, NULL, in bin_list_sasl_mechs()
1840 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR, NULL, 0); in bin_list_sasl_mechs()
1843 write_bin_response(c, (char*)result_string, 0, 0, string_length); in bin_list_sasl_mechs()
1846 static void process_bin_sasl_auth(conn *c) { in process_bin_sasl_auth() argument
1849 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND, NULL, in process_bin_sasl_auth()
1850 c->binary_header.request.bodylen in process_bin_sasl_auth()
1851 - c->binary_header.request.keylen); in process_bin_sasl_auth()
1855 assert(c->binary_header.request.extlen == 0); in process_bin_sasl_auth()
1857 int nkey = c->binary_header.request.keylen; in process_bin_sasl_auth()
1858 int vlen = c->binary_header.request.bodylen - nkey; in process_bin_sasl_auth()
1861 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_EINVAL, NULL, vlen); in process_bin_sasl_auth()
1862 c->write_and_go = conn_swallow; in process_bin_sasl_auth()
1866 char *key = binary_get_key(c); in process_bin_sasl_auth()
1873 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, NULL, vlen); in process_bin_sasl_auth()
1874 c->write_and_go = conn_swallow; in process_bin_sasl_auth()
1878 c->item = it; in process_bin_sasl_auth()
1879 c->ritem = ITEM_data(it); in process_bin_sasl_auth()
1880 c->rlbytes = vlen; in process_bin_sasl_auth()
1881 conn_set_state(c, conn_nread); in process_bin_sasl_auth()
1882 c->substate = bin_reading_sasl_auth_data; in process_bin_sasl_auth()
1885 static void process_bin_complete_sasl_auth(conn *c) { in process_bin_complete_sasl_auth() argument
1890 assert(c->item); in process_bin_complete_sasl_auth()
1891 init_sasl_conn(c); in process_bin_complete_sasl_auth()
1893 int nkey = c->binary_header.request.keylen; in process_bin_complete_sasl_auth()
1894 int vlen = c->binary_header.request.bodylen - nkey; in process_bin_complete_sasl_auth()
1897 memcpy(mech, ITEM_key((item*)c->item), nkey); in process_bin_complete_sasl_auth()
1903 const char *challenge = vlen == 0 ? NULL : ITEM_data((item*) c->item); in process_bin_complete_sasl_auth()
1907 switch (c->cmd) { in process_bin_complete_sasl_auth()
1909 result = sasl_server_start(c->sasl_conn, mech, in process_bin_complete_sasl_auth()
1914 result = sasl_server_step(c->sasl_conn, in process_bin_complete_sasl_auth()
1924 c->cmd, challenge); in process_bin_complete_sasl_auth()
1929 item_unlink(c->item); in process_bin_complete_sasl_auth()
1937 c->authenticated = true; in process_bin_complete_sasl_auth()
1938 write_bin_response(c, "Authenticated", 0, 0, strlen("Authenticated")); in process_bin_complete_sasl_auth()
1939 pthread_mutex_lock(&c->thread->stats.mutex); in process_bin_complete_sasl_auth()
1940 c->thread->stats.auth_cmds++; in process_bin_complete_sasl_auth()
1941 pthread_mutex_unlock(&c->thread->stats.mutex); in process_bin_complete_sasl_auth()
1944 add_bin_header(c, PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE, 0, 0, outlen); in process_bin_complete_sasl_auth()
1946 add_iov(c, out, outlen); in process_bin_complete_sasl_auth()
1948 conn_set_state(c, conn_mwrite); in process_bin_complete_sasl_auth()
1949 c->write_and_go = conn_new_cmd; in process_bin_complete_sasl_auth()
1954 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR, NULL, 0); in process_bin_complete_sasl_auth()
1955 pthread_mutex_lock(&c->thread->stats.mutex); in process_bin_complete_sasl_auth()
1956 c->thread->stats.auth_cmds++; in process_bin_complete_sasl_auth()
1957 c->thread->stats.auth_errors++; in process_bin_complete_sasl_auth()
1958 pthread_mutex_unlock(&c->thread->stats.mutex); in process_bin_complete_sasl_auth()
1962 static bool authenticated(conn *c) { in authenticated() argument
1966 switch (c->cmd) { in authenticated()
1974 rv = c->authenticated; in authenticated()
1979 c->cmd, rv ? "true" : "false"); in authenticated()
1985 static void dispatch_bin_command(conn *c) { in dispatch_bin_command() argument
1988 int extlen = c->binary_header.request.extlen; in dispatch_bin_command()
1989 int keylen = c->binary_header.request.keylen; in dispatch_bin_command()
1990 uint32_t bodylen = c->binary_header.request.bodylen; in dispatch_bin_command()
1992 if (settings.sasl && !authenticated(c)) { in dispatch_bin_command()
1993 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR, NULL, 0); in dispatch_bin_command()
1994 c->write_and_go = conn_closing; in dispatch_bin_command()
1998 MEMCACHED_PROCESS_COMMAND_START(c->sfd, c->rcurr, c->rbytes); in dispatch_bin_command()
1999 c->noreply = true; in dispatch_bin_command()
2003 handle_binary_protocol_error(c); in dispatch_bin_command()
2007 switch (c->cmd) { in dispatch_bin_command()
2009 c->cmd = PROTOCOL_BINARY_CMD_SET; in dispatch_bin_command()
2012 c->cmd = PROTOCOL_BINARY_CMD_ADD; in dispatch_bin_command()
2015 c->cmd = PROTOCOL_BINARY_CMD_REPLACE; in dispatch_bin_command()
2018 c->cmd = PROTOCOL_BINARY_CMD_DELETE; in dispatch_bin_command()
2021 c->cmd = PROTOCOL_BINARY_CMD_INCREMENT; in dispatch_bin_command()
2024 c->cmd = PROTOCOL_BINARY_CMD_DECREMENT; in dispatch_bin_command()
2027 c->cmd = PROTOCOL_BINARY_CMD_QUIT; in dispatch_bin_command()
2030 c->cmd = PROTOCOL_BINARY_CMD_FLUSH; in dispatch_bin_command()
2033 c->cmd = PROTOCOL_BINARY_CMD_APPEND; in dispatch_bin_command()
2036 c->cmd = PROTOCOL_BINARY_CMD_PREPEND; in dispatch_bin_command()
2039 c->cmd = PROTOCOL_BINARY_CMD_GET; in dispatch_bin_command()
2042 c->cmd = PROTOCOL_BINARY_CMD_GETK; in dispatch_bin_command()
2045 c->cmd = PROTOCOL_BINARY_CMD_GAT; in dispatch_bin_command()
2048 c->cmd = PROTOCOL_BINARY_CMD_GATK; in dispatch_bin_command()
2051 c->noreply = false; in dispatch_bin_command()
2054 switch (c->cmd) { in dispatch_bin_command()
2057 write_bin_response(c, VERSION, 0, 0, strlen(VERSION)); in dispatch_bin_command()
2064 bin_read_key(c, bin_read_flush_exptime, extlen); in dispatch_bin_command()
2071 write_bin_response(c, NULL, 0, 0, 0); in dispatch_bin_command()
2080 bin_read_key(c, bin_reading_set_header, 8); in dispatch_bin_command()
2090 bin_read_key(c, bin_reading_get_key, 0); in dispatch_bin_command()
2097 bin_read_key(c, bin_reading_del_header, extlen); in dispatch_bin_command()
2105 bin_read_key(c, bin_reading_incr_header, 20); in dispatch_bin_command()
2113 bin_read_key(c, bin_reading_set_header, 0); in dispatch_bin_command()
2120 bin_read_key(c, bin_reading_stat, 0); in dispatch_bin_command()
2127 write_bin_response(c, NULL, 0, 0, 0); in dispatch_bin_command()
2128 c->write_and_go = conn_closing; in dispatch_bin_command()
2129 if (c->noreply) { in dispatch_bin_command()
2130 conn_set_state(c, conn_closing); in dispatch_bin_command()
2138 bin_list_sasl_mechs(c); in dispatch_bin_command()
2146 bin_read_key(c, bin_reading_sasl_auth, 0); in dispatch_bin_command()
2157 bin_read_key(c, bin_reading_touch_key, 4); in dispatch_bin_command()
2163 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND, NULL, in dispatch_bin_command()
2168 handle_binary_protocol_error(c); in dispatch_bin_command()
2171 static void process_bin_update(conn *c) { in process_bin_update() argument
2176 protocol_binary_request_set* req = binary_get_request(c); in process_bin_update()
2178 assert(c != NULL); in process_bin_update()
2180 key = binary_get_key(c); in process_bin_update()
2181 nkey = c->binary_header.request.keylen; in process_bin_update()
2187 vlen = c->binary_header.request.bodylen - (nkey + c->binary_header.request.extlen); in process_bin_update()
2191 if (c->cmd == PROTOCOL_BINARY_CMD_ADD) { in process_bin_update()
2192 fprintf(stderr, "<%d ADD ", c->sfd); in process_bin_update()
2193 } else if (c->cmd == PROTOCOL_BINARY_CMD_SET) { in process_bin_update()
2194 fprintf(stderr, "<%d SET ", c->sfd); in process_bin_update()
2196 fprintf(stderr, "<%d REPLACE ", c->sfd); in process_bin_update()
2216 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_E2BIG, NULL, vlen); in process_bin_update()
2219 out_of_memory(c, "SERVER_ERROR Out of memory allocating item"); in process_bin_update()
2221 c->sbytes = vlen; in process_bin_update()
2225 LOGGER_LOG(c->thread->l, LOG_MUTATIONS, LOGGER_ITEM_STORE, in process_bin_update()
2230 if (c->cmd == PROTOCOL_BINARY_CMD_SET) { in process_bin_update()
2231 it = item_get(key, nkey, c); in process_bin_update()
2239 c->write_and_go = conn_swallow; in process_bin_update()
2243 ITEM_set_cas(it, c->binary_header.request.cas); in process_bin_update()
2245 switch (c->cmd) { in process_bin_update()
2247 c->cmd = NREAD_ADD; in process_bin_update()
2250 c->cmd = NREAD_SET; in process_bin_update()
2253 c->cmd = NREAD_REPLACE; in process_bin_update()
2260 c->cmd = NREAD_CAS; in process_bin_update()
2263 c->item = it; in process_bin_update()
2264 c->ritem = ITEM_data(it); in process_bin_update()
2265 c->rlbytes = vlen; in process_bin_update()
2266 conn_set_state(c, conn_nread); in process_bin_update()
2267 c->substate = bin_read_set_value; in process_bin_update()
2270 static void process_bin_append_prepend(conn *c) { in process_bin_append_prepend() argument
2276 assert(c != NULL); in process_bin_append_prepend()
2278 key = binary_get_key(c); in process_bin_append_prepend()
2279 nkey = c->binary_header.request.keylen; in process_bin_append_prepend()
2280 vlen = c->binary_header.request.bodylen - nkey; in process_bin_append_prepend()
2294 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_E2BIG, NULL, vlen); in process_bin_append_prepend()
2296 out_of_memory(c, "SERVER_ERROR Out of memory allocating item"); in process_bin_append_prepend()
2298 c->sbytes = vlen; in process_bin_append_prepend()
2301 c->write_and_go = conn_swallow; in process_bin_append_prepend()
2305 ITEM_set_cas(it, c->binary_header.request.cas); in process_bin_append_prepend()
2307 switch (c->cmd) { in process_bin_append_prepend()
2309 c->cmd = NREAD_APPEND; in process_bin_append_prepend()
2312 c->cmd = NREAD_PREPEND; in process_bin_append_prepend()
2318 c->item = it; in process_bin_append_prepend()
2319 c->ritem = ITEM_data(it); in process_bin_append_prepend()
2320 c->rlbytes = vlen; in process_bin_append_prepend()
2321 conn_set_state(c, conn_nread); in process_bin_append_prepend()
2322 c->substate = bin_read_set_value; in process_bin_append_prepend()
2325 static void process_bin_flush(conn *c) { in process_bin_flush() argument
2327 protocol_binary_request_flush* req = binary_get_request(c); in process_bin_flush()
2332 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR, NULL, 0); in process_bin_flush()
2336 if (c->binary_header.request.extlen == sizeof(req->message.body)) { in process_bin_flush()
2353 pthread_mutex_lock(&c->thread->stats.mutex); in process_bin_flush()
2354 c->thread->stats.flush_cmds++; in process_bin_flush()
2355 pthread_mutex_unlock(&c->thread->stats.mutex); in process_bin_flush()
2357 write_bin_response(c, NULL, 0, 0, 0); in process_bin_flush()
2360 static void process_bin_delete(conn *c) { in process_bin_delete() argument
2363 protocol_binary_request_delete* req = binary_get_request(c); in process_bin_delete()
2365 char* key = binary_get_key(c); in process_bin_delete()
2366 size_t nkey = c->binary_header.request.keylen; in process_bin_delete()
2368 assert(c != NULL); in process_bin_delete()
2383 it = item_get(key, nkey, c); in process_bin_delete()
2387 MEMCACHED_COMMAND_DELETE(c->sfd, ITEM_key(it), it->nkey); in process_bin_delete()
2388 pthread_mutex_lock(&c->thread->stats.mutex); in process_bin_delete()
2389 c->thread->stats.slab_stats[ITEM_clsid(it)].delete_hits++; in process_bin_delete()
2390 pthread_mutex_unlock(&c->thread->stats.mutex); in process_bin_delete()
2392 write_bin_response(c, NULL, 0, 0, 0); in process_bin_delete()
2394 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS, NULL, 0); in process_bin_delete()
2398 write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, NULL, 0); in process_bin_delete()
2399 pthread_mutex_lock(&c->thread->stats.mutex); in process_bin_delete()
2400 c->thread->stats.delete_misses++; in process_bin_delete()
2401 pthread_mutex_unlock(&c->thread->stats.mutex); in process_bin_delete()
2405 static void complete_nread_binary(conn *c) { in complete_nread_binary() argument
2406 assert(c != NULL); in complete_nread_binary()
2407 assert(c->cmd >= 0); in complete_nread_binary()
2409 switch(c->substate) { in complete_nread_binary()
2411 if (c->cmd == PROTOCOL_BINARY_CMD_APPEND || in complete_nread_binary()
2412 c->cmd == PROTOCOL_BINARY_CMD_PREPEND) { in complete_nread_binary()
2413 process_bin_append_prepend(c); in complete_nread_binary()
2415 process_bin_update(c); in complete_nread_binary()
2419 complete_update_bin(c); in complete_nread_binary()
2423 process_bin_get_or_touch(c); in complete_nread_binary()
2426 process_bin_stat(c); in complete_nread_binary()
2429 process_bin_delete(c); in complete_nread_binary()
2432 complete_incr_bin(c); in complete_nread_binary()
2435 process_bin_flush(c); in complete_nread_binary()
2438 process_bin_sasl_auth(c); in complete_nread_binary()
2441 process_bin_complete_sasl_auth(c); in complete_nread_binary()
2444 fprintf(stderr, "Not handling substate %d\n", c->substate); in complete_nread_binary()
2449 static void reset_cmd_handler(conn *c) { in reset_cmd_handler() argument
2450 c->cmd = -1; in reset_cmd_handler()
2451 c->substate = bin_no_state; in reset_cmd_handler()
2452 if(c->item != NULL) { in reset_cmd_handler()
2453 item_remove(c->item); in reset_cmd_handler()
2454 c->item = NULL; in reset_cmd_handler()
2456 conn_shrink(c); in reset_cmd_handler()
2457 if (c->rbytes > 0) { in reset_cmd_handler()
2458 conn_set_state(c, conn_parse_cmd); in reset_cmd_handler()
2460 conn_set_state(c, conn_waiting); in reset_cmd_handler()
2464 static void complete_nread(conn *c) { in complete_nread() argument
2465 assert(c != NULL); in complete_nread()
2466 assert(c->protocol == ascii_prot in complete_nread()
2467 || c->protocol == binary_prot); in complete_nread()
2469 if (c->protocol == ascii_prot) { in complete_nread()
2470 complete_nread_ascii(c); in complete_nread()
2471 } else if (c->protocol == binary_prot) { in complete_nread()
2472 complete_nread_binary(c); in complete_nread()
2559 enum store_item_type do_store_item(item *it, int comm, conn *c, const uint32_t hv) { in do_store_item() argument
2561 item *old_it = do_item_get(key, it->nkey, hv, c); in do_store_item()
2579 pthread_mutex_lock(&c->thread->stats.mutex); in do_store_item()
2580 c->thread->stats.cas_misses++; in do_store_item()
2581 pthread_mutex_unlock(&c->thread->stats.mutex); in do_store_item()
2587 pthread_mutex_lock(&c->thread->stats.mutex); in do_store_item()
2588 c->thread->stats.slab_stats[ITEM_clsid(old_it)].cas_hits++; in do_store_item()
2589 pthread_mutex_unlock(&c->thread->stats.mutex); in do_store_item()
2594 pthread_mutex_lock(&c->thread->stats.mutex); in do_store_item()
2595 c->thread->stats.slab_stats[ITEM_clsid(old_it)].cas_badval++; in do_store_item()
2596 pthread_mutex_unlock(&c->thread->stats.mutex); in do_store_item()
2648 c->cas = ITEM_get_cas(it); in do_store_item()
2660 c->cas = ITEM_get_cas(it); in do_store_item()
2662 LOGGER_LOG(c->thread->l, LOG_MUTATIONS, LOGGER_ITEM_STORE, NULL, in do_store_item()
2741 static void write_and_free(conn *c, char *buf, int bytes) { in write_and_free() argument
2743 c->write_and_free = buf; in write_and_free()
2744 c->wcurr = buf; in write_and_free()
2745 c->wbytes = bytes; in write_and_free()
2746 conn_set_state(c, conn_write); in write_and_free()
2747 c->write_and_go = conn_new_cmd; in write_and_free()
2749 out_of_memory(c, "SERVER_ERROR out of memory writing stats"); in write_and_free()
2753 static inline bool set_noreply_maybe(conn *c, token_t *tokens, size_t ntokens) in set_noreply_maybe() argument
2766 c->noreply = true; in set_noreply_maybe()
2768 return c->noreply; in set_noreply_maybe()
2771 void append_stat(const char *name, ADD_STAT add_stats, conn *c, in append_stat() argument
2779 assert(c); in append_stat()
2786 add_stats(name, strlen(name), val_str, vlen, c); in append_stat()
2789 inline static void process_stats_detail(conn *c, const char *command) { in process_stats_detail() argument
2790 assert(c != NULL); in process_stats_detail()
2794 out_string(c, "OK"); in process_stats_detail()
2798 out_string(c, "OK"); in process_stats_detail()
2803 write_and_free(c, stats, len); in process_stats_detail()
2806 out_string(c, "CLIENT_ERROR usage: stats detail on|off|dump"); in process_stats_detail()
2811 static void server_stats(ADD_STAT add_stats, conn *c) { in server_stats() argument
2835 append_stat("rusage_user", add_stats, c, "%ld.%06ld", in server_stats()
2838 append_stat("rusage_system", add_stats, c, "%ld.%06ld", in server_stats()
2910 static void process_stat_settings(ADD_STAT add_stats, void *c) { in process_stat_settings() argument
2957 static void conn_to_str(const conn *c, char *buf) { in conn_to_str() argument
2960 if (!c) { in conn_to_str()
2962 } else if (c->state == conn_closed) { in conn_to_str()
2967 struct sockaddr *addr = (void *)&c->request_addr; in conn_to_str()
2972 if (c->state == conn_listening || in conn_to_str()
2973 (IS_UDP(c->transport) && in conn_to_str()
2974 c->state == conn_read)) { in conn_to_str()
2977 if (getsockname(c->sfd, in conn_to_str()
2994 protoname = IS_UDP(c->transport) ? "udp" : "tcp"; in conn_to_str()
3007 protoname = IS_UDP(c->transport) ? "udp6" : "tcp6"; in conn_to_str()
3035 static void process_stats_conns(ADD_STAT add_stats, void *c) { in process_stats_conns() argument
3064 static void process_stat(conn *c, token_t *tokens, const size_t ntokens) { in process_stat() argument
3066 assert(c != NULL); in process_stat()
3069 out_string(c, "CLIENT_ERROR bad command line"); in process_stat()
3074 server_stats(&append_stats, c); in process_stat()
3075 (void)get_stats(NULL, 0, &append_stats, c); in process_stat()
3078 out_string(c, "RESET"); in process_stat()
3083 process_stats_detail(c, ""); /* outputs the error message */ in process_stat()
3085 process_stats_detail(c, tokens[2].value); in process_stat()
3089 process_stat_settings(&append_stats, c); in process_stat()
3095 out_string(c, "CLIENT_ERROR bad command line"); in process_stat()
3101 out_string(c, "CLIENT_ERROR bad command line format"); in process_stat()
3106 out_string(c, "CLIENT_ERROR Illegal slab id"); in process_stat()
3111 write_and_free(c, buf, bytes); in process_stat()
3114 process_stats_conns(&append_stats, c); in process_stat()
3118 if (get_stats(subcommand, strlen(subcommand), &append_stats, c)) { in process_stat()
3119 if (c->stats.buffer == NULL) { in process_stat()
3120 out_of_memory(c, "SERVER_ERROR out of memory writing stats"); in process_stat()
3122 write_and_free(c, c->stats.buffer, c->stats.offset); in process_stat()
3123 c->stats.buffer = NULL; in process_stat()
3126 out_string(c, "ERROR"); in process_stat()
3132 append_stats(NULL, 0, NULL, 0, c); in process_stat()
3134 if (c->stats.buffer == NULL) { in process_stat()
3135 out_of_memory(c, "SERVER_ERROR out of memory writing stats"); in process_stat()
3137 write_and_free(c, c->stats.buffer, c->stats.offset); in process_stat()
3138 c->stats.buffer = NULL; in process_stat()
3143 static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens, bool return_cas) { in process_get_command() argument
3150 assert(c != NULL); in process_get_command()
3159 out_string(c, "CLIENT_ERROR bad command line format"); in process_get_command()
3161 item_remove(*(c->ilist + i)); in process_get_command()
3166 it = item_get(key, nkey, c); in process_get_command()
3171 if (i >= c->isize) { in process_get_command()
3172 item **new_list = realloc(c->ilist, sizeof(item *) * c->isize * 2); in process_get_command()
3174 c->isize *= 2; in process_get_command()
3175 c->ilist = new_list; in process_get_command()
3195 MEMCACHED_COMMAND_GET(c->sfd, ITEM_key(it), it->nkey, in process_get_command()
3198 if (i >= c->suffixsize) { in process_get_command()
3199 char **new_suffix_list = realloc(c->suffixlist, in process_get_command()
3200 sizeof(char *) * c->suffixsize * 2); in process_get_command()
3202 c->suffixsize *= 2; in process_get_command()
3203 c->suffixlist = new_suffix_list; in process_get_command()
3213 suffix = cache_alloc(c->thread->suffix_cache); in process_get_command()
3218 out_of_memory(c, "SERVER_ERROR out of memory making CAS suffix"); in process_get_command()
3221 item_remove(*(c->ilist + i)); in process_get_command()
3225 *(c->suffixlist + i) = suffix; in process_get_command()
3229 if (add_iov(c, "VALUE ", 6) != 0 || in process_get_command()
3230 add_iov(c, ITEM_key(it), it->nkey) != 0 || in process_get_command()
3231 add_iov(c, ITEM_suffix(it), it->nsuffix - 2) != 0 || in process_get_command()
3232 add_iov(c, suffix, suffix_len) != 0) in process_get_command()
3238 add_iov(c, ITEM_data(it), it->nbytes); in process_get_command()
3239 } else if (add_chunked_item_iovs(c, it, it->nbytes) != 0) { in process_get_command()
3246 MEMCACHED_COMMAND_GET(c->sfd, ITEM_key(it), it->nkey, in process_get_command()
3248 if (add_iov(c, "VALUE ", 6) != 0 || in process_get_command()
3249 add_iov(c, ITEM_key(it), it->nkey) != 0) in process_get_command()
3256 if (add_iov(c, ITEM_suffix(it), it->nsuffix + it->nbytes) != 0) in process_get_command()
3261 } else if (add_iov(c, ITEM_suffix(it), it->nsuffix) != 0 || in process_get_command()
3262 add_chunked_item_iovs(c, it, it->nbytes) != 0) { in process_get_command()
3271 fprintf(stderr, ">%d sending key ", c->sfd); in process_get_command()
3279 pthread_mutex_lock(&c->thread->stats.mutex); in process_get_command()
3280 c->thread->stats.slab_stats[ITEM_clsid(it)].get_hits++; in process_get_command()
3281 c->thread->stats.get_cmds++; in process_get_command()
3282 pthread_mutex_unlock(&c->thread->stats.mutex); in process_get_command()
3284 *(c->ilist + i) = it; in process_get_command()
3288 pthread_mutex_lock(&c->thread->stats.mutex); in process_get_command()
3289 c->thread->stats.get_misses++; in process_get_command()
3290 c->thread->stats.get_cmds++; in process_get_command()
3291 pthread_mutex_unlock(&c->thread->stats.mutex); in process_get_command()
3292 MEMCACHED_COMMAND_GET(c->sfd, key, nkey, -1, 0); in process_get_command()
3309 c->icurr = c->ilist; in process_get_command()
3310 c->ileft = i; in process_get_command()
3312 c->suffixcurr = c->suffixlist; in process_get_command()
3313 c->suffixleft = i; in process_get_command()
3317 fprintf(stderr, ">%d END\n", c->sfd); in process_get_command()
3324 if (key_token->value != NULL || add_iov(c, "END\r\n", 5) != 0 in process_get_command()
3325 || (IS_UDP(c->transport) && build_udp_headers(c) != 0)) { in process_get_command()
3326 out_of_memory(c, "SERVER_ERROR out of memory writing get response"); in process_get_command()
3329 conn_set_state(c, conn_mwrite); in process_get_command()
3330 c->msgcurr = 0; in process_get_command()
3334 static void process_update_command(conn *c, token_t *tokens, const size_t ntokens, int comm, bool h… in process_update_command() argument
3344 assert(c != NULL); in process_update_command()
3346 set_noreply_maybe(c, tokens, ntokens); in process_update_command()
3349 out_string(c, "CLIENT_ERROR bad command line format"); in process_update_command()
3359 out_string(c, "CLIENT_ERROR bad command line format"); in process_update_command()
3375 out_string(c, "CLIENT_ERROR bad command line format"); in process_update_command()
3381 out_string(c, "CLIENT_ERROR bad command line format"); in process_update_command()
3395 out_string(c, "SERVER_ERROR object too large for cache"); in process_update_command()
3398 out_of_memory(c, "SERVER_ERROR out of memory storing object"); in process_update_command()
3401 LOGGER_LOG(c->thread->l, LOG_MUTATIONS, LOGGER_ITEM_STORE, in process_update_command()
3404 c->write_and_go = conn_swallow; in process_update_command()
3405 c->sbytes = vlen; in process_update_command()
3410 it = item_get(key, nkey, c); in process_update_command()
3421 c->item = it; in process_update_command()
3422 c->ritem = ITEM_data(it); in process_update_command()
3423 c->rlbytes = it->nbytes; in process_update_command()
3424 c->cmd = comm; in process_update_command()
3425 conn_set_state(c, conn_nread); in process_update_command()
3428 static void process_touch_command(conn *c, token_t *tokens, const size_t ntokens) { in process_touch_command() argument
3434 assert(c != NULL); in process_touch_command()
3436 set_noreply_maybe(c, tokens, ntokens); in process_touch_command()
3439 out_string(c, "CLIENT_ERROR bad command line format"); in process_touch_command()
3447 out_string(c, "CLIENT_ERROR invalid exptime argument"); in process_touch_command()
3451 it = item_touch(key, nkey, realtime(exptime_int), c); in process_touch_command()
3454 pthread_mutex_lock(&c->thread->stats.mutex); in process_touch_command()
3455 c->thread->stats.touch_cmds++; in process_touch_command()
3456 c->thread->stats.slab_stats[ITEM_clsid(it)].touch_hits++; in process_touch_command()
3457 pthread_mutex_unlock(&c->thread->stats.mutex); in process_touch_command()
3459 out_string(c, "TOUCHED"); in process_touch_command()
3462 pthread_mutex_lock(&c->thread->stats.mutex); in process_touch_command()
3463 c->thread->stats.touch_cmds++; in process_touch_command()
3464 c->thread->stats.touch_misses++; in process_touch_command()
3465 pthread_mutex_unlock(&c->thread->stats.mutex); in process_touch_command()
3467 out_string(c, "NOT_FOUND"); in process_touch_command()
3471 static void process_arithmetic_command(conn *c, token_t *tokens, const size_t ntokens, const bool i… in process_arithmetic_command() argument
3477 assert(c != NULL); in process_arithmetic_command()
3479 set_noreply_maybe(c, tokens, ntokens); in process_arithmetic_command()
3482 out_string(c, "CLIENT_ERROR bad command line format"); in process_arithmetic_command()
3490 out_string(c, "CLIENT_ERROR invalid numeric delta argument"); in process_arithmetic_command()
3494 switch(add_delta(c, key, nkey, incr, delta, temp, NULL)) { in process_arithmetic_command()
3496 out_string(c, temp); in process_arithmetic_command()
3499 out_string(c, "CLIENT_ERROR cannot increment or decrement non-numeric value"); in process_arithmetic_command()
3502 out_of_memory(c, "SERVER_ERROR out of memory"); in process_arithmetic_command()
3505 pthread_mutex_lock(&c->thread->stats.mutex); in process_arithmetic_command()
3507 c->thread->stats.incr_misses++; in process_arithmetic_command()
3509 c->thread->stats.decr_misses++; in process_arithmetic_command()
3511 pthread_mutex_unlock(&c->thread->stats.mutex); in process_arithmetic_command()
3513 out_string(c, "NOT_FOUND"); in process_arithmetic_command()
3531 enum delta_result_type do_add_delta(conn *c, const char *key, const size_t nkey, in do_add_delta() argument
3540 it = do_item_get(key, nkey, hv, c); in do_add_delta()
3565 MEMCACHED_COMMAND_INCR(c->sfd, ITEM_key(it), it->nkey, value); in do_add_delta()
3572 MEMCACHED_COMMAND_DECR(c->sfd, ITEM_key(it), it->nkey, value); in do_add_delta()
3575 pthread_mutex_lock(&c->thread->stats.mutex); in do_add_delta()
3577 c->thread->stats.slab_stats[ITEM_clsid(it)].incr_hits++; in do_add_delta()
3579 c->thread->stats.slab_stats[ITEM_clsid(it)].decr_hits++; in do_add_delta()
3581 pthread_mutex_unlock(&c->thread->stats.mutex); in do_add_delta()
3633 static void process_delete_command(conn *c, token_t *tokens, const size_t ntokens) { in process_delete_command() argument
3638 assert(c != NULL); in process_delete_command()
3642 bool sets_noreply = set_noreply_maybe(c, tokens, ntokens); in process_delete_command()
3646 out_string(c, "CLIENT_ERROR bad command line format. " in process_delete_command()
3657 out_string(c, "CLIENT_ERROR bad command line format"); in process_delete_command()
3665 it = item_get(key, nkey, c); in process_delete_command()
3667 MEMCACHED_COMMAND_DELETE(c->sfd, ITEM_key(it), it->nkey); in process_delete_command()
3669 pthread_mutex_lock(&c->thread->stats.mutex); in process_delete_command()
3670 c->thread->stats.slab_stats[ITEM_clsid(it)].delete_hits++; in process_delete_command()
3671 pthread_mutex_unlock(&c->thread->stats.mutex); in process_delete_command()
3675 out_string(c, "DELETED"); in process_delete_command()
3677 pthread_mutex_lock(&c->thread->stats.mutex); in process_delete_command()
3678 c->thread->stats.delete_misses++; in process_delete_command()
3679 pthread_mutex_unlock(&c->thread->stats.mutex); in process_delete_command()
3681 out_string(c, "NOT_FOUND"); in process_delete_command()
3685 static void process_verbosity_command(conn *c, token_t *tokens, const size_t ntokens) { in process_verbosity_command() argument
3688 assert(c != NULL); in process_verbosity_command()
3690 set_noreply_maybe(c, tokens, ntokens); in process_verbosity_command()
3694 out_string(c, "OK"); in process_verbosity_command()
3698 static void process_slabs_automove_command(conn *c, token_t *tokens, const size_t ntokens) { in process_slabs_automove_command() argument
3701 assert(c != NULL); in process_slabs_automove_command()
3703 set_noreply_maybe(c, tokens, ntokens); in process_slabs_automove_command()
3711 out_string(c, "ERROR"); in process_slabs_automove_command()
3714 out_string(c, "OK"); in process_slabs_automove_command()
3719 static void process_watch_command(conn *c, token_t *tokens, const size_t ntokens) { in process_watch_command() argument
3722 assert(c != NULL); in process_watch_command()
3724 set_noreply_maybe(c, tokens, ntokens); in process_watch_command()
3736 out_string(c, "ERROR"); in process_watch_command()
3744 switch(logger_add_watcher(c, c->sfd, f)) { in process_watch_command()
3746 out_string(c, "WATCHER_TOO_MANY log watcher limit reached"); in process_watch_command()
3749 out_string(c, "WATCHER_FAILED failed to add log watcher"); in process_watch_command()
3752 conn_set_state(c, conn_watch); in process_watch_command()
3753 event_del(&c->event); in process_watch_command()
3758 static void process_memlimit_command(conn *c, token_t *tokens, const size_t ntokens) { in process_memlimit_command() argument
3760 assert(c != NULL); in process_memlimit_command()
3762 set_noreply_maybe(c, tokens, ntokens); in process_memlimit_command()
3765 out_string(c, "ERROR"); in process_memlimit_command()
3768 out_string(c, "MEMLIMIT_TOO_SMALL cannot set maxbytes to less than 8m"); in process_memlimit_command()
3775 out_string(c, "OK"); in process_memlimit_command()
3777 out_string(c, "MEMLIMIT_ADJUST_FAILED out of bounds or unable to adjust"); in process_memlimit_command()
3783 static void process_command(conn *c, char *command) { in process_command() argument
3789 assert(c != NULL); in process_command()
3791 MEMCACHED_PROCESS_COMMAND_START(c->sfd, c->rcurr, c->rbytes); in process_command()
3794 fprintf(stderr, "<%d %s\n", c->sfd, command); in process_command()
3801 c->msgcurr = 0; in process_command()
3802 c->msgused = 0; in process_command()
3803 c->iovused = 0; in process_command()
3804 if (add_msghdr(c) != 0) { in process_command()
3805 out_of_memory(c, "SERVER_ERROR out of memory preparing response"); in process_command()
3814 process_get_command(c, tokens, ntokens, false); in process_command()
3823 process_update_command(c, tokens, ntokens, comm, false); in process_command()
3827 process_update_command(c, tokens, ntokens, comm, true); in process_command()
3831 process_arithmetic_command(c, tokens, ntokens, 1); in process_command()
3835 process_get_command(c, tokens, ntokens, true); in process_command()
3839 process_arithmetic_command(c, tokens, ntokens, 0); in process_command()
3843 process_delete_command(c, tokens, ntokens); in process_command()
3847 process_touch_command(c, tokens, ntokens); in process_command()
3851 process_stat(c, tokens, ntokens); in process_command()
3857 set_noreply_maybe(c, tokens, ntokens); in process_command()
3859 pthread_mutex_lock(&c->thread->stats.mutex); in process_command()
3860 c->thread->stats.flush_cmds++; in process_command()
3861 pthread_mutex_unlock(&c->thread->stats.mutex); in process_command()
3865 out_string(c, "CLIENT_ERROR flush_all not allowed"); in process_command()
3869 if (ntokens != (c->noreply ? 3 : 2)) { in process_command()
3872 out_string(c, "CLIENT_ERROR bad command line format"); in process_command()
3896 out_string(c, "OK"); in process_command()
3901 out_string(c, "VERSION " VERSION); in process_command()
3905 conn_set_state(c, conn_closing); in process_command()
3910 conn_set_state(c, conn_closing); in process_command()
3913 out_string(c, "ERROR: shutdown not enabled"); in process_command()
3921 out_string(c, "CLIENT_ERROR slab reassignment disabled"); in process_command()
3929 out_string(c, "CLIENT_ERROR bad command line format"); in process_command()
3936 out_string(c, "OK"); in process_command()
3939 out_string(c, "BUSY currently processing reassign request"); in process_command()
3942 out_string(c, "BADCLASS invalid src or dst class id"); in process_command()
3945 out_string(c, "NOSPARE source class has no spare pages"); in process_command()
3948 out_string(c, "SAME src and dst class are identical"); in process_command()
3954 process_slabs_automove_command(c, tokens, ntokens); in process_command()
3956 out_string(c, "ERROR"); in process_command()
3962 out_string(c, "CLIENT_ERROR lru crawler disabled"); in process_command()
3969 out_string(c, "OK"); in process_command()
3972 out_string(c, "BUSY currently processing crawler request"); in process_command()
3975 out_string(c, "BADCLASS invalid class id"); in process_command()
3978 out_string(c, "NOTSTARTED no items to crawl"); in process_command()
3985 out_string(c, "CLIENT_ERROR bad command line format"); in process_command()
3989 out_string(c, "OK"); in process_command()
3994 out_string(c, "CLIENT_ERROR bad command line format"); in process_command()
3998 out_string(c, "CLIENT_ERROR sleep must be one second or less"); in process_command()
4002 out_string(c, "OK"); in process_command()
4007 out_string(c, "OK"); in process_command()
4009 out_string(c, "ERROR failed to start lru crawler thread"); in process_command()
4013 out_string(c, "OK"); in process_command()
4015 out_string(c, "ERROR failed to stop lru crawler thread"); in process_command()
4018 out_string(c, "ERROR"); in process_command()
4022 out_string(c, "ERROR"); in process_command()
4025 process_watch_command(c, tokens, ntokens); in process_command()
4027 process_memlimit_command(c, tokens, ntokens); in process_command()
4029 process_verbosity_command(c, tokens, ntokens); in process_command()
4031 out_string(c, "ERROR"); in process_command()
4039 static int try_read_command(conn *c) { in try_read_command() argument
4040 assert(c != NULL); in try_read_command()
4041 assert(c->rcurr <= (c->rbuf + c->rsize)); in try_read_command()
4042 assert(c->rbytes > 0); in try_read_command()
4044 if (c->protocol == negotiating_prot || c->transport == udp_transport) { in try_read_command()
4045 if ((unsigned char)c->rbuf[0] == (unsigned char)PROTOCOL_BINARY_REQ) { in try_read_command()
4046 c->protocol = binary_prot; in try_read_command()
4048 c->protocol = ascii_prot; in try_read_command()
4052 fprintf(stderr, "%d: Client using the %s protocol\n", c->sfd, in try_read_command()
4053 prot_text(c->protocol)); in try_read_command()
4057 if (c->protocol == binary_prot) { in try_read_command()
4059 if (c->rbytes < sizeof(c->binary_header)) { in try_read_command()
4064 if (((long)(c->rcurr)) % 8 != 0) { in try_read_command()
4066 memmove(c->rbuf, c->rcurr, c->rbytes); in try_read_command()
4067 c->rcurr = c->rbuf; in try_read_command()
4069 fprintf(stderr, "%d: Realign input buffer\n", c->sfd); in try_read_command()
4074 req = (protocol_binary_request_header*)c->rcurr; in try_read_command()
4079 fprintf(stderr, "<%d Read binary protocol data:", c->sfd); in try_read_command()
4082 fprintf(stderr, "\n<%d ", c->sfd); in try_read_command()
4089 c->binary_header = *req; in try_read_command()
4090 c->binary_header.request.keylen = ntohs(req->request.keylen); in try_read_command()
4091 c->binary_header.request.bodylen = ntohl(req->request.bodylen); in try_read_command()
4092 c->binary_header.request.cas = ntohll(req->request.cas); in try_read_command()
4094 if (c->binary_header.request.magic != PROTOCOL_BINARY_REQ) { in try_read_command()
4097 c->binary_header.request.magic); in try_read_command()
4099 conn_set_state(c, conn_closing); in try_read_command()
4103 c->msgcurr = 0; in try_read_command()
4104 c->msgused = 0; in try_read_command()
4105 c->iovused = 0; in try_read_command()
4106 if (add_msghdr(c) != 0) { in try_read_command()
4107 out_of_memory(c, in try_read_command()
4112 c->cmd = c->binary_header.request.opcode; in try_read_command()
4113 c->keylen = c->binary_header.request.keylen; in try_read_command()
4114 c->opaque = c->binary_header.request.opaque; in try_read_command()
4116 c->cas = 0; in try_read_command()
4118 dispatch_bin_command(c); in try_read_command()
4120 c->rbytes -= sizeof(c->binary_header); in try_read_command()
4121 c->rcurr += sizeof(c->binary_header); in try_read_command()
4126 if (c->rbytes == 0) in try_read_command()
4129 el = memchr(c->rcurr, '\n', c->rbytes); in try_read_command()
4131 if (c->rbytes > 1024) { in try_read_command()
4136 char *ptr = c->rcurr; in try_read_command()
4141 if (ptr - c->rcurr > 100 || in try_read_command()
4144 conn_set_state(c, conn_closing); in try_read_command()
4152 if ((el - c->rcurr) > 1 && *(el - 1) == '\r') { in try_read_command()
4157 assert(cont <= (c->rcurr + c->rbytes)); in try_read_command()
4159 c->last_cmd_time = current_time; in try_read_command()
4160 process_command(c, c->rcurr); in try_read_command()
4162 c->rbytes -= (cont - c->rcurr); in try_read_command()
4163 c->rcurr = cont; in try_read_command()
4165 assert(c->rcurr <= (c->rbuf + c->rsize)); in try_read_command()
4174 static enum try_read_result try_read_udp(conn *c) { in try_read_udp() argument
4177 assert(c != NULL); in try_read_udp()
4179 c->request_addr_size = sizeof(c->request_addr); in try_read_udp()
4180 res = recvfrom(c->sfd, c->rbuf, c->rsize, in try_read_udp()
4181 0, (struct sockaddr *)&c->request_addr, in try_read_udp()
4182 &c->request_addr_size); in try_read_udp()
4184 unsigned char *buf = (unsigned char *)c->rbuf; in try_read_udp()
4185 pthread_mutex_lock(&c->thread->stats.mutex); in try_read_udp()
4186 c->thread->stats.bytes_read += res; in try_read_udp()
4187 pthread_mutex_unlock(&c->thread->stats.mutex); in try_read_udp()
4190 c->request_id = buf[0] * 256 + buf[1]; in try_read_udp()
4194 out_string(c, "SERVER_ERROR multi-packet request not supported"); in try_read_udp()
4200 memmove(c->rbuf, c->rbuf + 8, res); in try_read_udp()
4202 c->rbytes = res; in try_read_udp()
4203 c->rcurr = c->rbuf; in try_read_udp()
4221 static enum try_read_result try_read_network(conn *c) { in try_read_network() argument
4225 assert(c != NULL); in try_read_network()
4227 if (c->rcurr != c->rbuf) { in try_read_network()
4228 if (c->rbytes != 0) /* otherwise there's nothing to copy */ in try_read_network()
4229 memmove(c->rbuf, c->rcurr, c->rbytes); in try_read_network()
4230 c->rcurr = c->rbuf; in try_read_network()
4234 if (c->rbytes >= c->rsize) { in try_read_network()
4239 char *new_rbuf = realloc(c->rbuf, c->rsize * 2); in try_read_network()
4247 c->rbytes = 0; /* ignore what we read */ in try_read_network()
4248 out_of_memory(c, "SERVER_ERROR out of memory reading request"); in try_read_network()
4249 c->write_and_go = conn_closing; in try_read_network()
4252 c->rcurr = c->rbuf = new_rbuf; in try_read_network()
4253 c->rsize *= 2; in try_read_network()
4256 int avail = c->rsize - c->rbytes; in try_read_network()
4257 res = read(c->sfd, c->rbuf + c->rbytes, avail); in try_read_network()
4259 pthread_mutex_lock(&c->thread->stats.mutex); in try_read_network()
4260 c->thread->stats.bytes_read += res; in try_read_network()
4261 pthread_mutex_unlock(&c->thread->stats.mutex); in try_read_network()
4263 c->rbytes += res; in try_read_network()
4283 static bool update_event(conn *c, const int new_flags) { in update_event() argument
4284 assert(c != NULL); in update_event()
4286 struct event_base *base = c->event.ev_base; in update_event()
4287 if (c->ev_flags == new_flags) in update_event()
4289 if (event_del(&c->event) == -1) return false; in update_event()
4290 event_set(&c->event, c->sfd, new_flags, event_handler, (void *)c); in update_event()
4291 event_base_set(base, &c->event); in update_event()
4292 c->ev_flags = new_flags; in update_event()
4293 if (event_add(&c->event, 0) == -1) return false; in update_event()
4349 static enum transmit_result transmit(conn *c) { in transmit() argument
4350 assert(c != NULL); in transmit()
4352 if (c->msgcurr < c->msgused && in transmit()
4353 c->msglist[c->msgcurr].msg_iovlen == 0) { in transmit()
4355 c->msgcurr++; in transmit()
4357 if (c->msgcurr < c->msgused) { in transmit()
4359 struct msghdr *m = &c->msglist[c->msgcurr]; in transmit()
4361 res = sendmsg(c->sfd, m, 0); in transmit()
4363 pthread_mutex_lock(&c->thread->stats.mutex); in transmit()
4364 c->thread->stats.bytes_written += res; in transmit()
4365 pthread_mutex_unlock(&c->thread->stats.mutex); in transmit()
4384 if (!update_event(c, EV_WRITE | EV_PERSIST)) { in transmit()
4387 conn_set_state(c, conn_closing); in transmit()
4397 if (IS_UDP(c->transport)) in transmit()
4398 conn_set_state(c, conn_read); in transmit()
4400 conn_set_state(c, conn_closing); in transmit()
4411 static int read_into_chunked_item(conn *c) { in read_into_chunked_item() argument
4414 assert(c->rcurr != c->ritem); in read_into_chunked_item()
4416 while (c->rlbytes > 0) { in read_into_chunked_item()
4417 item_chunk *ch = (item_chunk *)c->ritem; in read_into_chunked_item()
4420 if (c->rbytes > 0) { in read_into_chunked_item()
4422 int tocopy = c->rbytes > c->rlbytes ? c->rlbytes : c->rbytes; in read_into_chunked_item()
4424 if (c->ritem != c->rcurr) { in read_into_chunked_item()
4425 memmove(ch->data + ch->used, c->rcurr, tocopy); in read_into_chunked_item()
4428 c->rlbytes -= tocopy; in read_into_chunked_item()
4429 c->rcurr += tocopy; in read_into_chunked_item()
4430 c->rbytes -= tocopy; in read_into_chunked_item()
4432 if (c->rlbytes == 0) { in read_into_chunked_item()
4437 res = read(c->sfd, ch->data + ch->used, in read_into_chunked_item()
4438 (unused > c->rlbytes ? c->rlbytes : unused)); in read_into_chunked_item()
4440 pthread_mutex_lock(&c->thread->stats.mutex); in read_into_chunked_item()
4441 c->thread->stats.bytes_read += res; in read_into_chunked_item()
4442 pthread_mutex_unlock(&c->thread->stats.mutex); in read_into_chunked_item()
4445 c->rlbytes -= res; in read_into_chunked_item()
4456 c->ritem = (char *) ch->next; in read_into_chunked_item()
4459 assert(c->rlbytes == 0); in read_into_chunked_item()
4467 static void drive_machine(conn *c) { in drive_machine() argument
4481 assert(c != NULL); in drive_machine()
4485 switch(c->state) { in drive_machine()
4490 sfd = accept4(c->sfd, (struct sockaddr *)&addr, &addrlen, SOCK_NONBLOCK); in drive_machine()
4492 sfd = accept(c->sfd, (struct sockaddr *)&addr, &addrlen); in drive_machine()
4495 sfd = accept(c->sfd, (struct sockaddr *)&addr, &addrlen); in drive_machine()
4535 DATA_BUFFER_SIZE, c->transport); in drive_machine()
4542 if (!update_event(c, EV_READ | EV_PERSIST)) { in drive_machine()
4545 conn_set_state(c, conn_closing); in drive_machine()
4549 conn_set_state(c, conn_read); in drive_machine()
4554 res = IS_UDP(c->transport) ? try_read_udp(c) : try_read_network(c); in drive_machine()
4558 conn_set_state(c, conn_waiting); in drive_machine()
4561 conn_set_state(c, conn_parse_cmd); in drive_machine()
4564 conn_set_state(c, conn_closing); in drive_machine()
4573 if (try_read_command(c) == 0) { in drive_machine()
4575 conn_set_state(c, conn_waiting); in drive_machine()
4586 reset_cmd_handler(c); in drive_machine()
4588 pthread_mutex_lock(&c->thread->stats.mutex); in drive_machine()
4589 c->thread->stats.conn_yields++; in drive_machine()
4590 pthread_mutex_unlock(&c->thread->stats.mutex); in drive_machine()
4591 if (c->rbytes > 0) { in drive_machine()
4598 if (!update_event(c, EV_WRITE | EV_PERSIST)) { in drive_machine()
4601 conn_set_state(c, conn_closing); in drive_machine()
4610 if (c->rlbytes == 0) { in drive_machine()
4611 complete_nread(c); in drive_machine()
4616 if (c->rlbytes < 0) { in drive_machine()
4618 fprintf(stderr, "Invalid rlbytes to read: len %d\n", c->rlbytes); in drive_machine()
4620 conn_set_state(c, conn_closing); in drive_machine()
4624 if (!c->item || (((item *)c->item)->it_flags & ITEM_CHUNKED) == 0) { in drive_machine()
4626 if (c->rbytes > 0) { in drive_machine()
4627 int tocopy = c->rbytes > c->rlbytes ? c->rlbytes : c->rbytes; in drive_machine()
4628 if (c->ritem != c->rcurr) { in drive_machine()
4629 memmove(c->ritem, c->rcurr, tocopy); in drive_machine()
4631 c->ritem += tocopy; in drive_machine()
4632 c->rlbytes -= tocopy; in drive_machine()
4633 c->rcurr += tocopy; in drive_machine()
4634 c->rbytes -= tocopy; in drive_machine()
4635 if (c->rlbytes == 0) { in drive_machine()
4641 res = read(c->sfd, c->ritem, c->rlbytes); in drive_machine()
4643 pthread_mutex_lock(&c->thread->stats.mutex); in drive_machine()
4644 c->thread->stats.bytes_read += res; in drive_machine()
4645 pthread_mutex_unlock(&c->thread->stats.mutex); in drive_machine()
4646 if (c->rcurr == c->ritem) { in drive_machine()
4647 c->rcurr += res; in drive_machine()
4649 c->ritem += res; in drive_machine()
4650 c->rlbytes -= res; in drive_machine()
4654 res = read_into_chunked_item(c); in drive_machine()
4660 conn_set_state(c, conn_closing); in drive_machine()
4665 if (!update_event(c, EV_READ | EV_PERSIST)) { in drive_machine()
4668 conn_set_state(c, conn_closing); in drive_machine()
4680 (long)c->rcurr, (long)c->ritem, (long)c->rbuf, in drive_machine()
4681 (int)c->rlbytes, (int)c->rsize); in drive_machine()
4683 conn_set_state(c, conn_closing); in drive_machine()
4688 if (c->sbytes == 0) { in drive_machine()
4689 conn_set_state(c, conn_new_cmd); in drive_machine()
4694 if (c->rbytes > 0) { in drive_machine()
4695 int tocopy = c->rbytes > c->sbytes ? c->sbytes : c->rbytes; in drive_machine()
4696 c->sbytes -= tocopy; in drive_machine()
4697 c->rcurr += tocopy; in drive_machine()
4698 c->rbytes -= tocopy; in drive_machine()
4703 res = read(c->sfd, c->rbuf, c->rsize > c->sbytes ? c->sbytes : c->rsize); in drive_machine()
4705 pthread_mutex_lock(&c->thread->stats.mutex); in drive_machine()
4706 c->thread->stats.bytes_read += res; in drive_machine()
4707 pthread_mutex_unlock(&c->thread->stats.mutex); in drive_machine()
4708 c->sbytes -= res; in drive_machine()
4712 conn_set_state(c, conn_closing); in drive_machine()
4716 if (!update_event(c, EV_READ | EV_PERSIST)) { in drive_machine()
4719 conn_set_state(c, conn_closing); in drive_machine()
4728 conn_set_state(c, conn_closing); in drive_machine()
4737 if (c->iovused == 0 || (IS_UDP(c->transport) && c->iovused == 1)) { in drive_machine()
4738 if (add_iov(c, c->wcurr, c->wbytes) != 0) { in drive_machine()
4741 conn_set_state(c, conn_closing); in drive_machine()
4749 if (IS_UDP(c->transport) && c->msgcurr == 0 && build_udp_headers(c) != 0) { in drive_machine()
4752 conn_set_state(c, conn_closing); in drive_machine()
4755 switch (transmit(c)) { in drive_machine()
4757 if (c->state == conn_mwrite) { in drive_machine()
4758 conn_release_items(c); in drive_machine()
4760 if(c->protocol == binary_prot) { in drive_machine()
4761 conn_set_state(c, c->write_and_go); in drive_machine()
4763 conn_set_state(c, conn_new_cmd); in drive_machine()
4765 } else if (c->state == conn_write) { in drive_machine()
4766 if (c->write_and_free) { in drive_machine()
4767 free(c->write_and_free); in drive_machine()
4768 c->write_and_free = 0; in drive_machine()
4770 conn_set_state(c, c->write_and_go); in drive_machine()
4773 fprintf(stderr, "Unexpected state %d\n", c->state); in drive_machine()
4774 conn_set_state(c, conn_closing); in drive_machine()
4789 if (IS_UDP(c->transport)) in drive_machine()
4790 conn_cleanup(c); in drive_machine()
4792 conn_close(c); in drive_machine()
4815 conn *c; in event_handler() local
4817 c = (conn *)arg; in event_handler()
4818 assert(c != NULL); in event_handler()
4820 c->which = which; in event_handler()
4823 if (fd != c->sfd) { in event_handler()
4826 conn_close(c); in event_handler()
4830 drive_machine(c); in event_handler()
5009 int c; in server_socket() local
5011 for (c = 0; c < settings.num_threads_per_udp; c++) { in server_socket()
5020 int per_thread_fd = c ? dup(sfd) : sfd; in server_socket()
5575 int c; in main() local
5672 while (-1 != (c = getopt(argc, argv, in main()
5703 switch (c) { in main()
6076 fprintf(stderr, "Illegal argument \"%c\"\n", c); in main()