示例#1
0
memcached_result_st *memcached_result_create(const memcached_st *memc,
                                             memcached_result_st *ptr)
{
  WATCHPOINT_ASSERT(memc);

  /* Saving malloc calls :) */
  if (ptr)
  {
    ptr->options.is_allocated= false;
  }
  else
  {
    ptr= libmemcached_malloc(memc, sizeof(memcached_result_st));

    if (ptr == NULL)
      return NULL;

    ptr->options.is_allocated= true;
  }

  ptr->options.is_initialized= true;

  _result_init(ptr, memc);

  ptr->root= memc;
  WATCHPOINT_SET(ptr->value.options.is_initialized= false);
  memcached_string_create(memc, &ptr->value, 0);
  WATCHPOINT_ASSERT_INITIALIZED(&ptr->value);
  WATCHPOINT_ASSERT(ptr->value.string == NULL);

  return ptr;
}
示例#2
0
static const char *lookup_help(memcached_options option)
{
  switch (option)
  {
  case OPT_SERVERS: return("List which servers you wish to connect to.");
  case OPT_VERSION: return("Display the version of the application and then exit.");
  case OPT_HELP: return("Display this message and then exit.");
  case OPT_VERBOSE: return("Give more details on the progression of the application.");
  case OPT_DEBUG: return("Provide output only useful for debugging.");
  case OPT_FLAG: return("Provide flag information for storage operation.");
  case OPT_EXPIRE: return("Set the expire option for the object.");
  case OPT_SET: return("Use set command with memcached when storing.");
  case OPT_REPLACE: return("Use replace command with memcached when storing.");
  case OPT_ADD: return("Use add command with memcached when storing.");
  case OPT_SLAP_EXECUTE_NUMBER: return("Number of times to execute the given test.");
  case OPT_SLAP_INITIAL_LOAD: return("Number of key pairs to load before executing tests.");
  case OPT_SLAP_TEST: return("Test to run (currently \"get\" or \"set\").");
  case OPT_SLAP_CONCURRENCY: return("Number of users to simulate with load.");
  case OPT_SLAP_NON_BLOCK: return("Set TCP up to use non-blocking IO.");
  case OPT_SLAP_TCP_NODELAY: return("Set TCP socket up to use nodelay.");
  case OPT_FLUSH: return("Flush servers before running tests.");
  case OPT_HASH: return("Select hash type.");
  case OPT_BINARY: return("Switch to binary protocol.");
  case OPT_ANALYZE: return("Analyze the provided servers.");
  case OPT_UDP: return("Use UDP protocol when communicating with server.");
  default: WATCHPOINT_ASSERT(0);
  };

  WATCHPOINT_ASSERT(0);
  return "forgot to document this function :)";
}
示例#3
0
memcached_result_st *memcached_result_create(memcached_st *memc, 
                                             memcached_result_st *ptr)
{
  /* Saving malloc calls :) */
  if (ptr)
  {
    memset(ptr, 0, sizeof(memcached_result_st));
    ptr->is_allocated= MEMCACHED_NOT_ALLOCATED;
  }
  else
  {
    if (memc->call_malloc)
      ptr= (memcached_result_st *)memc->call_malloc(memc, sizeof(memcached_result_st));
    else
      ptr= (memcached_result_st *)malloc(sizeof(memcached_result_st));

    if (ptr == NULL)
      return NULL;
    memset(ptr, 0, sizeof(memcached_result_st));
    ptr->is_allocated= MEMCACHED_ALLOCATED;
  }

  ptr->root= memc;
  memcached_string_create(memc, &ptr->value, 0);
  WATCHPOINT_ASSERT(ptr->value.string == NULL);
  WATCHPOINT_ASSERT(ptr->value.is_allocated == MEMCACHED_NOT_ALLOCATED);

  return ptr;
}
示例#4
0
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;
}
示例#5
0
static test_return_t drizzle(memcached_st *memc)
{
  memcached_return_t rc;
  char *return_value;
  size_t return_value_length;
  uint32_t flags;

infinite:
  for (size_t x= 0; x < TEST_COUNTER; x++)
  {
    uint32_t test_bit;
    uint8_t which;

    test_bit= (uint32_t)(random() % GLOBAL_COUNT);
    which= (uint8_t)(random() % 2);

    if (which == 0)
    {
      return_value= memcached_get(memc, global_keys[test_bit], global_keys_length[test_bit],
                                  &return_value_length, &flags, &rc);
      if (rc == MEMCACHED_SUCCESS && return_value)
      {
        free(return_value);
      }
      else if (rc == MEMCACHED_NOTFOUND)
      {
        continue;
      }
      else
      {
        WATCHPOINT_ERROR(rc);
        WATCHPOINT_ASSERT(rc);
      }
    }
    else
    {
      rc= memcached_set(memc, global_pairs[test_bit].key,
                        global_pairs[test_bit].key_length,
                        global_pairs[test_bit].value,
                        global_pairs[test_bit].value_length,
                        0, 0);
      if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED)
      {
        WATCHPOINT_ERROR(rc);
        WATCHPOINT_ASSERT(0);
      }
    }
  }

  if (getenv("MEMCACHED_ATOM_BURIN_IN"))
    goto infinite;

  return TEST_SUCCESS;
}
示例#6
0
文件: do.c 项目: bsmr-couchbase/moxi
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;
}
示例#7
0
/*
  One version is public and will not modify the distribution hash, the other will.
*/
static uint32_t _generate_hash_wrapper(const memcached_st *ptr, const char *key, size_t key_length)
{
  WATCHPOINT_ASSERT(memcached_server_count(ptr));

  if (memcached_server_count(ptr) == 1)
    return 0;

  if (ptr->flags.hash_with_prefix_key)
  {
    size_t temp_length= ptr->prefix_key_length + key_length;
    char *temp = malloc(temp_length);
    uint32_t ret;

    if (temp_length > MEMCACHED_MAX_KEY -1)
      return 0;

    strncpy(temp, ptr->prefix_key, ptr->prefix_key_length);
    strncpy(temp + ptr->prefix_key_length, key, key_length);

    ret = generate_hash(ptr, temp, temp_length);
    free(temp);
    return ret;
  }
  else
  {
    return generate_hash(ptr, key, key_length);
  }
}
示例#8
0
static memcached_return io_wait(memcached_server_st *ptr,
                                memc_read_or_write read_or_write)
{
  struct pollfd fds[1];
  short flags= 0;
  int error;

  if (read_or_write == MEM_WRITE) /* write */
    flags= POLLOUT |  POLLERR;
  else
    flags= POLLIN | POLLERR;

  memset(&fds, 0, sizeof(struct pollfd));
  fds[0].fd= ptr->fd;
  fds[0].events= flags;

  error= poll(fds, 1, ptr->root->poll_timeout);

  if (error == 1)
    return MEMCACHED_SUCCESS;
  else if (error == 0)
  {
    return MEMCACHED_TIMEOUT;
  }

  /* Imposssible for anything other then -1 */
  WATCHPOINT_ASSERT(error == -1);
  memcached_quit_server(ptr, 1);

  return MEMCACHED_FAILURE;

}
示例#9
0
memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list)
{
  unsigned int x;
  uint16_t count;
  memcached_server_st *new_host_list;

  if (!list)
    return MEMCACHED_SUCCESS;

  count= list[0].count;
  if (ptr->call_realloc)
    new_host_list= 
      (memcached_server_st *)ptr->call_realloc(ptr, ptr->hosts, 
                                               sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
  else
    new_host_list= 
      (memcached_server_st *)realloc(ptr->hosts, 
                                     sizeof(memcached_server_st) * (count + ptr->number_of_hosts));

  if (!new_host_list)
    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;

  ptr->hosts= new_host_list;

  for (x= 0; x < count; x++)
  {
    WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
    host_reset(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname, 
               list[x].port, list[x].weight, list[x].type);
    ptr->number_of_hosts++;
  }
  ptr->hosts[0].count= ptr->number_of_hosts;

  return run_distribution(ptr);
}
示例#10
0
memcached_st *memcached_create(memcached_st *ptr)
{
  memcached_result_st *result_ptr;
#ifdef _WIN32
  WSADATA wsaData;
  WSAStartup(MAKEWORD(2, 0), &wsaData);
#endif

  if (ptr == NULL)
  {
    ptr= (memcached_st *)malloc(sizeof(memcached_st));

    if (!ptr)
      return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */

    memset(ptr, 0, sizeof(memcached_st));
    ptr->is_allocated= true;
  }
  else
  {
    memset(ptr, 0, sizeof(memcached_st));
  }
  result_ptr= memcached_result_create(ptr, &ptr->result);
  WATCHPOINT_ASSERT(result_ptr);
  ptr->poll_timeout= MEMCACHED_DEFAULT_TIMEOUT;
  ptr->connect_timeout= MEMCACHED_DEFAULT_TIMEOUT;
  ptr->retry_timeout= 0;
  ptr->distribution= MEMCACHED_DISTRIBUTION_MODULA;

  /* TODO, Document why we picked these defaults */
  ptr->io_msg_watermark= 500;
  ptr->io_bytes_watermark= 65 * 1024;

  return ptr;
}
void memcached_array_free(memcached_array_st *array)
{
  if (array)
  {
    WATCHPOINT_ASSERT(array->root);
    libmemcached_free(array->root, array);
  }
}
示例#12
0
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;
}
示例#13
0
static uint32_t dispatch_host(const memcached_st *ptr, uint32_t hash)
{
  switch (ptr->distribution)
  {
  case MEMCACHED_DISTRIBUTION_CONSISTENT:
  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
    {
      uint32_t num= ptr->continuum_points_counter;
      WATCHPOINT_ASSERT(ptr->continuum);

      hash= hash;
      memcached_continuum_item_st *begin, *end, *left, *right, *middle;
      begin= left= ptr->continuum;
      end= right= ptr->continuum + num;

      while (left < right)
      {
        middle= left + (right - left) / 2;
        if (middle->value < hash)
          left= middle + 1;
        else
          right= middle;
      }
      if (right == end)
        right= begin;
      return right->index;
    }
  case MEMCACHED_DISTRIBUTION_MODULA:
    return hash % memcached_server_count(ptr);
  case MEMCACHED_DISTRIBUTION_RANDOM:
    return (uint32_t) random() % memcached_server_count(ptr);
  case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
  default:
    WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
    return hash % memcached_server_count(ptr);
  }
  /* NOTREACHED */
}
static int continuum_item_cmp(const void *t1, const void *t2)
{
  memcached_continuum_item_st *ct1= (memcached_continuum_item_st *)t1;
  memcached_continuum_item_st *ct2= (memcached_continuum_item_st *)t2;

  /* Why 153? Hmmm... */
  WATCHPOINT_ASSERT(ct1->value != 153);
  if (ct1->value == ct2->value)
    return 0;
  else if (ct1->value > ct2->value)
    return 1;
  else
    return -1;
}
示例#15
0
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;
}
示例#16
0
void memcached_array_free(memcached_array_st *array)
{
  if (! array)
    return;

  WATCHPOINT_ASSERT(array->root);
  if (array && array->root)
  {
    libmemcached_free(array->root, array);
  }
  else if (array)
  {
    free(array);
  }
}
示例#17
0
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);
}
示例#18
0
ssize_t memcached_io_write(memcached_server_st *ptr,
                           const void *buffer, size_t length, char with_flush)
{
  size_t original_length;
  const char* buffer_ptr;

  original_length= length;
  buffer_ptr= buffer;

  while (length)
  {
    char *write_ptr;
    size_t should_write;

    should_write= MEMCACHED_MAX_BUFFER - ptr->write_buffer_offset;
    write_ptr= ptr->write_buffer + ptr->write_buffer_offset;

    should_write= (should_write < length) ? should_write : length;

    memcpy(write_ptr, buffer_ptr, should_write);
    ptr->write_buffer_offset+= should_write;
    buffer_ptr+= should_write;
    length-= should_write;

    if (ptr->write_buffer_offset == MEMCACHED_MAX_BUFFER)
    {
      memcached_return rc;
      ssize_t sent_length;

      sent_length= io_flush(ptr, &rc);
      if (sent_length == -1)
        return -1;

      WATCHPOINT_ASSERT(sent_length == MEMCACHED_MAX_BUFFER);
    }
  }

  if (with_flush)
  {
    memcached_return rc;
    if (io_flush(ptr, &rc) == -1)
      return -1;
  }

  return original_length;
}
示例#19
0
void memcached_result_free(memcached_result_st *ptr)
{
  if (ptr == NULL)
    return;

  memcached_string_free(&ptr->value);

  if (memcached_is_allocated(ptr))
  {
    WATCHPOINT_ASSERT(ptr->root); // Without a root, that means that result was not properly initialized.
    libmemcached_free(ptr->root, ptr);
  }
  else
  {
    ptr->options.is_initialized= false;
  }
}
示例#20
0
memcached_return run_distribution(memcached_st *ptr)
{
  switch (ptr->distribution) 
  {
  case MEMCACHED_DISTRIBUTION_CONSISTENT:
  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
    return update_continuum(ptr);
  case MEMCACHED_DISTRIBUTION_MODULA:
    if (ptr->flags & MEM_USE_SORT_HOSTS)
      sort_hosts(ptr);
    break;
  case MEMCACHED_DISTRIBUTION_RANDOM:
    break;
  default:
    WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
  }

  return MEMCACHED_SUCCESS;
}
示例#21
0
/*
  clone is the destination, while ptr is the structure to clone.
  If ptr is NULL the call is the same as if a gearman_create() was
  called.
*/
gearman_connection_st *gearman_connection_clone(gearman_connection_st *clone, gearman_connection_st *ptr)
{
  gearman_connection_st *new_clone;

  if (ptr == NULL)
    return gearman_connection_create(clone);

  if (ptr->is_allocated)
  {
    WATCHPOINT_ASSERT(0);
    return NULL;
  }
  
  new_clone= gearman_connection_create(clone);
  
  if (new_clone == NULL)
    return NULL;

  return new_clone;
}
示例#22
0
memcached_return_t run_distribution(memcached_st *ptr)
{
  if (ptr->flags.use_sort_hosts)
    sort_hosts(ptr);

  switch (ptr->distribution)
  {
  case MEMCACHED_DISTRIBUTION_CONSISTENT:
  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
    return update_continuum(ptr);
  case MEMCACHED_DISTRIBUTION_MODULA:
    break;
  case MEMCACHED_DISTRIBUTION_RANDOM:
    srandom((uint32_t) time(NULL));
    break;
  case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
  default:
    WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
  }

  return MEMCACHED_SUCCESS;
}
示例#23
0
memcached_result_st *memcached_result_create(memcached_st *memc,
                                             memcached_result_st *ptr)
{
  /* Saving malloc calls :) */
  if (ptr)
    memset(ptr, 0, sizeof(memcached_result_st));
  else
  {
    if (memc->call_malloc)
      ptr= (memcached_result_st *)memc->call_malloc(memc, sizeof(memcached_result_st));
    else
      ptr= (memcached_result_st *)calloc(1, sizeof(memcached_result_st));

    if (ptr == NULL)
      return NULL;
    ptr->is_allocated= true;
  }

  ptr->root= memc;
  memcached_string_create(memc, &ptr->value, 0);
  WATCHPOINT_ASSERT(ptr->value.string == NULL);

  return ptr;
}
memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list)
{
  unsigned int x;
  uint16_t count;
  memcached_server_st *new_host_list;

  if (!list)
    return MEMCACHED_SUCCESS;

  count= list[0].count;
  new_host_list= ptr->call_realloc(ptr, ptr->hosts, 
                                   sizeof(memcached_server_st) * (count + ptr->number_of_hosts));

  if (!new_host_list)
    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;

  ptr->hosts= new_host_list;

  for (x= 0; x < count; x++)
  {
    if ((ptr->flags & MEM_USE_UDP && list[x].type != MEMCACHED_CONNECTION_UDP)
            || ((list[x].type == MEMCACHED_CONNECTION_UDP)
            && ! (ptr->flags & MEM_USE_UDP)) )
      return MEMCACHED_INVALID_HOST_PROTOCOL;

    WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
    memcached_server_create(ptr, &ptr->hosts[ptr->number_of_hosts]);
    /* TODO check return type */
    (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname, 
                                       list[x].port, list[x].weight, list[x].type);
    ptr->number_of_hosts++;
  }
  ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;

  return run_distribution(ptr);
}
memcached_return update_continuum(memcached_st *ptr)
{
  uint32_t host_index;
  uint32_t continuum_index= 0;
  uint32_t value;
  memcached_server_st *list;
  uint32_t pointer_index;
  uint32_t pointer_counter= 0;
  uint32_t pointer_per_server= MEMCACHED_POINTS_PER_SERVER;
  uint32_t pointer_per_hash= 1;
  uint64_t total_weight= 0;
  uint64_t is_ketama_weighted= 0;
  uint64_t is_auto_ejecting= 0;
  uint32_t points_per_server= 0;
  uint32_t live_servers= 0;
  struct timeval now;

  if (gettimeofday(&now, NULL) != 0)
  {
    ptr->cached_errno = errno;
    return MEMCACHED_ERRNO;
  }

  list = ptr->hosts;

  /* count live servers (those without a retry delay set) */
  is_auto_ejecting= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS);
  if (is_auto_ejecting)
  {
    live_servers= 0;
    ptr->next_distribution_rebuild= 0;
    for (host_index= 0; host_index < ptr->number_of_hosts; ++host_index)
    {
      if (list[host_index].next_retry <= now.tv_sec)
        live_servers++;
      else
      {
        if (ptr->next_distribution_rebuild == 0 || list[host_index].next_retry < ptr->next_distribution_rebuild)
          ptr->next_distribution_rebuild= list[host_index].next_retry;
      }
    }
  }
  else
    live_servers= ptr->number_of_hosts;

  is_ketama_weighted= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED);
  points_per_server= (uint32_t) (is_ketama_weighted ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER);

  if (live_servers == 0)
    return MEMCACHED_SUCCESS;

  if (live_servers > ptr->continuum_count)
  {
    memcached_continuum_item_st *new_ptr;

    new_ptr= ptr->call_realloc(ptr, ptr->continuum, 
                               sizeof(memcached_continuum_item_st) * (live_servers + MEMCACHED_CONTINUUM_ADDITION) * points_per_server);

    if (new_ptr == 0)
      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;

    ptr->continuum= new_ptr;
    ptr->continuum_count= live_servers + MEMCACHED_CONTINUUM_ADDITION;
  }

  if (is_ketama_weighted) 
  {
    for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index) 
    {
      if (list[host_index].weight == 0)
      {
        list[host_index].weight = 1;
      }
      if (!is_auto_ejecting || list[host_index].next_retry <= now.tv_sec)
        total_weight += list[host_index].weight;
    }
  }

  for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index) 
  {
    if (is_auto_ejecting && list[host_index].next_retry > now.tv_sec)
      continue;

    if (is_ketama_weighted) 
    {
        float pct = (float)list[host_index].weight / (float)total_weight;
        pointer_per_server= (uint32_t) ((floorf((float) (pct * MEMCACHED_POINTS_PER_SERVER_KETAMA / 4 * (float)live_servers + 0.0000000001))) * 4);
        pointer_per_hash= 4;
#ifdef DEBUG
        printf("ketama_weighted:%s|%d|%llu|%u\n", 
               list[host_index].hostname, 
               list[host_index].port,  
               (unsigned long long)list[host_index].weight, 
               pointer_per_server);
#endif
    }
    for (pointer_index= 1;
         pointer_index <= pointer_per_server / pointer_per_hash;
         ++pointer_index) 
    {
      char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= "";
      size_t sort_host_length;

      if (list[host_index].port == MEMCACHED_DEFAULT_PORT)
      {
        sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
                                            "%s-%d",
                                            list[host_index].hostname,
                                            pointer_index - 1);

      }
      else
      {
        sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
                                            "%s:%d-%d", 
                                            list[host_index].hostname,
                                            list[host_index].port, pointer_index - 1);
      }
      WATCHPOINT_ASSERT(sort_host_length);

      if (is_ketama_weighted)
      {
        unsigned int i;
        for (i = 0; i < pointer_per_hash; i++)
        {
          value= ketama_server_hash(sort_host, (uint32_t) sort_host_length, (int) i);
          ptr->continuum[continuum_index].index= host_index;
          ptr->continuum[continuum_index++].value= value;
        }
      }
      else
      {
        value= memcached_generate_hash_value(sort_host, sort_host_length, ptr->hash_continuum);
        ptr->continuum[continuum_index].index= host_index;
        ptr->continuum[continuum_index++].value= value;
      }
    }
    pointer_counter+= pointer_per_server;
  }

  WATCHPOINT_ASSERT(ptr);
  WATCHPOINT_ASSERT(ptr->continuum);
  WATCHPOINT_ASSERT(ptr->number_of_hosts * MEMCACHED_POINTS_PER_SERVER <= MEMCACHED_CONTINUUM_SIZE);
  ptr->continuum_points_counter= pointer_counter;
  qsort(ptr->continuum, ptr->continuum_points_counter, sizeof(memcached_continuum_item_st), continuum_item_cmp);

