static memcached_return_t server_add(memcached_st *ptr, const char *hostname, in_port_t port, uint32_t weight, memcached_connection_t type) { memcached_server_st *new_host_list; memcached_server_write_instance_st instance; if ( (ptr->flags.use_udp && type != MEMCACHED_CONNECTION_UDP) || ( (type == MEMCACHED_CONNECTION_UDP) && (! ptr->flags.use_udp) ) ) return MEMCACHED_INVALID_HOST_PROTOCOL; new_host_list= libmemcached_realloc(ptr, memcached_server_list(ptr), sizeof(memcached_server_st) * (ptr->number_of_hosts + 1)); if (new_host_list == NULL) return MEMCACHED_MEMORY_ALLOCATION_FAILURE; memcached_server_list_set(ptr, new_host_list); /* TODO: Check return type */ instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr)); (void)memcached_server_create_with(ptr, instance, hostname, port, weight, type); ptr->number_of_hosts++; instance= memcached_server_instance_fetch(ptr, 0); memcached_servers_set_count(instance, memcached_server_count(ptr)); return run_distribution(ptr); }
static memcached_return_t memcached_flush_textual(memcached_st *ptr, time_t expiration) { unsigned int x; size_t send_length; memcached_return_t rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; unlikely (memcached_server_count(ptr) == 0) return MEMCACHED_NO_SERVERS; for (x= 0; x < memcached_server_count(ptr); x++) { bool no_reply= ptr->flags.no_reply; memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x); if (expiration) send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "flush_all %llu%s\r\n", (unsigned long long)expiration, no_reply ? " noreply" : ""); else send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "flush_all%s\r\n", no_reply ? " noreply" : ""); rc= memcached_do(instance, buffer, send_length, true); if (rc == MEMCACHED_SUCCESS && !no_reply) (void)memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); } return MEMCACHED_SUCCESS; }
memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list) { uint32_t count; memcached_server_st *new_host_list; uint32_t x; if (! list) return MEMCACHED_SUCCESS; count= memcached_server_list_count(list); new_host_list= libmemcached_realloc(ptr, memcached_server_list(ptr), sizeof(memcached_server_st) * (count + memcached_server_count(ptr))); if (! new_host_list) return MEMCACHED_MEMORY_ALLOCATION_FAILURE; memcached_server_list_set(ptr, new_host_list); for (x= 0; x < count; x++) { memcached_server_write_instance_st instance; if ((ptr->flags.use_udp && list[x].type != MEMCACHED_CONNECTION_UDP) || ((list[x].type == MEMCACHED_CONNECTION_UDP) && ! (ptr->flags.use_udp)) ) return MEMCACHED_INVALID_HOST_PROTOCOL; WATCHPOINT_ASSERT(list[x].hostname[0] != 0); instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr)); /* TODO check return type */ (void)memcached_server_create_with(ptr, instance, list[x].hostname, list[x].port, list[x].weight, list[x].type); ptr->number_of_hosts++; } /* Provides backwards compatibility with server list. */ { memcached_server_write_instance_st instance; instance= memcached_server_instance_fetch(ptr, 0); instance->number_of_hosts= memcached_server_count(ptr); } return run_distribution(ptr); }
static void sort_hosts(memcached_st *ptr) { if (memcached_server_count(ptr)) { memcached_server_write_instance_st instance; qsort(memcached_server_list(ptr), memcached_server_count(ptr), sizeof(memcached_server_st), compare_servers); instance= memcached_server_instance_fetch(ptr, 0); instance->number_of_hosts= memcached_server_count(ptr); } }
void memcached_quit(memcached_st *ptr) { uint32_t x; if (memcached_server_count(ptr) == 0) return; if (memcached_server_count(ptr)) { for (x= 0; x < memcached_server_count(ptr); x++) { memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, x); memcached_quit_server(instance, false); } } }
static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks) { memcached_return_t rc= MEMCACHED_SUCCESS; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; size_t send_length; uint32_t server_key; uint32_t x; unlikely (memcached_server_count(ptr) == 0) return MEMCACHED_NO_SERVERS; for (server_key= 0; server_key < memcached_server_count(ptr); server_key++) { memcached_server_instance_st *instance; instance= memcached_server_instance_fetch(ptr, server_key); /* 256 I BELIEVE is the upper limit of slabs */ for (x= 0; x < 256; x++) { send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "stats cachedump %u 0 0\r\n", x); rc= memcached_do(instance, buffer, send_length, true); unlikely (rc != MEMCACHED_SUCCESS) goto error; while (1) { uint32_t callback_counter; rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); if (rc == MEMCACHED_ITEM) { char *string_ptr, *end_ptr; char *key; string_ptr= buffer; string_ptr+= 5; /* Move past ITEM */ for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++); key= string_ptr; key[(size_t)(end_ptr-string_ptr)]= 0; for (callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++) { rc= (*callback[callback_counter])(ptr, key, (size_t)(end_ptr-string_ptr), context); if (rc != MEMCACHED_SUCCESS) break; } } else if (rc == MEMCACHED_END) break; else if (rc == MEMCACHED_SERVER_ERROR || rc == MEMCACHED_CLIENT_ERROR) { /* If we try to request stats cachedump for a slab class that is too big * the server will return an incorrect error message: * "MEMCACHED_SERVER_ERROR failed to allocate memory" * This isn't really a fatal error, so let's just skip it. I want to * fix the return value from the memcached server to a CLIENT_ERROR, * so let's add support for that as well right now. */ rc= MEMCACHED_END; break; } else goto error; } } } error: if (rc == MEMCACHED_END) return MEMCACHED_SUCCESS; else return rc; }
static inline memcached_return_t memcached_send(memcached_st *ptr, const char *master_key, size_t master_key_length, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags, uint64_t cas, memcached_storage_action_t verb) { bool to_write; size_t write_length; memcached_return_t rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; uint32_t server_key; memcached_server_instance_st *instance; WATCHPOINT_ASSERT(!(value == NULL && value_length > 0)); rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol); unlikely (rc != MEMCACHED_SUCCESS) return rc; unlikely (memcached_server_count(ptr) == 0) return MEMCACHED_NO_SERVERS; if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) return MEMCACHED_BAD_KEY_PROVIDED; if (ptr->flags.binary_protocol) { return memcached_send_binary(ptr, master_key, master_key_length, key, key_length, value, value_length, expiration, flags, cas, verb); } server_key= memcached_generate_hash(ptr, master_key, master_key_length); instance= memcached_server_instance_fetch(ptr, server_key); if (cas) { write_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "%s %.*s%.*s %u %llu %zu %llu%s\r\n", storage_op_string(verb), (int)ptr->prefix_key_length, ptr->prefix_key, (int)key_length, key, flags, (unsigned long long)expiration, value_length, (unsigned long long)cas, (ptr->flags.no_reply) ? " noreply" : ""); } else { char *buffer_ptr= buffer; const char *command= storage_op_string(verb); /* Copy in the command, no space needed, we handle that in the command function*/ memcpy(buffer_ptr, command, strlen(command)); /* Copy in the key prefix, switch to the buffer_ptr */ buffer_ptr= memcpy((buffer_ptr + strlen(command)), ptr->prefix_key, ptr->prefix_key_length); /* Copy in the key, adjust point if a key prefix was used. */ buffer_ptr= memcpy(buffer_ptr + (ptr->prefix_key_length ? ptr->prefix_key_length : 0), key, key_length); buffer_ptr+= key_length; buffer_ptr[0]= ' '; buffer_ptr++; write_length= (size_t)(buffer_ptr - buffer); write_length+= (size_t) snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE, "%u %llu %zu%s\r\n", flags, (unsigned long long)expiration, value_length, ptr->flags.no_reply ? " noreply" : ""); } if (ptr->flags.use_udp && ptr->flags.buffer_requests) { size_t cmd_size= write_length + value_length + 2; if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH) return MEMCACHED_WRITE_FAILURE; if (cmd_size + instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH) memcached_io_write(instance, NULL, 0, true); } if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE) { rc= MEMCACHED_WRITE_FAILURE; goto error; } /* Send command header */ rc= memcached_do(instance, buffer, write_length, false); if (rc != MEMCACHED_SUCCESS) goto error; /* Send command body */ if (memcached_io_write(instance, value, value_length, false) == -1) { rc= MEMCACHED_WRITE_FAILURE; goto error; } if (ptr->flags.buffer_requests && verb == SET_OP) { to_write= false; } else { to_write= true; } if (memcached_io_write(instance, "\r\n", 2, to_write) == -1) { rc= MEMCACHED_WRITE_FAILURE; goto error; } if (ptr->flags.no_reply) return (to_write == false) ? MEMCACHED_BUFFERED : MEMCACHED_SUCCESS; if (to_write == false) return MEMCACHED_BUFFERED; rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); if (rc == MEMCACHED_STORED) return MEMCACHED_SUCCESS; else return rc; error: memcached_io_reset(instance); return rc; }
memcached_return_t memcached_behavior_set(memcached_st *ptr, const memcached_behavior_t flag, uint64_t data) { switch (flag) { case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS: ptr->number_of_replicas= (uint32_t)data; break; case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK: ptr->io_msg_watermark= (uint32_t) data; break; case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK: ptr->io_bytes_watermark= (uint32_t)data; break; case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH: ptr->io_key_prefetch = (uint32_t)data; break; case MEMCACHED_BEHAVIOR_SND_TIMEOUT: ptr->snd_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_RCV_TIMEOUT: ptr->rcv_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT: ptr->server_failure_limit= (uint32_t)data; break; case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL: memcached_quit(ptr); // We need t shutdown all of the connections to make sure we do the correct protocol if (data) { ptr->flags.verify_key= false; } ptr->flags.binary_protocol= set_flag(data); break; case MEMCACHED_BEHAVIOR_SUPPORT_CAS: ptr->flags.support_cas= set_flag(data); break; case MEMCACHED_BEHAVIOR_NO_BLOCK: ptr->flags.no_block= set_flag(data); memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS: ptr->flags.buffer_requests= set_flag(data); memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_USE_UDP: if (memcached_server_count(ptr)) { return MEMCACHED_FAILURE; } ptr->flags.use_udp= set_flag(data); if (data) { ptr->flags.no_reply= set_flag(data); } break; case MEMCACHED_BEHAVIOR_TCP_NODELAY: ptr->flags.tcp_nodelay= set_flag(data); memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE: ptr->flags.tcp_keepalive= set_flag(data); memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_DISTRIBUTION: return memcached_behavior_set_distribution(ptr, (memcached_server_distribution_t)data); case MEMCACHED_BEHAVIOR_KETAMA: { if (data) { (void)memcached_behavior_set_key_hash(ptr, MEMCACHED_HASH_MD5); (void)memcached_behavior_set_distribution_hash(ptr, MEMCACHED_HASH_MD5); (void)memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA); } else { (void)memcached_behavior_set_key_hash(ptr, MEMCACHED_HASH_DEFAULT); (void)memcached_behavior_set_distribution_hash(ptr, MEMCACHED_HASH_DEFAULT); (void)memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_MODULA); } break; } case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: { (void)memcached_behavior_set_key_hash(ptr, MEMCACHED_HASH_MD5); (void)memcached_behavior_set_distribution_hash(ptr, MEMCACHED_HASH_MD5); ptr->flags.ketama_weighted= set_flag(data); /** @note We try to keep the same distribution going. This should be deprecated and rewritten. */ return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA); } case MEMCACHED_BEHAVIOR_HASH: return memcached_behavior_set_key_hash(ptr, (memcached_hash_t)(data)); case MEMCACHED_BEHAVIOR_KETAMA_HASH: return memcached_behavior_set_distribution_hash(ptr, (memcached_hash_t)(data)); case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS: ptr->flags.use_cache_lookups= set_flag(data); memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_VERIFY_KEY: if (ptr->flags.binary_protocol) return MEMCACHED_FAILURE; ptr->flags.verify_key= set_flag(data); break; case MEMCACHED_BEHAVIOR_SORT_HOSTS: { ptr->flags.use_sort_hosts= set_flag(data); run_distribution(ptr); break; } case MEMCACHED_BEHAVIOR_POLL_TIMEOUT: ptr->poll_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT: ptr->connect_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT: ptr->retry_timeout= (int32_t)data; break; case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: ptr->send_size= (int32_t)data; memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: ptr->recv_size= (int32_t)data; memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE: ptr->tcp_keepidle= (uint32_t)data; memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_USER_DATA: return MEMCACHED_FAILURE; case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: ptr->flags.hash_with_prefix_key= set_flag(data); break; case MEMCACHED_BEHAVIOR_NOREPLY: ptr->flags.no_reply= set_flag(data); break; case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS: ptr->flags.auto_eject_hosts= set_flag(data); break; case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ: srandom((uint32_t) time(NULL)); ptr->flags.randomize_replica_read= set_flag(data); break; case MEMCACHED_BEHAVIOR_CORK: { memcached_server_write_instance_st instance; bool action= set_flag(data); if (action == false) { ptr->flags.cork= set_flag(false); return MEMCACHED_SUCCESS; } instance= memcached_server_instance_fetch(ptr, 0); if (! instance) return MEMCACHED_NO_SERVERS; /* We just try the first host, and if it is down we return zero */ memcached_return_t rc; rc= memcached_connect(instance); if (rc != MEMCACHED_SUCCESS) { return rc; } /* Now we test! */ memcached_ternary_t enabled; enabled= test_cork(instance, true); switch (enabled) { case MEM_FALSE: return ptr->cached_errno ? MEMCACHED_ERRNO : MEMCACHED_FAILURE ; case MEM_TRUE: { enabled= test_cork(instance, false); if (enabled == false) // Possible bug in OS? { memcached_quit_server(instance, false); // We should reset everything on this error. return MEMCACHED_ERRNO; // Errno will be true because we will have already set it. } ptr->flags.cork= true; ptr->flags.tcp_nodelay= true; memcached_quit(ptr); // We go on and reset the connections. } break; case MEM_NOT: default: return MEMCACHED_NOT_SUPPORTED; } } break; case MEMCACHED_BEHAVIOR_MAX: default: /* Shouldn't get here */ WATCHPOINT_ASSERT(0); return MEMCACHED_FAILURE; } return MEMCACHED_SUCCESS; }
uint64_t memcached_behavior_get(memcached_st *ptr, const memcached_behavior_t flag) { switch (flag) { case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS: return ptr->number_of_replicas; case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK: return ptr->io_msg_watermark; case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK: return ptr->io_bytes_watermark; case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH: return ptr->io_key_prefetch; case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL: return ptr->flags.binary_protocol; case MEMCACHED_BEHAVIOR_SUPPORT_CAS: return ptr->flags.support_cas; case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS: return ptr->flags.use_cache_lookups; case MEMCACHED_BEHAVIOR_NO_BLOCK: return ptr->flags.no_block; case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS: return ptr->flags.buffer_requests; case MEMCACHED_BEHAVIOR_USE_UDP: return ptr->flags.use_udp; case MEMCACHED_BEHAVIOR_TCP_NODELAY: return ptr->flags.tcp_nodelay; case MEMCACHED_BEHAVIOR_VERIFY_KEY: return ptr->flags.verify_key; case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: return ptr->flags.ketama_weighted; case MEMCACHED_BEHAVIOR_DISTRIBUTION: return ptr->distribution; case MEMCACHED_BEHAVIOR_KETAMA: return (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA) ? (uint64_t) 1 : 0; case MEMCACHED_BEHAVIOR_HASH: return hashkit_get_function(&ptr->hashkit); case MEMCACHED_BEHAVIOR_KETAMA_HASH: return hashkit_get_function(&ptr->distribution_hashkit); case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT: return ptr->server_failure_limit; case MEMCACHED_BEHAVIOR_SORT_HOSTS: return ptr->flags.use_sort_hosts; case MEMCACHED_BEHAVIOR_POLL_TIMEOUT: return (uint64_t)ptr->poll_timeout; case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT: return (uint64_t)ptr->connect_timeout; case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT: return (uint64_t)ptr->retry_timeout; case MEMCACHED_BEHAVIOR_SND_TIMEOUT: return (uint64_t)ptr->snd_timeout; case MEMCACHED_BEHAVIOR_RCV_TIMEOUT: return (uint64_t)ptr->rcv_timeout; case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE: return (uint64_t)ptr->tcp_keepidle; case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: { int sock_size= 0; socklen_t sock_length= sizeof(int); memcached_server_write_instance_st instance; if (ptr->send_size != -1) // If value is -1 then we are using the default return (uint64_t) ptr->send_size; instance= memcached_server_instance_fetch(ptr, 0); if (instance) // If we have an instance we test, otherwise we just set and pray { /* REFACTOR */ /* We just try the first host, and if it is down we return zero */ if ((memcached_connect(instance)) != MEMCACHED_SUCCESS) return 0; if (getsockopt(instance->fd, SOL_SOCKET, SO_SNDBUF, &sock_size, &sock_length)) return 0; /* Zero means error */ } return (uint64_t) sock_size; } case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: { int sock_size= 0; socklen_t sock_length= sizeof(int); memcached_server_write_instance_st instance; if (ptr->recv_size != -1) // If value is -1 then we are using the default return (uint64_t) ptr->recv_size; instance= memcached_server_instance_fetch(ptr, 0); /** @note REFACTOR */ if (instance) { /* We just try the first host, and if it is down we return zero */ if ((memcached_connect(instance)) != MEMCACHED_SUCCESS) return 0; if (getsockopt(instance->fd, SOL_SOCKET, SO_RCVBUF, &sock_size, &sock_length)) return 0; /* Zero means error */ } return (uint64_t) sock_size; } case MEMCACHED_BEHAVIOR_USER_DATA: return MEMCACHED_FAILURE; case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: return ptr->flags.hash_with_prefix_key; case MEMCACHED_BEHAVIOR_NOREPLY: return ptr->flags.no_reply; case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS: return ptr->flags.auto_eject_hosts; case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ: return ptr->flags.randomize_replica_read; case MEMCACHED_BEHAVIOR_CORK: return ptr->flags.cork; case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE: return ptr->flags.tcp_keepalive; case MEMCACHED_BEHAVIOR_MAX: default: WATCHPOINT_ASSERT(0); /* Programming mistake if it gets this far */ return 0; } /* NOTREACHED */ }
static inline memcached_return_t memcached_send(memcached_st *ptr, const char *master_key, size_t master_key_length, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags, uint64_t cas, uint16_t vbucketid, memcached_storage_action_t verb) { bool to_write; size_t write_length; memcached_return_t rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; uint32_t server_key; memcached_server_write_instance_st instance; WATCHPOINT_ASSERT(!(value == NULL && value_length > 0)); rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol); unlikely (rc != MEMCACHED_SUCCESS) return rc; unlikely (memcached_server_count(ptr) == 0) return MEMCACHED_NO_SERVERS; if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) return MEMCACHED_BAD_KEY_PROVIDED; server_key= memcached_generate_hash_with_redistribution(ptr, master_key, master_key_length); instance= memcached_server_instance_fetch(ptr, server_key); instance->read_buffer_length = 0; WATCHPOINT_SET(instance->io_wait_count.read= 0); WATCHPOINT_SET(instance->io_wait_count.write= 0); if (ptr->flags.binary_protocol) { rc= memcached_send_binary(ptr, instance, server_key, key, key_length, value, value_length, expiration, flags, cas, vbucketid, verb); WATCHPOINT_IF_LABELED_NUMBER(instance->io_wait_count.read > 2, "read IO_WAIT", instance->io_wait_count.read); WATCHPOINT_IF_LABELED_NUMBER(instance->io_wait_count.write > 2, "write_IO_WAIT", instance->io_wait_count.write); } else { if (cas) { int check_length; check_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "%s %.*s%.*s %u %llu %lu %llu%s\r\n", storage_op_string(verb), (int)ptr->prefix_key_length, ptr->prefix_key, (int)key_length, key, flags, (unsigned long long)expiration, (unsigned long)value_length, (unsigned long long)cas, (ptr->flags.no_reply) ? " noreply" : ""); if (check_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || check_length < 0) { rc= MEMCACHED_WRITE_FAILURE; memcached_io_reset(instance); return rc; } write_length= check_length; } else { char *buffer_ptr= buffer; const char *command= storage_op_string(verb); /* Copy in the command, no space needed, we handle that in the command function*/ memcpy(buffer_ptr, command, strlen(command)); /* Copy in the key prefix, switch to the buffer_ptr */ buffer_ptr= memcpy((buffer_ptr + strlen(command)), ptr->prefix_key, ptr->prefix_key_length); /* Copy in the key, adjust point if a key prefix was used. */ buffer_ptr= memcpy(buffer_ptr + (ptr->prefix_key_length ? ptr->prefix_key_length : 0), key, key_length); buffer_ptr+= key_length; buffer_ptr[0]= ' '; buffer_ptr++; write_length= (size_t)(buffer_ptr - buffer); int check_length; check_length= snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE -(size_t)(buffer_ptr - buffer), "%u %llu %lu%s\r\n", flags, (unsigned long long)expiration, (unsigned long)value_length, ptr->flags.no_reply ? " noreply" : ""); if ((size_t)check_length >= MEMCACHED_DEFAULT_COMMAND_SIZE -(size_t)(buffer_ptr - buffer) || check_length < 0) { rc= MEMCACHED_WRITE_FAILURE; memcached_io_reset(instance); return rc; } write_length+= (size_t)check_length; WATCHPOINT_ASSERT(write_length < MEMCACHED_DEFAULT_COMMAND_SIZE); } if (ptr->flags.use_udp && ptr->flags.buffer_requests) { size_t cmd_size= write_length + value_length + 2; if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH) return MEMCACHED_WRITE_FAILURE; if (cmd_size + instance->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH) memcached_io_write(instance, NULL, 0, true); } if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE) { rc= MEMCACHED_WRITE_FAILURE; } else { struct libmemcached_io_vector_st vector[]= { { .length= write_length, .buffer= buffer }, { .length= value_length, .buffer= value }, { .length= 2, .buffer= "\r\n" } };