static memcached_return binary_incr_decr(memcached_st *ptr, uint8_t cmd, const char *key, size_t key_length, uint32_t offset, uint64_t *value) { unsigned int server_key; #ifndef _MSC_VER protocol_binary_request_incr request= {.bytes= {0}}; #else protocol_binary_request_incr request= {0}; #endif unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0) return MEMCACHED_NO_SERVERS; server_key= memcached_generate_hash(ptr, key, key_length); request.message.header.request.magic= PROTOCOL_BINARY_REQ; request.message.header.request.opcode= cmd; request.message.header.request.keylen= htons((uint16_t)key_length); request.message.header.request.extlen= 20; request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES; request.message.header.request.bodylen= htonl(key_length + request.message.header.request.extlen); request.message.body.delta= htonll(offset); /* TODO: The binary protocol allows you to specify initial and expiry time */ if ((memcached_do(&ptr->hosts[server_key], request.bytes, sizeof(request.bytes), 0)!=MEMCACHED_SUCCESS) || (memcached_io_write(&ptr->hosts[server_key], key, key_length, 1) == -1)) { memcached_io_reset(&ptr->hosts[server_key]); return MEMCACHED_WRITE_FAILURE; } return memcached_response(&ptr->hosts[server_key], (char*)value, sizeof(*value), NULL); }
static memcached_return binary_stats_fetch(memcached_st *ptr, memcached_stat_st *stat, char *args, unsigned int server_key) { memcached_return rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; protocol_binary_request_stats request= {0}; request.message.header.request.magic= PROTOCOL_BINARY_REQ; request.message.header.request.opcode= PROTOCOL_BINARY_CMD_STAT; request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES; if (args != NULL) { int len= strlen(args); rc= memcached_validate_key_length(len, true); unlikely (rc != MEMCACHED_SUCCESS) return rc; request.message.header.request.keylen= htons((uint16_t)len); request.message.header.request.bodylen= htonl(len); if ((memcached_do(&ptr->hosts[server_key], request.bytes, sizeof(request.bytes), 0) != MEMCACHED_SUCCESS) || (memcached_io_write(&ptr->hosts[server_key], args, len, 1) == -1)) { memcached_io_reset(&ptr->hosts[server_key]); return MEMCACHED_WRITE_FAILURE; } }
memcached_return_t memcached_response(memcached_server_write_instance_st ptr, char *buffer, size_t buffer_length, memcached_result_st *result) { /* We may have old commands in the buffer not set, first purge */ if ((ptr->root->flags.no_block) && (memcached_is_processing_input(ptr->root) == false)) { (void)memcached_io_write(ptr, NULL, 0, true); } /* * The previous implementation purged all pending requests and just * returned the last one. Purge all pending messages to ensure backwards * compatibility. But this breaks prefetching, so we only make it when * mget_flush_old_results is true. */ if ((ptr->root->flags.mget_flush_old_results) && (ptr->root->flags.binary_protocol == false)) while (memcached_server_response_count(ptr) > 1) { memcached_return_t rc= memcached_read_one_response(ptr, buffer, buffer_length, result); unlikely (rc != MEMCACHED_END && rc != MEMCACHED_STORED && rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STAT && rc != MEMCACHED_DELETED && rc != MEMCACHED_NOTFOUND && rc != MEMCACHED_NOTSTORED && rc != MEMCACHED_DATA_EXISTS) return rc; } return memcached_read_one_response(ptr, buffer, buffer_length, result); }
memcached_return_t memcached_do(memcached_server_write_instance_st ptr, const void *command, size_t command_length, bool with_flush) { memcached_return_t rc; ssize_t sent_length; WATCHPOINT_ASSERT(command_length); WATCHPOINT_ASSERT(command); if ((rc= memcached_connect(ptr)) != MEMCACHED_SUCCESS) { WATCHPOINT_ERROR(rc); return rc; } /* ** Since non buffering ops in UDP mode dont check to make sure they will fit ** before they start writing, if there is any data in buffer, clear it out, ** otherwise we might get a partial write. **/ if (ptr->type == MEMCACHED_CONNECTION_UDP && with_flush && ptr->write_buffer_offset > UDP_DATAGRAM_HEADER_LENGTH) { memcached_io_write(ptr, NULL, 0, true); } sent_length= memcached_io_write(ptr, command, command_length, with_flush); if (sent_length == -1 || (size_t)sent_length != command_length) { rc= MEMCACHED_WRITE_FAILURE; } else if ((ptr->root->flags.no_reply) == 0) { memcached_server_response_increment(ptr); } return rc; }
memcached_return memcached_flush_buffers(memcached_st *mem) { memcached_return ret= MEMCACHED_SUCCESS; for (int x= 0; x < mem->number_of_hosts; ++x) if (mem->hosts[x].write_buffer_offset != 0) { if (mem->hosts[x].fd == -1 && (ret= memcached_connect(&mem->hosts[x])) != MEMCACHED_SUCCESS) { WATCHPOINT_ERROR(ret); return ret; } if (memcached_io_write(&mem->hosts[x], NULL, 0, 1) == -1) ret= MEMCACHED_SOME_ERRORS; } return ret; }
memcached_return memcached_do(memcached_server_st *ptr, const void *command, size_t command_length, uint8_t with_flush) { memcached_return rc; ssize_t sent_length; WATCHPOINT_ASSERT(command_length); WATCHPOINT_ASSERT(command); if ((rc= memcached_connect(ptr)) != MEMCACHED_SUCCESS) return rc; sent_length= memcached_io_write(ptr, command, command_length, with_flush); if (sent_length == -1 || sent_length != command_length) rc= MEMCACHED_WRITE_FAILURE; else memcached_server_response_increment(ptr); return rc; }
memcached_return memcached_vdo(memcached_server_st *ptr, const struct libmemcached_io_vector_st *vector, size_t count, uint8_t with_flush) { memcached_return rc; ssize_t sent_length; size_t command_length; uint32_t x; WATCHPOINT_ASSERT(count); WATCHPOINT_ASSERT(vector); if ((rc= memcached_connect(ptr)) != MEMCACHED_SUCCESS) { WATCHPOINT_ERROR(rc); return rc; } if (ptr->type == MEMCACHED_CONNECTION_UDP && with_flush && ptr->write_buffer_offset > UDP_DATAGRAM_HEADER_LENGTH) { memcached_io_write(ptr, NULL, 0, true); } sent_length= memcached_io_writev(ptr, vector, count, (char) with_flush); command_length = 0; for (x= 0; x < count; ++x, vector++) command_length+= vector->length; if (sent_length == -1 || (size_t)sent_length != command_length) { rc = MEMCACHED_WRITE_FAILURE; WATCHPOINT_ERROR(rc); } else if ((ptr->root->flags & MEM_NOREPLY) == 0) memcached_server_response_increment(ptr); 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_purge(memcached_server_write_instance_st ptr) { uint32_t x; memcached_return_t ret= MEMCACHED_SUCCESS; memcached_st *root= (memcached_st *)ptr->root; uint32_t no_msg; if (memcached_is_purging(ptr->root) || /* already purging */ (memcached_server_response_count(ptr) < ptr->root->io_msg_watermark && ptr->io_bytes_sent < ptr->root->io_bytes_watermark) || (ptr->io_bytes_sent >= ptr->root->io_bytes_watermark && memcached_server_response_count(ptr) < 2)) { return MEMCACHED_SUCCESS; } /* memcached_io_write and memcached_response may call memcached_purge so we need to be able stop any recursion.. */ memcached_set_purging(root, true); WATCHPOINT_ASSERT(ptr->fd != -1); /* Force a flush of the buffer to ensure that we don't have the n-1 pending requests buffered up.. */ if (memcached_io_write(ptr, NULL, 0, true) == -1) { memcached_set_purging(root, true); return MEMCACHED_WRITE_FAILURE; } WATCHPOINT_ASSERT(ptr->fd != -1); no_msg= memcached_server_response_count(ptr) - 1; if (no_msg > 0) { memcached_result_st result; memcached_result_st *result_ptr; char buffer[SMALL_STRING_LEN]; /* * We need to increase the timeout, because we might be waiting for * data to be sent from the server (the commands was in the output buffer * and just flushed */ const int32_t timeo= ptr->root->poll_timeout; root->poll_timeout= 2000; result_ptr= memcached_result_create(root, &result); WATCHPOINT_ASSERT(result_ptr); for (x= 0; x < no_msg; x++) { memcached_return_t rc; memcached_result_reset(result_ptr); rc= memcached_read_one_response(ptr, buffer, sizeof (buffer), result_ptr); /* * Purge doesn't care for what kind of command results that is received. * The only kind of errors I care about if is I'm out of sync with the * protocol or have problems reading data from the network.. */ if (rc== MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_UNKNOWN_READ_FAILURE) { WATCHPOINT_ERROR(rc); ret = rc; memcached_io_reset(ptr); } if (ptr->root->callbacks != NULL) { memcached_callback_st cb = *ptr->root->callbacks; if (rc == MEMCACHED_SUCCESS) { uint32_t y; for (y= 0; y < cb.number_of_callback; y++) { rc = (*cb.callback[y])(ptr->root, result_ptr, cb.context); if (rc != MEMCACHED_SUCCESS) break; } } } } memcached_result_free(result_ptr); root->poll_timeout= timeo; } memcached_set_purging(root, false); return ret; }
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" } };
static inline memcached_return 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 verb) { char to_write; size_t write_length; ssize_t sent_length; memcached_return rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; unsigned int server_key; WATCHPOINT_ASSERT(!(value == NULL && value_length > 0)); rc= memcached_validate_key_length(key_length, ptr->flags & MEM_BINARY_PROTOCOL); unlikely (rc != MEMCACHED_SUCCESS) return rc; unlikely (ptr->number_of_hosts == 0) return MEMCACHED_NO_SERVERS; if ((ptr->flags & MEM_VERIFY_KEY) && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) return MEMCACHED_BAD_KEY_PROVIDED; if (ptr->flags & MEM_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); 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), ptr->prefix_key, (int)key_length, key, flags, (unsigned long long)expiration, value_length, (unsigned long long)cas, (ptr->flags & MEM_NOREPLY) ? " 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, strlen(ptr->prefix_key)); /* Copy in the key, adjust point if a key prefix was used. */ buffer_ptr= memcpy(buffer_ptr + (ptr->prefix_key ? strlen(ptr->prefix_key) : 0), key, key_length); buffer_ptr+= key_length; buffer_ptr[0]= ' '; buffer_ptr++; write_length= (size_t)(buffer_ptr - buffer); if (verb == DELETE_OP) { if (ptr->flags & MEM_NOREPLY) write_length+= (size_t) snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE, "noreply"); } else { 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 & MEM_NOREPLY) ? " noreply" : ""); } } if (ptr->flags & MEM_USE_UDP && ptr->flags & MEM_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 + ptr->hosts[server_key].write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH) memcached_io_write(&ptr->hosts[server_key], NULL, 0, 1); } if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE) return MEMCACHED_WRITE_FAILURE; /* Send command header */ rc= memcached_do(&ptr->hosts[server_key], buffer, write_length, 0); if (rc != MEMCACHED_SUCCESS) return rc; /* Send command body */ if ((sent_length= memcached_io_write(&ptr->hosts[server_key], value, value_length, 0)) == -1) return MEMCACHED_WRITE_FAILURE; if ((ptr->flags & MEM_BUFFER_REQUESTS) && (verb == SET_OP || verb == PREPEND_OP || verb == APPEND_OP || verb == DELETE_OP)) to_write= 0; else to_write= 1; if ((sent_length= memcached_io_write(&ptr->hosts[server_key], "\r\n", 2, to_write)) == -1) return MEMCACHED_WRITE_FAILURE; if (ptr->flags & MEM_NOREPLY) return (to_write == 0) ? MEMCACHED_BUFFERED : MEMCACHED_SUCCESS; if (to_write == 0) return MEMCACHED_BUFFERED; rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); if (rc == MEMCACHED_STORED || rc == MEMCACHED_DELETED) return MEMCACHED_SUCCESS; return rc; }
static inline memcached_return 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 verb) { char to_write; size_t write_length; ssize_t sent_length; memcached_return rc; char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; unsigned int server_key; WATCHPOINT_ASSERT(!(value == NULL && value_length > 0)); rc= memcached_validate_key_length(key_length, ptr->flags & MEM_BINARY_PROTOCOL); unlikely (rc != MEMCACHED_SUCCESS) return rc; unlikely (ptr->number_of_hosts == 0) return MEMCACHED_NO_SERVERS; if ((ptr->flags & MEM_VERIFY_KEY) && (memcachd_key_test((char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)) return MEMCACHED_BAD_KEY_PROVIDED; server_key= memcached_generate_hash(ptr, master_key, master_key_length); if (ptr->flags & MEM_BINARY_PROTOCOL) return memcached_send_binary(&ptr->hosts[server_key], key, key_length, value, value_length, expiration, flags, cas, verb); #ifndef _WIN32 if (cas) write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "%s %s%.*s %u %llu %zu %llu%s\r\n", storage_op_string(verb), ptr->prefix_key, (int)key_length, key, flags, (unsigned long long)expiration, value_length, (unsigned long long)cas, (ptr->flags & MEM_NOREPLY) ? " noreply" : ""); else write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "%s %s%.*s %u %llu %zu%s\r\n", storage_op_string(verb), ptr->prefix_key, (int)key_length, key, flags, (unsigned long long)expiration, value_length, (ptr->flags & MEM_NOREPLY) ? " noreply" : ""); #else if (cas) write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "%s %s%.*s %u %llu %u %llu%s\r\n", storage_op_string(verb), ptr->prefix_key, (int)key_length, key, flags, (unsigned long long)expiration, value_length, (unsigned long long)cas, (ptr->flags & MEM_NOREPLY) ? " noreply" : ""); else write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "%s %s%.*s %u %llu %u%s\r\n", storage_op_string(verb), ptr->prefix_key, (int)key_length, key, flags, (unsigned long long)expiration, value_length, (ptr->flags & MEM_NOREPLY) ? " noreply" : ""); #endif if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE) { rc= MEMCACHED_WRITE_FAILURE; goto error; } /* Send command header */ rc= memcached_do(&ptr->hosts[server_key], buffer, write_length, 0); if (rc != MEMCACHED_SUCCESS) goto error; /* Send command body */ if ((sent_length= memcached_io_write(&ptr->hosts[server_key], value, value_length, 0)) == -1) { rc= MEMCACHED_WRITE_FAILURE; goto error; } if ((ptr->flags & MEM_BUFFER_REQUESTS) && verb == SET_OP) to_write= 0; else to_write= 1; if ((sent_length= memcached_io_write(&ptr->hosts[server_key], "\r\n", 2, to_write)) == -1) { rc= MEMCACHED_WRITE_FAILURE; goto error; } if (ptr->flags & MEM_NOREPLY) { memcached_server_response_decrement(&ptr->hosts[server_key]); return (to_write == 0) ? MEMCACHED_BUFFERED : MEMCACHED_SUCCESS; } if (to_write == 0) return MEMCACHED_BUFFERED; rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); if (rc == MEMCACHED_STORED) return MEMCACHED_SUCCESS; else return rc; error: memcached_io_reset(&ptr->hosts[server_key]); return rc; }