Exemple #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);
}
Exemple #2
0
static memcached_return_t memcached_flush_textual(memcached_st *ptr, 
                                                  time_t expiration)
{
  unsigned int x;
  size_t send_length;
  memcached_return_t rc;
  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];

  unlikely (memcached_server_count(ptr) == 0)
    return MEMCACHED_NO_SERVERS;

  for (x= 0; x < memcached_server_count(ptr); x++)
  {
    bool no_reply= ptr->flags.no_reply;
    memcached_server_write_instance_st instance=
      memcached_server_instance_fetch(ptr, x);

    if (expiration)
      send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
                                     "flush_all %llu%s\r\n",
                                     (unsigned long long)expiration, no_reply ? " noreply" : "");
    else
      send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
                                     "flush_all%s\r\n", no_reply ? " noreply" : "");

    rc= memcached_do(instance, buffer, send_length, true);

    if (rc == MEMCACHED_SUCCESS && !no_reply)
      (void)memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
  }

  return MEMCACHED_SUCCESS;
}
Exemple #3
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);
}
Exemple #4
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);
  }
}
Exemple #5
0
void memcached_quit(memcached_st *ptr)
{
  uint32_t x;

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

  if (memcached_server_count(ptr))
  {
    for (x= 0; x < memcached_server_count(ptr); x++)
    {
      memcached_server_write_instance_st instance=
        memcached_server_instance_fetch(ptr, x);

      memcached_quit_server(instance, false);
    }
  }
}
Exemple #6
0
static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
{
  memcached_return_t rc= MEMCACHED_SUCCESS;
  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
  size_t send_length;
  uint32_t server_key;
  uint32_t x;

  unlikely (memcached_server_count(ptr) == 0)
    return MEMCACHED_NO_SERVERS;

  for (server_key= 0; server_key < memcached_server_count(ptr); server_key++)
  {
    memcached_server_instance_st *instance;
    instance= memcached_server_instance_fetch(ptr, server_key);

    /* 256 I BELIEVE is the upper limit of slabs */
    for (x= 0; x < 256; x++)
    {
      send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
                                     "stats cachedump %u 0 0\r\n", x);

      rc= memcached_do(instance, buffer, send_length, true);

      unlikely (rc != MEMCACHED_SUCCESS)
        goto error;

      while (1)
      {
        uint32_t callback_counter;
        rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);

        if (rc == MEMCACHED_ITEM)
        {
          char *string_ptr, *end_ptr;
          char *key;

          string_ptr= buffer;
          string_ptr+= 5; /* Move past ITEM */
          for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++);
          key= string_ptr;
          key[(size_t)(end_ptr-string_ptr)]= 0;
          for (callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++)
          {
            rc= (*callback[callback_counter])(ptr, key, (size_t)(end_ptr-string_ptr), context);
            if (rc != MEMCACHED_SUCCESS)
              break;
          }
        }
        else if (rc == MEMCACHED_END)
          break;
        else if (rc == MEMCACHED_SERVER_ERROR || rc == MEMCACHED_CLIENT_ERROR)
        {
          /* If we try to request stats cachedump for a slab class that is too big
           * the server will return an incorrect error message:
           * "MEMCACHED_SERVER_ERROR failed to allocate memory"
           * This isn't really a fatal error, so let's just skip it. I want to
           * fix the return value from the memcached server to a CLIENT_ERROR,
           * so let's add support for that as well right now.
           */
          rc= MEMCACHED_END;
          break;
        }
        else
          goto error;
      }
    }
  }

error:
  if (rc == MEMCACHED_END)
    return MEMCACHED_SUCCESS;
  else
    return rc;
}
Exemple #7
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;
}
Exemple #8
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;
}
Exemple #9
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 */
}
Exemple #10
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,
                                                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" }
      };