#ifdef DEBUG
  for (pointer_index= 0; ptr->number_of_hosts && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++) 
  {
    WATCHPOINT_ASSERT(ptr->continuum[pointer_index].value <= ptr->continuum[pointer_index + 1].value);
  }
#endif

  return MEMCACHED_SUCCESS;
}
示例#26
0
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;
}
示例#27
0
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 */
}
示例#28
0
void memcached_quit_server(memcached_server_st *ptr, bool io_death)
{
  if (ptr->fd != -1)
  {
    if (io_death == false && ptr->type != MEMCACHED_CONNECTION_UDP && ptr->options.is_shutting_down == false)
    {
      memcached_return_t rc;
      char buffer[MEMCACHED_MAX_BUFFER];

      ptr->options.is_shutting_down= true;

      if (ptr->root->flags.binary_protocol)
      {
        protocol_binary_request_quit request;
        memset(&request, 0, sizeof(request));
        request.message.header.request.magic = PROTOCOL_BINARY_REQ;
        request.message.header.request.opcode = PROTOCOL_BINARY_CMD_QUIT;
        request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
        rc= memcached_do(ptr, request.bytes, sizeof(request.bytes), true);
      }
      else
      {
        rc= memcached_do(ptr, "quit\r\n", strlen("quit\r\n"), true);
      }

      WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_FETCH_NOTFINISHED);
      (void)rc; /* Shut up ICC */

      /* read until socket is closed, or there is an error
       * closing the socket before all data is read
       * results in server throwing away all data which is
       * not read
       *
       * In .40 we began to only do this if we had been doing buffered
       * requests of had replication enabled.
       */
      if (ptr->root->flags.buffer_requests || ptr->root->number_of_replicas)
      {
        ssize_t nread;
        while (memcached_io_read(ptr, buffer, sizeof(buffer)/sizeof(*buffer),
                                 &nread) == MEMCACHED_SUCCESS);
      }


      /*
       * memcached_io_read may call memcached_quit_server with io_death if
       * it encounters problems, but we don't care about those occurences.
       * The intention of that loop is to drain the data sent from the
       * server to ensure that the server processed all of the data we
       * sent to the server.
       */
      ptr->server_failure_counter= 0;
    }
    memcached_io_close(ptr);
  }

  ptr->fd= -1;
  ptr->io_bytes_sent= 0;
  ptr->write_buffer_offset= (size_t) ((ptr->type == MEMCACHED_CONNECTION_UDP) ? UDP_DATAGRAM_HEADER_LENGTH : 0);
  ptr->read_buffer_length= 0;
  ptr->read_ptr= ptr->read_buffer;
  ptr->options.is_shutting_down= false;
  memcached_server_response_reset(ptr);

  /* We reset the version so that if we end up talking to a different server */
  /* we don't have stale server version information. */
  ptr->major_version= ptr->minor_version= ptr->micro_version= UINT8_MAX;

  if (io_death)
  {
    ptr->server_failure_counter++;
    set_last_disconnected_host(ptr);
  }
}
示例#29
0
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 value_fetch(memcached_server_st *ptr,
                             char *buffer,
                             memcached_result_st *result)
{
  memcached_return rc= MEMCACHED_SUCCESS;
  char *string_ptr;
  char *end_ptr;
  char *next_ptr;
  size_t value_length;
  size_t read_length;
  size_t to_read;
  char *value_ptr;

  WATCHPOINT_ASSERT(ptr->root);
  end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;

  memcached_result_reset(result);

  string_ptr= buffer;
  string_ptr+= 6; /* "VALUE " */


  /* We load the key */
  {
    char *key;
    size_t prefix_length;

    key= result->key;
    result->key_length= 0;

    for (prefix_length= ptr->root->prefix_key_length; !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
    {
      if (prefix_length == 0)
      {
        *key= *string_ptr;
        key++;
        result->key_length++;
      }
      else
        prefix_length--;
    }
    result->key[result->key_length]= 0;
  }

  if (end_ptr == string_ptr)
    goto read_error;

  /* Flags fetch move past space */
  string_ptr++;
  if (end_ptr == string_ptr)
    goto read_error;
  for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
  result->flags= strtoul(next_ptr, &string_ptr, 10);

  if (end_ptr == string_ptr)
    goto read_error;

  /* Length fetch move past space*/
  string_ptr++;
  if (end_ptr == string_ptr)
    goto read_error;

  for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
  value_length= (size_t)strtoull(next_ptr, &string_ptr, 10);

  if (end_ptr == string_ptr)
    goto read_error;

  /* Skip spaces */
  if (*string_ptr == '\r')
  {
    /* Skip past the \r\n */
    string_ptr+= 2;
  }
  else
  {
    string_ptr++;
    for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
    result->cas= strtoull(next_ptr, &string_ptr, 10);
  }

  if (end_ptr < string_ptr)
    goto read_error;

  /* We add two bytes so that we can walk the \r\n */
  rc= memcached_string_check(&result->value, value_length+2);
  if (rc != MEMCACHED_SUCCESS)
  {
    value_length= 0;
    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
  }

  value_ptr= memcached_string_value(&result->value);
  read_length= 0;
  /* 
    We read the \r\n into the string since not doing so is more 
    cycles then the waster of memory to do so.

    We are null terminating through, which will most likely make
    some people lazy about using the return length.
  */
  to_read= (value_length) + 2;
  read_length= memcached_io_read(ptr, value_ptr, to_read);
  if (read_length != (size_t)(value_length + 2))
  {
    goto read_error;
  }

/* This next bit blows the API, but this is internal....*/
  {
    char *char_ptr;
    char_ptr= memcached_string_value(&result->value);;
    char_ptr[value_length]= 0;
    char_ptr[value_length + 1]= 0;
    memcached_string_set_length(&result->value, value_length);
  }

  return MEMCACHED_SUCCESS;

read_error:
  memcached_io_reset(ptr);

  return MEMCACHED_PARTIAL_READ;
}