liMemcachedRequest* li_memcached_get(liMemcachedCon *con, GString *key, liMemcachedCB callback, gpointer cb_data, GError **err) { int_request* req; if (!li_memcached_is_key_valid(key)) { g_set_error(err, LI_MEMCACHED_ERROR, LI_MEMCACHED_BAD_KEY, "Invalid key: '%s'", key->str); return NULL; } if (-1 == con->fd) memcached_connect(con); if (-1 == con->fd) { if (NULL == con->err) { g_set_error(err, LI_MEMCACHED_ERROR, LI_MEMCACHED_DISABLED, "Not connected"); } else if (err) { *err = g_error_copy(con->err); } return NULL; } req = g_slice_new0(int_request); req->req.callback = callback; req->req.cb_data = cb_data; req->type = REQ_GET; req->key = g_string_new_len(GSTR_LEN(key)); if (!push_request(con, req, err)) { free_request(con, req); return NULL; } return &req->req; }
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) { 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, 1); sent_length= memcached_io_write(ptr, command, command_length, (char) with_flush); if (sent_length == -1 || (size_t)sent_length != command_length) rc= MEMCACHED_WRITE_FAILURE; else if ((ptr->root->flags & MEM_NOREPLY) == 0) memcached_server_response_increment(ptr); return rc; }
liMemcachedCon* li_memcached_con_new(liEventLoop *loop, liSocketAddress addr) { liMemcachedCon* con = g_slice_new0(liMemcachedCon); con->refcount = 1; con->addr = li_sockaddr_dup(addr); con->tmpstr = g_string_sized_new(511); con->fd = -1; li_event_io_init(loop, "memcached", &con->con_watcher, memcached_io_cb, -1, 0); li_event_set_keep_loop_alive(&con->con_watcher, FALSE); memcached_connect(con); return con; }
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 void close_con(liMemcachedCon *con) { if (con->line) con->line->used = 0; if (con->remaining) con->remaining->used = 0; if (con->data) con->data->used = 0; if (con->buf) con->buf->used = 0; reset_item(&con->curitem); send_queue_reset(&con->out); memcached_stop_io(con); close(li_event_io_fd(&con->con_watcher)); con->fd = -1; li_event_io_set_fd(&con->con_watcher, -1); con->cur_req = NULL; cancel_all_requests(con); memcached_connect(con); }
liMemcachedCon* li_memcached_con_new(struct ev_loop *loop, liSocketAddress addr) { liMemcachedCon* con = g_slice_new0(liMemcachedCon); con->refcount = 1; con->loop = loop; con->addr = li_sockaddr_dup(addr); con->tmpstr = g_string_sized_new(511); con->fd = -1; ev_io_init(&con->con_watcher, memcached_io_cb, -1, 0); con->con_watcher.data = con; memcached_connect(con); return con; }
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; }
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 void memcached_io_cb(liEventBase *watcher, int events) { liMemcachedCon *con = LI_CONTAINER_OF(li_event_io_from(watcher), liMemcachedCon, con_watcher); if (1 == g_atomic_int_get(&con->refcount) && li_event_active(&con->con_watcher)) { memcached_stop_io(con); return; } if (-1 == con->fd) { memcached_connect(con); return; } li_memcached_con_acquire(con); /* make sure con isn't freed in the middle of something */ if (events & LI_EV_WRITE) { int i; ssize_t written, len; gchar *data; send_item *si; si = g_queue_peek_head(&con->out); for (i = 0; si && (i < 10); i++) { /* don't send more than 10 chunks */ data = si->buf->addr + si->pos; len = si->len; written = write(li_event_io_fd(&con->con_watcher), data, len); if (written < 0) { switch (errno) { case EINTR: continue; case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif goto write_eagain; default: /* Fatal error, connection has to be closed */ g_clear_error(&con->err); g_set_error(&con->err, LI_MEMCACHED_ERROR, LI_MEMCACHED_CONNECTION, "Couldn't write socket '%s': %s", li_sockaddr_to_string(con->addr, con->tmpstr, TRUE)->str, g_strerror(errno)); close_con(con); goto out; } } else { si->pos += written; si->len -= written; if (0 == si->len) { send_queue_item_free(si); g_queue_pop_head(&con->out); si = g_queue_peek_head(&con->out); } } } write_eagain: send_queue_clean(&con->out); } if (events & LI_EV_READ) { do { handle_read(con); } while (con->remaining && con->remaining->used > 0); } out: memcached_update_io(con); li_memcached_con_release(con); }
uint64_t memcached_behavior_get(memcached_st *ptr, memcached_behavior flag) { memcached_flags temp_flag= MEM_NO_BLOCK; switch (flag) { 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: temp_flag= MEM_BINARY_PROTOCOL; break; case MEMCACHED_BEHAVIOR_SUPPORT_CAS: temp_flag= MEM_SUPPORT_CAS; break; case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS: temp_flag= MEM_USE_CACHE_LOOKUPS; break; case MEMCACHED_BEHAVIOR_NO_BLOCK: temp_flag= MEM_NO_BLOCK; break; case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS: temp_flag= MEM_BUFFER_REQUESTS; break; case MEMCACHED_BEHAVIOR_USE_UDP: temp_flag= MEM_USE_UDP; break; case MEMCACHED_BEHAVIOR_TCP_NODELAY: temp_flag= MEM_TCP_NODELAY; break; case MEMCACHED_BEHAVIOR_VERIFY_KEY: temp_flag= MEM_VERIFY_KEY; break; case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: temp_flag= MEM_KETAMA_WEIGHTED; break; 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 ptr->hash; case MEMCACHED_BEHAVIOR_KETAMA_HASH: return ptr->hash_continuum; case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT: return ptr->server_failure_limit; case MEMCACHED_BEHAVIOR_SORT_HOSTS: temp_flag= MEM_USE_SORT_HOSTS; break; 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_POLL_MAX_RETRIES: return (uint64_t)ptr->poll_max_retries; case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: { int sock_size; socklen_t sock_length= sizeof(int); /* REFACTOR */ /* We just try the first host, and if it is down we return zero */ if ((memcached_connect(&ptr->hosts[0])) != MEMCACHED_SUCCESS) return 0; if (getsockopt(ptr->hosts[0].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; socklen_t sock_length= sizeof(int); /* REFACTOR */ /* We just try the first host, and if it is down we return zero */ if ((memcached_connect(&ptr->hosts[0])) != MEMCACHED_SUCCESS) return 0; if (getsockopt(ptr->hosts[0].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: temp_flag= MEM_HASH_WITH_PREFIX_KEY; break; case MEMCACHED_BEHAVIOR_NOREPLY: temp_flag= MEM_NOREPLY; break; case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS: temp_flag= MEM_AUTO_EJECT_HOSTS; break; default: WATCHPOINT_ASSERT(flag); break; } WATCHPOINT_ASSERT(temp_flag); /* Programming mistake if it gets this far */ if (ptr->flags & temp_flag) return 1; else return 0; }
static int memcached_query_daemon (char *buffer, size_t buffer_size, memcached_t *st) { int fd = -1; int status; size_t buffer_fill; fd = memcached_connect (st); if (fd < 0) { ERROR ("memcached plugin: Instance \"%s\" could not connect to daemon.", st->name); return -1; } status = (int) swrite (fd, "stats\r\n", strlen ("stats\r\n")); if (status != 0) { char errbuf[1024]; ERROR ("memcached plugin: write(2) failed: %s", sstrerror (errno, errbuf, sizeof (errbuf))); shutdown(fd, SHUT_RDWR); close (fd); return (-1); } /* receive data from the memcached daemon */ memset (buffer, 0, buffer_size); buffer_fill = 0; while ((status = (int) recv (fd, buffer + buffer_fill, buffer_size - buffer_fill, /* flags = */ 0)) != 0) { char const end_token[5] = {'E', 'N', 'D', '\r', '\n'}; if (status < 0) { char errbuf[1024]; if ((errno == EAGAIN) || (errno == EINTR)) continue; ERROR ("memcached: Error reading from socket: %s", sstrerror (errno, errbuf, sizeof (errbuf))); shutdown(fd, SHUT_RDWR); close (fd); return (-1); } buffer_fill += (size_t) status; if (buffer_fill > buffer_size) { buffer_fill = buffer_size; WARNING ("memcached plugin: Message was truncated."); break; } /* If buffer ends in end_token, we have all the data. */ if (memcmp (buffer + buffer_fill - sizeof (end_token), end_token, sizeof (end_token)) == 0) break; } /* while (recv) */ status = 0; if (buffer_fill == 0) { WARNING ("memcached plugin: No data returned by memcached."); status = -1; } shutdown(fd, SHUT_RDWR); close(fd); return (status); } /* int memcached_query_daemon */