memcached_return_t memcached_vdo(memcached_server_write_instance_st ptr, const struct libmemcached_io_vector_st *vector, size_t count, bool with_flush) { memcached_return_t rc; ssize_t sent_length; size_t command_length= 0; uint32_t x; WATCHPOINT_ASSERT(count); WATCHPOINT_ASSERT(vector); 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_writev(ptr, vector, count, with_flush); 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); WATCHPOINT_ERRNO(errno); } else if ((ptr->root->flags.no_reply) == 0) { memcached_server_response_increment(ptr); } return rc; }
static ssize_t io_flush(memcached_server_st *ptr, memcached_return *error) { size_t sent_length; size_t return_length; char *local_write_ptr= ptr->write_buffer; size_t write_length= ptr->write_buffer_offset; *error= MEMCACHED_SUCCESS; if (ptr->write_buffer_offset == 0) return 0; /* Looking for memory overflows */ if (write_length == MEMCACHED_MAX_BUFFER) WATCHPOINT_ASSERT(ptr->write_buffer == local_write_ptr); WATCHPOINT_ASSERT((ptr->write_buffer + MEMCACHED_MAX_BUFFER) >= (local_write_ptr + write_length)); return_length= 0; while (write_length) { WATCHPOINT_ASSERT(write_length > 0); sent_length= 0; if (ptr->type == MEMCACHED_CONNECTION_UDP) { struct addrinfo *ai; ai= ptr->address_info; /* Crappy test code */ char buffer[HUGE_STRING_LEN + 8]; memset(buffer, 0, HUGE_STRING_LEN + 8); memcpy (buffer+8, local_write_ptr, write_length); buffer[0]= 0; buffer[1]= 0; buffer[2]= 0; buffer[3]= 0; buffer[4]= 0; buffer[5]= 1; buffer[6]= 0; buffer[7]= 0; sent_length= sendto(ptr->fd, buffer, write_length + 8, 0, (struct sockaddr *)ai->ai_addr, ai->ai_addrlen); if (sent_length == -1) { WATCHPOINT_ERRNO(errno); WATCHPOINT_ASSERT(0); } sent_length-= 8; /* We remove the header */ } else { if ((ssize_t)(sent_length= write(ptr->fd, local_write_ptr, write_length)) == -1) { switch (errno) { case ENOBUFS: continue; case EAGAIN: { memcached_return rc; rc= io_wait(ptr, MEM_WRITE); if (rc == MEMCACHED_SUCCESS) continue; memcached_quit_server(ptr, 1); return -1; } default: memcached_quit_server(ptr, 1); ptr->cached_errno= errno; *error= MEMCACHED_ERRNO; return -1; } } } local_write_ptr+= sent_length; write_length-= sent_length; return_length+= sent_length; } WATCHPOINT_ASSERT(write_length == 0); WATCHPOINT_ASSERT(return_length == ptr->write_buffer_offset); ptr->write_buffer_offset= 0; return return_length; }