Exemplo n.º 1
0
static memcached_return_t server_add(memcached_st *ptr, const char *hostname,
                                     in_port_t port,
                                     uint32_t weight,
                                     memcached_connection_t type)
{
  memcached_server_st *new_host_list;
  memcached_server_write_instance_st instance;

  if ( (ptr->flags.use_udp && type != MEMCACHED_CONNECTION_UDP)
      || ( (type == MEMCACHED_CONNECTION_UDP) && (! ptr->flags.use_udp) ) )
    return MEMCACHED_INVALID_HOST_PROTOCOL;

  new_host_list= libmemcached_realloc(ptr, memcached_server_list(ptr),
                                      sizeof(memcached_server_st) * (ptr->number_of_hosts + 1));

  if (new_host_list == NULL)
    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;

  memcached_server_list_set(ptr, new_host_list);

  /* TODO: Check return type */
  instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr));
  (void)memcached_server_create_with(ptr, instance, hostname, port, weight, type);
  ptr->number_of_hosts++;

  instance= memcached_server_instance_fetch(ptr, 0);
  memcached_servers_set_count(instance, memcached_server_count(ptr));

  return run_distribution(ptr);
}
Exemplo n.º 2
0
void memcached_servers_reset(memcached_st *ptr)
{
  server_list_free(ptr, memcached_server_list(ptr));

  memcached_server_list_set(ptr, NULL);
  ptr->number_of_hosts= 0;
  ptr->last_disconnected_server= NULL;
  ptr->server_failure_limit= 0;
}
Exemplo n.º 3
0
static void sort_hosts(memcached_st *ptr)
{
  if (memcached_server_count(ptr))
  {
    memcached_server_write_instance_st instance;

    qsort(memcached_server_list(ptr), memcached_server_count(ptr), sizeof(memcached_server_st), compare_servers);
    instance= memcached_server_instance_fetch(ptr, 0);
    instance->number_of_hosts= memcached_server_count(ptr);
  }
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
0
void memcached_free(memcached_st *ptr)
{
  /* If we have anything open, lets close it now */
  memcached_quit(ptr);
  server_list_free(ptr, memcached_server_list(ptr));
  memcached_result_free(&ptr->result);

  if (ptr->on_cleanup)
    ptr->on_cleanup(ptr);

  if (ptr->continuum)
    libmemcached_free(ptr, ptr->continuum);

  if (memcached_is_allocated(ptr))
  {
    libmemcached_free(ptr, ptr);
  }
}
Exemplo n.º 6
0
static test_return_t post_udp_op_check(memcached_st *memc, uint16_t *expected_req_ids)
{
    (void)memc;
    (void)expected_req_ids;
#if 0
    memcached_server_st *cur_server = memcached_server_list(memc);
    uint16_t *cur_req_ids = get_udp_request_ids(memc);

    for (size_t x= 0; x < memcached_server_count(memc); x++)
    {
        test_true(cur_server[x].cursor_active == 0);
        test_true(cur_req_ids[x] == expected_req_ids[x]);
    }
    free(expected_req_ids);
    free(cur_req_ids);

#endif
    return TEST_SUCCESS;
}
Exemplo n.º 7
0
/*
** There is a little bit of a hack here, instead of removing
** the servers, I just set num host to 0 and them add then new udp servers
**/
static test_return_t init_udp(memcached_st *memc)
{
    memcached_version(memc);
#if 0
    memcached_server_instance_st instance=
        memcached_server_instance_by_position(memc, 0);

    /* For the time being, only support udp test for >= 1.2.6 && < 1.3 */
    if (instance->major_version != 1 || instance->minor_version != 2
            || instance->micro_version < 6)
        return TEST_SKIPPED;

    uint32_t num_hosts= memcached_server_count(memc);
    memcached_server_st servers[num_hosts];
    memcpy(servers, memcached_server_list(memc), sizeof(memcached_server_st) * num_hosts);
    for (uint32_t x= 0; x < num_hosts; x++)
    {
        memcached_server_instance_st set_instance=
            memcached_server_instance_by_position(memc, x);

        memcached_server_free(((memcached_server_write_instance_st)set_instance));
    }

    memc->number_of_hosts= 0;
    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1);
    for (uint32_t x= 0; x < num_hosts; x++)
    {
        memcached_server_instance_st set_instance=
            memcached_server_instance_by_position(memc, x);

        test_true(memcached_server_add_udp(memc, servers[x].hostname, servers[x].port) == MEMCACHED_SUCCESS);
        test_true(set_instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH);
    }
#endif

    return TEST_SKIPPED;
}
Exemplo n.º 8
0
int main(int argc, char *argv[])
{
  memcached_return rc;
  memcached_st *memc;
  memcached_stat_st *stat;
  memcached_server_st *servers;
  memcached_server_st *server_list;
  memcached_analysis_st *report;

  options_parse(argc, argv);

  if (!opt_servers)
  {
    char *temp;

    if ((temp= getenv("MEMCACHED_SERVERS")))
      opt_servers= strdup(temp);
    else
    {
      fprintf(stderr, "No Servers provided\n\n");
      help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, 0);
      exit(1);
    }
  }

  memc= memcached_create(NULL);

  servers= memcached_servers_parse(opt_servers);
  memcached_server_push(memc, servers);
  memcached_server_list_free(servers);

  stat= memcached_stat(memc, NULL, &rc);

  if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_SOME_ERRORS)
  {
    printf("Failure to communicate with servers (%s)\n",
           memcached_strerror(memc, rc));
    exit(1);
  }

  server_list= memcached_server_list(memc);

  if (opt_analyze)
  {
    report= memcached_analyze(memc, stat, &rc);
    if (rc != MEMCACHED_SUCCESS || report == NULL)
    {
      printf("Failure to analyze servers (%s)\n",
             memcached_strerror(memc, rc));
      exit(1);
    }
    print_analysis_report(memc, report, server_list);
    free(report);
  }
  else
    print_server_listing(memc, stat, server_list);

  free(stat);
  free(opt_servers);

  memcached_free(memc);

  return 0;
}
Exemplo n.º 9
0
static memcached_return_t 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 = memcached_server_list(ptr);

  /* count live servers (those without a retry delay set) */
  is_auto_ejecting= _is_auto_eject_host(ptr);
  if (is_auto_ejecting)
  {
    live_servers= 0;
    ptr->next_distribution_rebuild= 0;
    for (host_index= 0; host_index < memcached_server_count(ptr); ++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= memcached_server_count(ptr);
  }

  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= libmemcached_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 < memcached_server_count(ptr); ++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 < memcached_server_count(ptr); ++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
    }


    if (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY)
    {
      for (pointer_index= 0;
           pointer_index < pointer_per_server / pointer_per_hash;
           pointer_index++)
      {
        char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= "";
        size_t sort_host_length;

        // Spymemcached ketema key format is: hostname/ip:port-index
        // If hostname is not available then: /ip:port-index
        sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
                                            "/%s:%u-%u",
                                            list[host_index].hostname,
                                            (uint32_t)list[host_index].port,
                                            pointer_index);
#ifdef DEBUG
        printf("update_continuum: key is %s\n", sort_host);
#endif

        WATCHPOINT_ASSERT(sort_host_length);

        if (is_ketama_weighted)
        {
          for (uint32_t x= 0; x < pointer_per_hash; x++)
          {
             value= ketama_server_hash(sort_host, sort_host_length, x);
             ptr->continuum[continuum_index].index= host_index;
             ptr->continuum[continuum_index++].value= value;
          }
        }
        else
        {
          value= hashkit_digest(&ptr->distribution_hashkit, sort_host, sort_host_length);
          ptr->continuum[continuum_index].index= host_index;
          ptr->continuum[continuum_index++].value= value;
        }
      }
    }
    else
    {
      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-%u",
                                              list[host_index].hostname,
                                              pointer_index - 1);
        }
        else
        {
          sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
                                              "%s:%u-%u",
                                              list[host_index].hostname,
                                              (uint32_t)list[host_index].port,
                                              pointer_index - 1);
        }

        WATCHPOINT_ASSERT(sort_host_length);

        if (is_ketama_weighted)
        {
          for (uint32_t x = 0; x < pointer_per_hash; x++)
          {
             value= ketama_server_hash(sort_host, sort_host_length, x);
             ptr->continuum[continuum_index].index= host_index;
             ptr->continuum[continuum_index++].value= value;
          }
        }
        else
        {
          value= hashkit_digest(&ptr->distribution_hashkit, sort_host, sort_host_length);
          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(memcached_server_count(ptr) * 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; memcached_server_count(ptr) && 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;
}
Exemplo n.º 10
0
/*
  clone is the destination, while source is the structure to clone.
  If source is NULL the call is the same as if a memcached_create() was
  called.
*/
memcached_st *memcached_clone(memcached_st *clone, const memcached_st *source)
{
  memcached_return_t rc= MEMCACHED_SUCCESS;
  memcached_st *new_clone;

  if (source == NULL)
    return memcached_create(clone);

  if (clone && memcached_is_allocated(clone))
  {
    return NULL;
  }

  new_clone= memcached_create(clone);

  if (new_clone == NULL)
    return NULL;

  new_clone->flags= source->flags;
  new_clone->send_size= source->send_size;
  new_clone->recv_size= source->recv_size;
  new_clone->poll_timeout= source->poll_timeout;
  new_clone->connect_timeout= source->connect_timeout;
  new_clone->retry_timeout= source->retry_timeout;
  new_clone->distribution= source->distribution;

  hashkit_st *hash_ptr;

  hash_ptr= hashkit_clone(&new_clone->hashkit, &source->hashkit);
  if (! hash_ptr)
  {
    memcached_free(new_clone);
    return NULL;
  }

  hash_ptr= hashkit_clone(&new_clone->distribution_hashkit, &source->distribution_hashkit);
  if (! hash_ptr)
  {
    memcached_free(new_clone);
    return NULL;
  }

  new_clone->user_data= source->user_data;

  new_clone->snd_timeout= source->snd_timeout;
  new_clone->rcv_timeout= source->rcv_timeout;

  new_clone->on_clone= source->on_clone;
  new_clone->on_cleanup= source->on_cleanup;

  new_clone->allocators= source->allocators;

  new_clone->get_key_failure= source->get_key_failure;
  new_clone->delete_trigger= source->delete_trigger;
  new_clone->server_failure_limit= source->server_failure_limit;
  new_clone->io_msg_watermark= source->io_msg_watermark;
  new_clone->io_bytes_watermark= source->io_bytes_watermark;
  new_clone->io_key_prefetch= source->io_key_prefetch;
  new_clone->number_of_replicas= source->number_of_replicas;

  if (memcached_server_list(source))
    rc= memcached_server_push(new_clone, memcached_server_list(source));

  if (rc != MEMCACHED_SUCCESS)
  {
    memcached_free(new_clone);

    return NULL;
  }


  if (source->prefix_key_length)
  {
    strcpy(new_clone->prefix_key, source->prefix_key);
    new_clone->prefix_key_length= source->prefix_key_length;
  }

  rc= run_distribution(new_clone);

  if (rc != MEMCACHED_SUCCESS)
  {
    memcached_free(new_clone);

    return NULL;
  }

  if (source->on_clone)
    source->on_clone(new_clone, source);

  return new_clone;
}