Beispiel #1
0
int main(int argc, char *argv[])
{
  memcached_st *memc;
  char *string;
  size_t string_length;
  uint32_t flags;
  memcached_return_t rc;
  memcached_server_st *servers;

  int return_code= 0;

  options_parse(argc, argv);
  initialize_sockets();

  if (!opt_servers)
  {
    char *temp;

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

  memc= memcached_create(NULL);
  process_hash_option(memc, opt_hash);

  servers= memcached_servers_parse(opt_servers);

  memcached_server_push(memc, servers);
  memcached_server_list_free(servers);
  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
                         (uint64_t)opt_binary);

  if (!initialize_sasl(memc, opt_username, opt_passwd))
  {
    memcached_free(memc);
    return EXIT_FAILURE;
  }

  while (optind < argc)
  {
    string= memcached_get(memc, argv[optind], strlen(argv[optind]),
                          &string_length, &flags, &rc);
    if (rc == MEMCACHED_SUCCESS)
    {
      if (opt_displayflag)
      {
        if (opt_verbose)
          printf("key: %s\nflags: ", argv[optind]);
        printf("%x\n", flags);
      }
      else
      {
        if (opt_verbose)
        {
          printf("key: %s\nflags: %x\nlength: %zu\nvalue: ",
                 argv[optind], flags, string_length);
        }

        if (opt_file)
        {
          FILE *fp;
          size_t written;

          fp= fopen(opt_file, "w");
          if (!fp)
          {
            perror("fopen");
            return_code= -1;
            break;
          }

          written= fwrite(string, 1, string_length, fp);
          if (written != string_length) 
          {
            fprintf(stderr, "error writing file (written %zu, should be %zu)\n", written, string_length);
            return_code= -1;
            break;
          }

          if (fclose(fp))
          {
            fprintf(stderr, "error closing file\n");
            return_code= -1;
            break;
          }
        }
        else
        {
            printf("%.*s\n", (int)string_length, string);
        }
        free(string);
      }
    }
    else if (rc != MEMCACHED_NOTFOUND)
    {
      fprintf(stderr, "memcat: %s: memcache error %s",
              argv[optind], memcached_strerror(memc, rc));
      if (memcached_last_error_errno(memc))
      {
	fprintf(stderr, " system error %s", strerror(memcached_last_error_errno(memc)));
      }
      fprintf(stderr, "\n");

      return_code= -1;
      break;
    }
    else // Unknown Issue
    {
      fprintf(stderr, "memcat: %s not found\n", argv[optind]);
      return_code= -1;
    }
    optind++;
  }

  memcached_free(memc);

  if (opt_servers)
    free(opt_servers);
  if (opt_hash)
    free(opt_hash);

  shutdown_sasl();

  return return_code;
}
 /**
  * Return an error string for the given return structure.
  *
  * @param[in] rc a memcached_return structure
  * @return error string corresponding to given return code in the library.
  */
 const std::string getError(memcached_return rc) const
 {
   /* first parameter to strerror is unused */
   return memcached_strerror(NULL, rc);
 }
Beispiel #3
0
/// Retrieve the data for a given namespace and key.
Store::Status MemcachedStore::get_data(const std::string& table,
                                       const std::string& key,
                                       std::string& data,
                                       uint64_t& cas,
                                       SAS::TrailId trail)
{
  Store::Status status = Store::Status::OK;


  // Construct the fully qualified key.
  std::string fqkey = table + "\\\\" + key;
  const char* key_ptr = fqkey.data();
  const size_t key_len = fqkey.length();

  const std::vector<memcached_st*>& replicas = get_replicas(fqkey, Op::READ);

  if (trail != 0)
  {
    SAS::Event start(trail, SASEvent::MEMCACHED_GET_START, 0);
    start.add_var_param(fqkey);
    SAS::report_event(start);
  }

  LOG_DEBUG("%d read replicas for key %s", replicas.size(), fqkey.c_str());

  // Read from all replicas until we get a positive result.
  memcached_return_t rc = MEMCACHED_ERROR;
  bool active_not_found = false;
  size_t failed_replicas = 0;
  size_t ii;
  // If we only have one replica, we should try it twice -
  // libmemcached won't notice a dropped TCP connection until it tries
  // to make a request on it, and will fail the request then
  // reconnect, so the second attempt could still work.
  size_t attempts = (replicas.size() == 1) ? 2 : replicas.size();

  for (ii = 0; ii < attempts; ++ii)
  {
    size_t replica_idx;
    if ((replicas.size() == 1) && (ii == 1))
    {
      if (rc != MEMCACHED_CONNECTION_FAILURE)
      {
        // This is a legitimate error, not a server failure, so we
        // shouldn't retry.
        break;
      }
      replica_idx = 0;
      LOG_WARNING("Failed to read from sole memcached replica: retrying once");
    }
    else
    {
      replica_idx = ii;
    }
    // We must use memcached_mget because memcached_get does not retrieve CAS
    // values.
    LOG_DEBUG("Attempt to read from replica %d (connection %p)", replica_idx, replicas[replica_idx]);
    rc = memcached_mget(replicas[replica_idx], &key_ptr, &key_len, 1);

    if (memcached_success(rc))
    {
      // memcached_mget command was successful, so retrieve the result.
      LOG_DEBUG("Fetch result");
      memcached_result_st result;
      memcached_result_create(replicas[replica_idx], &result);
      memcached_fetch_result(replicas[replica_idx], &result, &rc);

      if (memcached_success(rc))
      {
        // Found a record, so exit the read loop.
        LOG_DEBUG("Found record on replica %d", replica_idx);
        data.assign(memcached_result_value(&result), memcached_result_length(&result));
        cas = (active_not_found) ? 0 : memcached_result_cas(&result);

        // std::string::assign copies its arguments when used with a
        // char*, so this is safe.
        memcached_result_free(&result);
        break;
      }
      else
      {
        // Free the result and continue the read loop.
        memcached_result_free(&result);
      }
    }


    if (rc == MEMCACHED_NOTFOUND)
    {
      // Failed to find a record on an active replica.  Flag this so if we do
      // find data on a later replica we can reset the cas value returned to
      // zero to ensure a subsequent write will succeed.
      LOG_DEBUG("Read for %s on replica %d returned NOTFOUND", fqkey.c_str(), replica_idx);
      active_not_found = true;
    }
    else
    {
      // Error from this node, so consider it inactive.
      LOG_DEBUG("Read for %s on replica %d returned error %d (%s)",
                fqkey.c_str(), replica_idx, rc, memcached_strerror(replicas[replica_idx], rc));
      ++failed_replicas;
    }
  }

  if (memcached_success(rc))
  {
    if (trail != 0)
    {
      SAS::Event got_data(trail, SASEvent::MEMCACHED_GET_SUCCESS, 0);
      got_data.add_var_param(fqkey);
      got_data.add_var_param(data);
      got_data.add_static_param(cas);
      SAS::report_event(got_data);
    }
    // Return the data and CAS value.  The CAS value is either set to the CAS
    // value from the result, or zero if an earlier active replica returned
    // NOT_FOUND.  This ensures that a subsequent set operation will succeed
    // on the earlier active replica.
    LOG_DEBUG("Read %d bytes from table %s key %s, CAS = %ld",
              data.length(), table.c_str(), key.c_str(), cas);

  }
  else if (failed_replicas < replicas.size())
  {
    // At least one replica returned NOT_FOUND.
    if (trail != 0)
    {
      SAS::Event not_found(trail, SASEvent::MEMCACHED_GET_NOT_FOUND, 0);
      not_found.add_var_param(fqkey);
      SAS::report_event(not_found);
    }

    LOG_DEBUG("At least one replica returned not found, so return NOT_FOUND");
    status = Store::Status::NOT_FOUND;
  }
  else
  {
    // All replicas returned an error, so log the error and return the
    // failure.
    if (trail != 0)
    {
      SAS::Event err(trail, SASEvent::MEMCACHED_GET_ERROR, 0);
      err.add_var_param(fqkey);
      SAS::report_event(err);
    }

    LOG_ERROR("Failed to read data for %s from %d replicas",
              fqkey.c_str(), replicas.size());
    status = Store::Status::ERROR;
  }

  return status;
}
Beispiel #4
0
int pr_memcache_kdecr(pr_memcache_t *mcache, module *m, const char *key,
    size_t keysz, uint32_t decr, uint64_t *value) {
  memcached_return res;

  if (mcache == NULL ||
      m == NULL ||
      key == NULL ||
      decr == 0) {
    errno = EINVAL;
    return -1;
  }

  /* Note: libmemcached automatically handles the case where value might be
   * NULL.
   */

  mcache_set_module_namespace(mcache, m);
  res = memcached_decrement(mcache->mc, key, keysz, decr, value);
  mcache_set_module_namespace(mcache, NULL);

  switch (res) {
    case MEMCACHED_SUCCESS:
      return 0;

    case MEMCACHED_ERRNO:
      if (errno != EINPROGRESS) {
        int xerrno = errno;

        pr_trace_msg(trace_channel, 3,
          "error decrementing key (%lu bytes) by %lu: system error: %s",
          (unsigned long) keysz, (unsigned long) decr, strerror(xerrno));

        errno = xerrno;

      } else {
        /* We know that we're not using nonblocking IO; this value usually
         * means that libmemcached could not connect to the configured
         * memcached servers.  So set the value to something more
         * indicative, and fall through.
         */
        res = MEMCACHED_CONNECTION_FAILURE;
      }
      break;

    case MEMCACHED_SERVER_MARKED_DEAD:
    case MEMCACHED_CONNECTION_FAILURE: {
      memcached_server_instance_st server;

      server = memcached_server_get_last_disconnect(mcache->mc);
      if (server != NULL) {
        pr_trace_msg(trace_channel, 3,
          "unable to connect to %s:%d", memcached_server_name(server),
          memcached_server_port(server));
      }

      break;
    }

    default:
      pr_trace_msg(trace_channel, 2,
        "error decrementing key (%lu bytes) by %lu: %s",
        (unsigned long) keysz, (unsigned long) decr,
        memcached_strerror(mcache->mc, res));
      errno = EPERM;
      break;
  }

  return -1;
}
static inline std::ostream& operator<<(std::ostream& output, const enum memcached_return_t &arg)
{
  output << memcached_strerror(NULL, arg);
  return output;
}
//
// Output filter.
//
static apr_status_t resize_output_filter(ap_filter_t* f, apr_bucket_brigade* in_bb)
{
  request_rec* rec =f->r;
  resize_conf* conf = (resize_conf*)ap_get_module_config(rec->per_dir_config, &resizeimage_module);
  const char* content_type, *target_type = "JPEG";
  const char* image_url, *resize_param, *image_hash=NULL;
  Magick::Blob blob;
  char* vlob = NULL;
  size_t vlob_length = 0;
  int cache_hit = FALSE;

  AP_LOG_VERBOSE(rec, "Incoming %s.", __FUNCTION__);

  // Pass thru by request types.
  if(rec->status!=HTTP_OK || rec->main!=NULL || rec->header_only
    || (rec->handler!= NULL && strcmp(rec->handler, "default-handler") == 0)) goto PASS_THRU;

  AP_LOG_VERBOSE(rec, "-- Checking responce headers.");

  // Obtain and erase x-resize-image header or pass through.
  image_url = get_and_unset_header(rec->headers_out, X_RESIZE);
  if(image_url== NULL || image_url[0]=='\0') {
    image_url = get_and_unset_header(rec->err_headers_out, X_RESIZE);
  }
  if(image_url==NULL || image_url[0]=='\0') goto PASS_THRU;

  // Check content-type
  content_type = rec->content_type;
  if(content_type) {
    if(strcasecmp(content_type, "image/jpeg")==0) {
      target_type = "JPEG";
    } else
    if(strcasecmp(content_type, "image/png")==0) {
      target_type = "PNG";
    } else
    if(strcasecmp(content_type, "image/gif")==0) {
      target_type = "GIF";
    } else goto PASS_THRU;
  }

  // Resize parameter
  resize_param = get_and_unset_header(rec->headers_out, X_RESIZE_PARAM);
  if(resize_param==NULL || resize_param[0]=='\0') {
    resize_param = get_and_unset_header(rec->err_headers_out, X_RESIZE_PARAM);
  }
  if(resize_param[0]=='\0') resize_param = NULL;

  // Image hash
  image_hash = get_and_unset_header(rec->headers_out, X_RESIZE_HASH);
  if(image_hash==NULL || image_hash[0]=='\0') {
    image_hash = get_and_unset_header(rec->err_headers_out, X_RESIZE_HASH);
  }
 
  // Open image and resize.
  AP_LOG_INFO(rec, "URL: %s, %s => %s (%s)", image_url, content_type, resize_param, image_hash);

  if(image_hash) {
    // Try memcached...
    image_hash = apr_psprintf(rec->pool, "%s:%s:%s", image_hash, target_type, resize_param);
    memcached_return r;
    uint32_t flags;
    vlob = memcached_get(conf->memc, image_hash, strlen(image_hash), &vlob_length, &flags, &r);
    if(r==MEMCACHED_SUCCESS) {
      AP_LOG_DEBUG(rec, "Restored from memcached: %s, len=%d", image_hash, vlob_length);
      cache_hit = TRUE;
      goto WRITE_DATA;
    } else {
      AP_LOG_DEBUG(rec, "Can't restore from memcached: %s - %s(%d)", image_hash, memcached_strerror(conf->memc, r), r);
    }
  }

  // Reszize
  try {
    Magick::Image image;

    image.read(image_url);
    if(resize_param) image.zoom(resize_param);
    image.magick(target_type);
    image.quality(conf->jpeg_quality);
    image.write(&blob);
    vlob = (char*)blob.data();
    vlob_length = blob.length();
  }
  catch(Magick::Exception& err) {
    AP_LOG_ERR(rec, __FILE__ ": Magick failed: %s", err.what());
    goto PASS_THRU;
  }

  if(image_hash) {
    // Store to memcached...
    memcached_return r = memcached_set(conf->memc, image_hash, strlen(image_hash), vlob, vlob_length, conf->expire, 0);
    if(r==MEMCACHED_SUCCESS) {
      AP_LOG_DEBUG(rec, "Stored to memcached: %s(len=%d)", image_hash, vlob_length);
    } else {
      AP_LOG_DEBUG(rec, "Can't store from memcached: %s(len=%d) - %s(%d)", image_hash, vlob_length,memcached_strerror(conf->memc, r), r);
    }
  }

WRITE_DATA:
  AP_LOG_VERBOSE(rec, "-- Creating resize buckets.");

  // Drop all content and headers related.
  while(!APR_BRIGADE_EMPTY(in_bb)) {
    apr_bucket* b = APR_BRIGADE_FIRST(in_bb);
    apr_bucket_delete(b);
  }
  rec->eos_sent = 0;
  rec->clength = 0;
  unset_header(rec, "Content-Length");
  unset_header(rec, "Content-Encoding");
  unset_header(rec, "Last-Modified");
  unset_header(rec, "ETag");

  // Start resize bucket.
  {
    apr_off_t remain = vlob_length, offset = 0;
    while(remain>0) {
      apr_off_t bs = (remain<AP_MAX_SENDFILE)? remain: AP_MAX_SENDFILE;
      char* heap = (char*)malloc(bs);
      memcpy(heap, vlob+offset, bs);
      apr_bucket* b = apr_bucket_heap_create(heap, bs, free, in_bb-> bucket_alloc);
      APR_BRIGADE_INSERT_TAIL(in_bb, b);
      remain -= bs;
      offset += bs;
    }
    APR_BRIGADE_INSERT_TAIL(in_bb, apr_bucket_eos_create(in_bb->bucket_alloc));
    ap_set_content_length(rec, vlob_length);
    if(cache_hit) free(vlob);
  }
  AP_LOG_VERBOSE(rec, "-- Create done.");
 
PASS_THRU:
  AP_LOG_VERBOSE(rec, "-- Filter done.");
  ap_remove_output_filter(f);
  return ap_pass_brigade(f->next, in_bb);
}
Beispiel #7
0
      /* Ready to send data to the server. */
      debug_msg("carbon proxy:: %s is ready to receive",gmetad_config.carbon_server);
      nbytes = write (carbon_socket, graphite_msg, strlen(graphite_msg) + 1);
      if (nbytes < 0) {
        err_msg("write: %s", strerror(errno));
        close(carbon_socket);
        return EXIT_FAILURE;
      }
    } else if ( carbon_struct_poll.revents & POLLHUP ) {
      debug_msg("carbon proxy:: Recvd an RST from %s during transmission",gmetad_config.carbon_server);
     close(carbon_socket);
     return EXIT_FAILURE;
    } else if ( carbon_struct_poll.revents & POLLERR ) {
      debug_msg("carbon proxy:: Recvd an POLLERR from %s during transmission",gmetad_config.carbon_server);
      close(carbon_socket);
      return EXIT_FAILURE;
    }
  }
  close (carbon_socket);
  return EXIT_SUCCESS;
}

#ifdef WITH_MEMCACHED
#define MEMCACHED_MAX_KEY_LENGTH 250 /* Maximum allowed by memcached */
int
write_data_to_memcached ( const char *cluster, const char *host, const char *metric, 
                    const char *sum, unsigned int process_time, unsigned int expiry )
{
   time_t expiry_time;
   char s_path[MEMCACHED_MAX_KEY_LENGTH];
   if (strlen(cluster) + strlen(host) + strlen(metric) + 3 > MEMCACHED_MAX_KEY_LENGTH) {
      debug_msg("Cluster + host + metric + 3 > %d", MEMCACHED_MAX_KEY_LENGTH);
      return EXIT_FAILURE;
   }
   sprintf(s_path, "%s/%s/%s", cluster, host, metric);

   if (expiry != 0) {
      expiry_time = expiry;
   } else {
      expiry_time = (time_t) 0;
   }

   memcached_return_t rc;
   memcached_st *memc = memcached_pool_pop(memcached_connection_pool, false, &rc);
   if (rc != MEMCACHED_SUCCESS) {
      debug_msg("Unable to retrieve a memcached connection from the pool");
      return EXIT_FAILURE;
   }
   rc = memcached_set(memc, s_path, strlen(s_path), sum, strlen(sum), expiry_time, (uint32_t)0);
   if (rc != MEMCACHED_SUCCESS) {
      debug_msg("Unable to push %s value %s to the memcached server(s) - %s", s_path, sum, memcached_strerror(memc, rc));
      memcached_pool_push(memcached_connection_pool, memc);
      return EXIT_FAILURE;
   } else {
      debug_msg("Pushed %s value %s to the memcached server(s)", s_path, sum);
      memcached_pool_push(memcached_connection_pool, memc);
      return EXIT_SUCCESS;
   }
}
Beispiel #8
0
int main() {

    //memcached_t 时client handle
    //memcached_return_t 返回的消息类型
    memcached_st *memcli = NULL;

    //EE create a connect
    memcli = memcached_create(NULL); //NULL 为你分配空间
    if (memcli == NULL) {
        perror("memcached_create failed");
        exit(1);
    }

    memcached_return_t rtmsg ;
    //EE connecting to server
    //memcached_server_st server handle
    //connect memcache server
    //加入serverlist
    //port 
    memcached_server_st * memser = memcached_server_list_append(NULL, "127.0.0.1", 11211, &rtmsg);
    if (memser == NULL || rtmsg != MEMCACHED_SUCCESS) {
        perror("memcached_server_list_append failed");
        exit(1);
    }

    //connect client and server
	rtmsg = memcached_server_push(memcli, memser);
    if (rtmsg != MEMCACHED_SUCCESS) {
        printf(" memcached_server_push faled: %s\n", 
               memcached_strerror(memcli, rtmsg));
        exit(1);
    }

    //Add v-k to server
    char *key = "foll";
    char value[] ="hello";

    //EE 所有的设置操作
    //都是相同的 最后时时间和flags
    //len 不包括'\0'结尾
    rtmsg = memcached_set(memcli,  //client
                          key, strlen(key), //key and keylen
                          value, strlen(value), //value, valuelen
                          (time_t)0, //Experimental time
                          0); //flags

    //EE check rtmsg
    if (rtmsg != MEMCACHED_SUCCESS) {
        printf(" memcached_set faled: %s\n", 
               memcached_strerror(memcli, rtmsg));
        exit(1);
    }

    char buf[1024];
    //EE get v-k
    size_t valuelen=0;
    uint32_t flags=0;
    char *v = memcached_get(memcli,
                             key, strlen(key),
                             &valuelen,
                             &flags,
                             &rtmsg);

    memcpy(buf, v, valuelen);
    buf[valuelen]='\0';
    printf("vlen:%ld, flags:%u, value:%s\n", valuelen, flags, buf);


//	 memcached_return_t //
//	   memcached_mget (memcached_st *ptr,
//			 const char * const *keys,
//			 const size_t *key_length,
//			 size_t number_of_keys);

    //EE free server
	 memcached_server_free(memser);
    //EE free client 
    memcached_free(memcli);


    return 0;
}
Beispiel #9
0
/// Update the data for the specified namespace and key.  Writes the data
/// atomically, so if the underlying data has changed since it was last
/// read, the update is rejected and this returns Store::Status::CONTENTION.
Store::Status BaseMemcachedStore::set_data(const std::string& table,
                                           const std::string& key,
                                           const std::string& data,
                                           uint64_t cas,
                                           int expiry,
                                           SAS::TrailId trail)
{
  Store::Status status = Store::Status::OK;

  TRC_DEBUG("Writing %d bytes to table %s key %s, CAS = %ld, expiry = %d",
            data.length(), table.c_str(), key.c_str(), cas, expiry);

  // Construct the fully qualified key.
  std::string fqkey = table + "\\\\" + key;
  const char* key_ptr = fqkey.data();
  const size_t key_len = fqkey.length();

  int vbucket = vbucket_for_key(fqkey);
  const std::vector<memcached_st*>& replicas = get_replicas(vbucket, Op::WRITE);

  if (trail != 0)
  {
    SAS::Event start(trail, SASEvent::MEMCACHED_SET_START, 0);
    start.add_var_param(fqkey);
    start.add_var_param(data);
    start.add_static_param(cas);
    start.add_static_param(expiry);
    SAS::report_event(start);
  }

  TRC_DEBUG("%d write replicas for key %s", replicas.size(), fqkey.c_str());

  // Calculate a timestamp (least-significant 32 bits of milliseconds since the
  // epoch) for the current time.  We store this in the flags field to allow us
  // to resolve conflicts when resynchronizing between memcached servers.
  struct timespec ts;
  (void)clock_gettime(CLOCK_REALTIME, &ts);
  uint32_t flags = (uint32_t)((ts.tv_sec * 1000) + (ts.tv_nsec / 1000000));

  // Memcached uses a flexible mechanism for specifying expiration.
  // - 0 indicates never expire.
  // - <= MEMCACHED_EXPIRATION_MAXDELTA indicates a relative (delta) time.
  // - > MEMCACHED_EXPIRATION_MAXDELTA indicates an absolute time.
  // Absolute time is the only way to force immediate expiry.  Unfortunately,
  // it's not reliable - see https://github.com/Metaswitch/cpp-common/issues/160
  // for details.  Instead, we use relative time for future times (expiry > 0)
  // and the earliest absolute time for immediate expiry (expiry == 0).
  time_t memcached_expiration =
    (time_t)((expiry > 0) ? expiry : MEMCACHED_EXPIRATION_MAXDELTA + 1);

  // First try to write the primary data record to the first responding
  // server.
  memcached_return_t rc = MEMCACHED_ERROR;
  size_t ii;
  size_t replica_idx;

  // If we only have one replica, we should try it twice -
  // libmemcached won't notice a dropped TCP connection until it tries
  // to make a request on it, and will fail the request then
  // reconnect, so the second attempt could still work.
  size_t attempts = (replicas.size() == 1) ? 2: replicas.size();

  for (ii = 0; ii < attempts; ++ii)
  {
    if ((replicas.size() == 1) && (ii == 1)) {
      if (rc != MEMCACHED_CONNECTION_FAILURE)
      {
        // This is a legitimate error, not a transient server failure, so we
        // shouldn't retry.
        break;
      }
      replica_idx = 0;
      TRC_WARNING("Failed to write to sole memcached replica: retrying once");
    }
    else
    {
      replica_idx = ii;
    }

    TRC_DEBUG("Attempt conditional write to vbucket %d on replica %d (connection %p), CAS = %ld, expiry = %d",
              vbucket,
              replica_idx,
              replicas[replica_idx],
              cas,
              expiry);

    if (cas == 0)
    {
      // New record, so attempt to add (but overwrite any tombstones we
      // encounter).  This will fail if someone else got there first and some
      // data already exists in memcached for this key.
      rc = add_overwriting_tombstone(replicas[replica_idx],
                                     key_ptr,
                                     key_len,
                                     vbucket,
                                     data,
                                     memcached_expiration,
                                     flags,
                                     trail);
    }
    else
    {
      // This is an update to an existing record, so use memcached_cas
      // to make sure it is atomic.
      rc = memcached_cas_vb(replicas[replica_idx],
                            key_ptr,
                            key_len,
                            _binary ? vbucket : 0,
                            data.data(),
                            data.length(),
                            memcached_expiration,
                            flags,
                            cas);

      if (!memcached_success(rc))
      {
        TRC_DEBUG("memcached_cas command failed, rc = %d (%s)\n%s",
                  rc,
                  memcached_strerror(replicas[replica_idx], rc),
                  memcached_last_error_message(replicas[replica_idx]));
      }
    }

    if (memcached_success(rc))
    {
      TRC_DEBUG("Conditional write succeeded to replica %d", replica_idx);
      break;
    }
    else if ((rc == MEMCACHED_NOTSTORED) ||
             (rc == MEMCACHED_DATA_EXISTS))
    {
      if (trail != 0)
      {
        SAS::Event err(trail, SASEvent::MEMCACHED_SET_CONTENTION, 0);
        err.add_var_param(fqkey);
        SAS::report_event(err);
      }

      // A NOT_STORED or EXISTS response indicates a concurrent write failure,
      // so return this to the application immediately - don't go on to
      // other replicas.
      TRC_INFO("Contention writing data for %s to store", fqkey.c_str());
      status = Store::Status::DATA_CONTENTION;
      break;
    }
  }

  if ((rc == MEMCACHED_SUCCESS) &&
      (replica_idx < replicas.size()))
  {
    // Write has succeeded, so write unconditionally (and asynchronously)
    // to the replicas.
    for (size_t jj = replica_idx + 1; jj < replicas.size(); ++jj)
    {
      TRC_DEBUG("Attempt unconditional write to replica %d", jj);
      memcached_behavior_set(replicas[jj], MEMCACHED_BEHAVIOR_NOREPLY, 1);
      memcached_set_vb(replicas[jj],
                      key_ptr,
                      key_len,
                      _binary ? vbucket : 0,
                      data.data(),
                      data.length(),
                      memcached_expiration,
                      flags);
      memcached_behavior_set(replicas[jj], MEMCACHED_BEHAVIOR_NOREPLY, 0);
    }
  }

  if ((!memcached_success(rc)) &&
      (rc != MEMCACHED_NOTSTORED) &&
      (rc != MEMCACHED_DATA_EXISTS))
  {
    if (trail != 0)
    {
      SAS::Event err(trail, SASEvent::MEMCACHED_SET_FAILED, 0);
      err.add_var_param(fqkey);
      SAS::report_event(err);
    }

    update_vbucket_comm_state(vbucket, FAILED);

    if (_comm_monitor)
    {
      _comm_monitor->inform_failure();
    }

    TRC_ERROR("Failed to write data for %s to %d replicas",
              fqkey.c_str(), replicas.size());
    status = Store::Status::ERROR;
  }
  else
  {
    update_vbucket_comm_state(vbucket, OK);

    if (_comm_monitor)
    {
      _comm_monitor->inform_success();
    }
  }

  return status;
}
Beispiel #10
0
memcached_return_t BaseMemcachedStore::add_overwriting_tombstone(memcached_st* replica,
                                                                 const char* key_ptr,
                                                                 const size_t key_len,
                                                                 const uint32_t vbucket,
                                                                 const std::string& data,
                                                                 time_t memcached_expiration,
                                                                 uint32_t flags,
                                                                 SAS::TrailId trail)
{
  memcached_return_t rc;
  uint64_t cas = 0;

  TRC_DEBUG("Attempting to add data for key %.*s", key_len, key_ptr);

  // Convert the key into a std::string (sas-client does not like that
  // key_{ptr,len} are constant).
  const std::string key(key_ptr, key_len);

  while (true)
  {
    if (cas == 0)
    {
      TRC_DEBUG("Attempting memcached ADD command");
      rc = memcached_add_vb(replica,
                            key_ptr,
                            key_len,
                            _binary ? vbucket : 0,
                            data.data(),
                            data.length(),
                            memcached_expiration,
                            flags);
    }
    else
    {
      TRC_DEBUG("Attempting memcached CAS command (cas = %d)", cas);
      rc = memcached_cas_vb(replica,
                            key_ptr,
                            key_len,
                            _binary ? vbucket : 0,
                            data.data(),
                            data.length(),
                            memcached_expiration,
                            flags,
                            cas);
    }

    if ((rc == MEMCACHED_DATA_EXISTS) ||
        (rc == MEMCACHED_NOTSTORED))
    {
      // A record with this key already exists. If it is a tombstone, we need
      // to overwrite it. Get the record to see what it is.
      memcached_return_t get_rc;
      std::string existing_data;

      TRC_DEBUG("Existing data prevented the ADD/CAS."
                "Issue GET to see if we need to overwrite a tombstone");
      get_rc = get_from_replica(replica, key_ptr, key_len, existing_data, cas);

      if (memcached_success(get_rc))
      {
        if (existing_data != TOMBSTONE)
        {
          // The existing record is not a tombstone.  We mustn't overwrite
          // this, so break out of the loop and return the original return code
          // from the ADD/CAS.
          TRC_DEBUG("Found real data. Give up");
          break;
        }
        else
        {
          // The existing record IS a tombstone. Go round the loop again to
          // overwrite it. `cas` has been set to the cas of the tombstone.
          TRC_DEBUG("Found a tombstone. Attempt to overwrite");

          if (trail != 0)
          {
            SAS::Event event(trail, SASEvent::MEMCACHED_SET_BLOCKED_BY_TOMBSTONE, 0);
            event.add_var_param(key);
            event.add_static_param(cas);
            SAS::report_event(event);
          }
        }
      }
      else if (get_rc == MEMCACHED_NOTFOUND)
      {
        // The GET returned that there is no record for this key. This can
        // happen if the record has expired. We need to try again (it could
        // have been a tombstone which should not block adds).
        TRC_DEBUG("GET failed with NOT_FOUND");

        if (trail != 0)
        {
          SAS::Event event(trail, SASEvent::MEMCACHED_SET_BLOCKED_BY_EXPIRED, 0);
          event.add_var_param(key);
          SAS::report_event(event);
        }
      }
      else
      {
        // The replica failed. Return the return code from the original ADD/CAS.
        TRC_DEBUG("GET failed, rc = %d (%s)\n%s",
                  get_rc,
                  memcached_strerror(replica, get_rc),
                  memcached_last_error_message(replica));
        break;
      }
    }
    else
    {
      TRC_DEBUG("ADD/CAS returned rc = %d (%s)\n%s",
                rc,
                memcached_strerror(replica, rc),
                memcached_last_error_message(replica));
      break;
    }
  }

  return rc;
}
Beispiel #11
0
/// Retrieve the data for a given namespace and key.
Store::Status BaseMemcachedStore::get_data(const std::string& table,
                                           const std::string& key,
                                           std::string& data,
                                           uint64_t& cas,
                                           SAS::TrailId trail)
{
  Store::Status status;

  // Construct the fully qualified key.
  std::string fqkey = table + "\\\\" + key;
  const char* key_ptr = fqkey.data();
  const size_t key_len = fqkey.length();

  int vbucket = vbucket_for_key(fqkey);
  const std::vector<memcached_st*>& replicas = get_replicas(vbucket, Op::READ);

  if (trail != 0)
  {
    SAS::Event start(trail, SASEvent::MEMCACHED_GET_START, 0);
    start.add_var_param(fqkey);
    SAS::report_event(start);
  }

  TRC_DEBUG("%d read replicas for key %s", replicas.size(), fqkey.c_str());

  // Read from all replicas until we get a positive result.
  memcached_return_t rc = MEMCACHED_ERROR;
  bool active_not_found = false;
  size_t failed_replicas = 0;
  size_t ii;

  // If we only have one replica, we should try it twice -
  // libmemcached won't notice a dropped TCP connection until it tries
  // to make a request on it, and will fail the request then
  // reconnect, so the second attempt could still work.
  size_t attempts = (replicas.size() == 1) ? 2 : replicas.size();

  for (ii = 0; ii < attempts; ++ii)
  {
    size_t replica_idx;
    if ((replicas.size() == 1) && (ii == 1))
    {
      if (rc != MEMCACHED_CONNECTION_FAILURE)
      {
        // This is a legitimate error, not a server failure, so we
        // shouldn't retry.
        break;
      }
      replica_idx = 0;
      TRC_WARNING("Failed to read from sole memcached replica: retrying once");
    }
    else
    {
      replica_idx = ii;
    }

    TRC_DEBUG("Attempt to read from replica %d (connection %p)",
              replica_idx,
              replicas[replica_idx]);
    rc = get_from_replica(replicas[replica_idx], key_ptr, key_len, data, cas);

    if (memcached_success(rc))
    {
      // Got data back from this replica. Don't try any more.
      TRC_DEBUG("Read for %s on replica %d returned SUCCESS",
                fqkey.c_str(),
                replica_idx);
      break;
    }
    else if (rc == MEMCACHED_NOTFOUND)
    {
      // Failed to find a record on an active replica.  Flag this so if we do
      // find data on a later replica we can reset the cas value returned to
      // zero to ensure a subsequent write will succeed.
      TRC_DEBUG("Read for %s on replica %d returned NOTFOUND", fqkey.c_str(), replica_idx);
      active_not_found = true;
    }
    else
    {
      // Error from this node, so consider it inactive.
      TRC_DEBUG("Read for %s on replica %d returned error %d (%s)",
                fqkey.c_str(), replica_idx, rc, memcached_strerror(replicas[replica_idx], rc));
      ++failed_replicas;
    }
  }

  if (memcached_success(rc))
  {
    if (data != TOMBSTONE)
    {
      if (trail != 0)
      {
        SAS::Event got_data(trail, SASEvent::MEMCACHED_GET_SUCCESS, 0);
        got_data.add_var_param(fqkey);
        got_data.add_var_param(data);
        got_data.add_static_param(cas);
        SAS::report_event(got_data);
      }

      // Return the data and CAS value.  The CAS value is either set to the CAS
      // value from the result, or zero if an earlier active replica returned
      // NOT_FOUND.  This ensures that a subsequent set operation will succeed
      // on the earlier active replica.
      if (active_not_found)
      {
        cas = 0;
      }

      TRC_DEBUG("Read %d bytes from table %s key %s, CAS = %ld",
                data.length(), table.c_str(), key.c_str(), cas);
      status = Store::OK;
    }
    else
    {
      if (trail != 0)
      {
        SAS::Event got_tombstone(trail, SASEvent::MEMCACHED_GET_TOMBSTONE, 0);
        got_tombstone.add_var_param(fqkey);
        got_tombstone.add_static_param(cas);
        SAS::report_event(got_tombstone);
      }

      // We have read a tombstone. Return NOT_FOUND to the caller, and also
      // zero out the CAS (returning a zero CAS makes the interface cleaner).
      TRC_DEBUG("Read tombstone from table %s key %s, CAS = %ld",
                table.c_str(), key.c_str(), cas);
      cas = 0;
      status = Store::NOT_FOUND;
    }

    // Regardless of whether we got a tombstone, the vbucket is alive.
    update_vbucket_comm_state(vbucket, OK);

    if (_comm_monitor)
    {
      _comm_monitor->inform_success();
    }
  }
  else if (failed_replicas < replicas.size())
  {
    // At least one replica returned NOT_FOUND.
    if (trail != 0)
    {
      SAS::Event not_found(trail, SASEvent::MEMCACHED_GET_NOT_FOUND, 0);
      not_found.add_var_param(fqkey);
      SAS::report_event(not_found);
    }

    TRC_DEBUG("At least one replica returned not found, so return NOT_FOUND");
    status = Store::Status::NOT_FOUND;

    update_vbucket_comm_state(vbucket, OK);

    if (_comm_monitor)
    {
      _comm_monitor->inform_success();
    }
  }
  else
  {
    // All replicas returned an error, so log the error and return the
    // failure.
    if (trail != 0)
    {
      SAS::Event err(trail, SASEvent::MEMCACHED_GET_ERROR, 0);
      err.add_var_param(fqkey);
      SAS::report_event(err);
    }

    TRC_ERROR("Failed to read data for %s from %d replicas",
              fqkey.c_str(), replicas.size());
    status = Store::Status::ERROR;

    update_vbucket_comm_state(vbucket, FAILED);

    if (_comm_monitor)
    {
      _comm_monitor->inform_failure();
    }
  }

  return status;
}
Beispiel #12
0
int main(int argc, char *argv[])
{
  memcached_st *memc;
  memcached_return_t rc;
  memcached_server_st *servers;
  memcached_dump_fn callbacks[1];

  callbacks[0]= &key_printer;

  options_parse(argc, argv);

  memc= memcached_create(NULL);
  process_hash_option(memc, opt_hash);

  if (!opt_servers)
  {
    char *temp;

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

  if (opt_servers)
    servers= memcached_servers_parse(opt_servers);
  else
    servers= memcached_servers_parse(argv[--argc]);

  memcached_server_push(memc, servers);
  memcached_server_list_free(servers);
  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
                         (uint64_t)opt_binary);
  if (!initialize_sasl(memc, opt_username, opt_passwd))
  {
    memcached_free(memc);
    return EXIT_FAILURE;
  }

  rc= memcached_dump(memc, callbacks, NULL, 1);

  if (rc != MEMCACHED_SUCCESS)
  {
    fprintf(stderr, "memdump: memcache error %s", memcached_strerror(memc, rc));
    if (memcached_last_error_errno(memc))
      fprintf(stderr, " system error %s", strerror(memcached_last_error_errno(memc)));
    fprintf(stderr, "\n");
  }

  memcached_free(memc);

  if (opt_servers)
    free(opt_servers);
  if (opt_hash)
    free(opt_hash);

  shutdown_sasl();

  return EXIT_SUCCESS;
}
static int
do_btree_test(struct client *cli)
{
  memcached_coll_create_attrs_st create_attr;
  memcached_return rc;
  int ok, keylen, base;
  const char *key;
  uint64_t bkey;
  uint8_t *val_ptr;
  int val_len;

  // Pick a key
  key = keyset_get_key(cli->ks, &base);
  keylen = strlen(key);

  // Create a btree item
  if (0 != client_before_request(cli))
    return -1;

  memcached_coll_create_attrs_init(&create_attr, 20 /* flags */,
    100 /* exptime */, 4000 /* maxcount */);  
  memcached_coll_create_attrs_set_overflowaction(&create_attr,
    OVERFLOWACTION_SMALLEST_TRIM);
  rc = memcached_bop_create(cli->next_mc, key, keylen, &create_attr);
  ok = (rc == MEMCACHED_SUCCESS);
  if (!ok) {
    print_log("bop create failed. id=%d key=%s rc=%d(%s)", cli->id, key,
      rc, memcached_strerror(NULL, rc));
  }
  if (0 != client_after_request(cli, ok))
    return -1;

  // Insert 1000 elements
  for (bkey = base; bkey < base + 1000; bkey++) {
    char bkey_buf[32];
    int bkey_len;
    
    if (0 != client_before_request(cli))
      return -1;

    bkey_len = sprintf(bkey_buf, "%d", (int)bkey);

    val_ptr = NULL;
    val_len = valueset_get_value(cli->vs, &val_ptr);
    assert(val_ptr != NULL && val_len > 0 && val_len <= 4096);
    
    rc = memcached_bop_ext_insert(cli->next_mc, key, keylen,
      (const unsigned char*)bkey_buf,  bkey_len,
      NULL /* eflag */, 0 /* eflag length */,
      (const char*)val_ptr, (size_t)val_len,
      NULL /* Do not create automatically */);
    valueset_return_value(cli->vs, val_ptr);
    ok = (rc == MEMCACHED_SUCCESS);
    if (!ok) {
      print_log("bop insert failed. id=%d key=%s bkey=%llu rc=%d(%s)",
        cli->id, key, (long long unsigned)bkey,
        rc, memcached_strerror(NULL, rc));
    }
    if (0 != client_after_request(cli, ok))
      return -1;
  }

  return 0;
}
Beispiel #14
0
    bool base_client::insert(std::string key, const size_t num_of_items,
                             const uint64_t *bkeys, const char * const *values, const size_t *value_lengths,
                             memcached_coll_create_attrs_st *create_attrs, memcached_return_t *rc)
    {
        bool result = false;
#ifdef ENABLE_TWO_COPY_REP
        memcached_st *handle;
        memcached_return_t *piped_results;
        memcached_return_t piped_rc;

        memcached_coll_attrs_st set_attrs; 
        memcached_coll_attrs_init(&set_attrs);
        memcached_coll_attrs_set_expiretime(&set_attrs, create_attrs->expiretime);
        memcached_coll_attrs_set_readable_on(&set_attrs);
        
        memcached_coll_create_attrs_set_expiretime(create_attrs, 2); /* expiretime = 2 */
        memcached_coll_create_attrs_set_unreadable(create_attrs, true);

        piped_results = (memcached_return_t*)malloc(sizeof(memcached_return_t)*num_of_items);
        if (piped_results == NULL) {
            *rc = MEMCACHED_MEMORY_ALLOCATION_FAILURE;
            return result;
        }

        if (1) { /* _master_pool != NULL */
            if ((handle = _master_pool->fetch(rc)) == NULL) {
                /* *rc: MEMCACHED_IN_PROGRESS || MEMCACHED_NOTFOUND || MEMCACHED_TIMEOUT ||
                        MEMCACHED_ERRNO || MEMCACHED_SUCCESS(grow_pool() failure) */
                free(piped_results);
                return result;
            }

            for (int i = 0; i < DEFAULT_OPERATION_RETRY_COUNT; i++) {
                /* 1. create with unreadable flag */ 
                *rc = memcached_bop_create(handle, key.c_str(), key.length(), create_attrs);
                if (*rc == MEMCACHED_TIMEOUT) {
                    /* get the count of elements */ 
                    memcached_coll_attrs_st get_attrs; 
                    *rc = memcached_get_attrs(handle, key.c_str(), key.length(), &get_attrs);
                    if (*rc == MEMCACHED_NOTFOUND) continue;
                    if (*rc == MEMCACHED_SUCCESS) {
                        if (get_attrs.count != 0) *rc = MEMCACHED_EXISTS;
                        /* attrs.count == 0: OK => go downward */ 
                    }
                }
                /* 2. insert columns(elements) */
                if (*rc == MEMCACHED_SUCCESS) {
                    *rc = memcached_bop_piped_insert(handle, key.c_str(), key.length(), num_of_items,
                                 bkeys, NULL, 0, values, value_lengths, NULL, piped_results, &piped_rc);
                    if (*rc == MEMCACHED_TIMEOUT) {
                        memcached_return_t rrc = memcached_delete(handle, key.c_str(), key.length(), 0);
                        if (rrc == MEMCACHED_SUCCESS || rrc == MEMCACHED_NOTFOUND) continue;
                    }
                }
                break;
            }

            if (*rc == MEMCACHED_SUCCESS && piped_rc == MEMCACHED_ALL_SUCCESS) {
                /* 3. set readable */
                for (int i = 0; i < DEFAULT_OPERATION_RETRY_COUNT; i++) {
                    *rc = memcached_set_attrs(handle, key.c_str(), key.length(), &set_attrs);
                    if (*rc != MEMCACHED_TIMEOUT) break;
                }
                if (*rc == MEMCACHED_SUCCESS) {
                    result = true;
                }
            }

            if (result != true) {
                if (*rc == MEMCACHED_EXISTS) {
                    DEBUG("key(%s) or element exists (%s)", key.c_str(), _master_pool->to_string());
                } else {
                    ERROR("insert failed : rolling back (%s)", _master_pool->to_string());
                    memcached_return_t rrc = memcached_delete(handle, key.c_str(), key.length(), 0);
                    if (rrc != MEMCACHED_SUCCESS && rrc != MEMCACHED_NOTFOUND) {
                        ERROR("delete failed : %s (%s)", memcached_strerror(NULL, rrc), _master_pool->to_string());
                    } 
                }
            } 

            _master_pool->release(handle, NULL);
        } while(0);

        if (_backup_pool != NULL) {
            if (result == true || *rc == MEMCACHED_NO_SERVERS) {
                memcached_return_t brc;
                if ((handle = _backup_pool->fetch(&brc)) != NULL) {
                    do {
                        /* 1. create with unreadable flag */ 
                        brc = memcached_bop_create(handle, key.c_str(), key.length(), create_attrs);
                        if (brc != MEMCACHED_SUCCESS) break;

                        /* 2. insert columns(elements) */
                        brc = memcached_bop_piped_insert(handle, key.c_str(), key.length(), num_of_items,
                                     bkeys, NULL, 0, values, value_lengths, NULL, piped_results, &piped_rc);
                        if (brc != MEMCACHED_SUCCESS || piped_rc != MEMCACHED_ALL_SUCCESS) break;

                        /* 3. set readable */
                        brc = memcached_set_attrs(handle, key.c_str(), key.length(), &set_attrs);
                    } while(0);

                    if (brc != MEMCACHED_SUCCESS || piped_rc != MEMCACHED_ALL_SUCCESS) {
                        brc = memcached_delete(handle, key.c_str(), key.length(), 0);
                        if (brc != MEMCACHED_SUCCESS && brc != MEMCACHED_NOTFOUND) {
                            ERROR("delete failed : %s (%s)", memcached_strerror(NULL, brc), _backup_pool->to_string());
                        }
                    }
                    _backup_pool->release(handle, NULL);
                }
            }
        }
#else
        memcached_return_t *piped_results = (memcached_return_t*)malloc(sizeof(memcached_return_t)*num_of_items);
        memcached_return_t piped_rc;

        memcached_coll_create_attrs_set_unreadable(create_attrs, true);

        memcached_coll_attrs_st attrs; 
        memcached_coll_attrs_init(&attrs);
        memcached_coll_attrs_set_readable_on(&attrs);

        if (1) {
            connection_pool *pool = _cluster->pool(MASTER_CLUSTER); 
            memcached_st *handle = pool->fetch(rc);

            // FIXME
            for (size_t i = 0; handle != NULL && i < DEFAULT_OPERATION_RETRY_COUNT; ++i) {
                // 0. remove existing key when retry.    
                if (i > 0) {
                    DEBUG("insert : retry %d (%s)", i, pool->to_string());
                    memcached_return_t rrc = memcached_delete(handle, key.c_str(), key.length(), 0);
                    if (rrc != MEMCACHED_SUCCESS) {
                        ERROR("delete failed : %s (%s)", memcached_strerror(NULL, rrc), pool->to_string());
                        continue;
                    }
                }

                // 1. create with unreadable state.
                *rc = memcached_bop_create(handle, key.c_str(), key.length(), create_attrs);

                if (*rc == MEMCACHED_TIMEOUT) {
                    continue;
                }

                if (*rc != MEMCACHED_SUCCESS) {
                    break;
                }

                // 2. insert fields
                *rc = memcached_bop_piped_insert(handle, key.c_str(), key.length(), num_of_items,
                         bkeys, NULL, 0, values, value_lengths, NULL, piped_results, &piped_rc);

                if (*rc == MEMCACHED_TIMEOUT) {
                    continue;
                }

                if (piped_rc != MEMCACHED_ALL_SUCCESS) {
                    break;
                }

                // 3. change to readable state. 
                *rc = memcached_set_attrs(handle, key.c_str(), key.length(), &attrs);

                if (*rc != MEMCACHED_TIMEOUT) {
                    break;
                }
            }

            if (*rc == MEMCACHED_SUCCESS) {
                result = true;
            } else if (*rc == MEMCACHED_EXISTS) {
                DEBUG("key(%s) or element exists (%s)", key.c_str(), pool->to_string());
            } else {
                ERROR("insert failed : rolling back (%s)", pool->to_string());
                memcached_return_t rrc = memcached_delete(handle, key.c_str(), key.length(), 0);
                if (rrc != MEMCACHED_SUCCESS) {
                    ERROR("delete failed : %s (%s)", memcached_strerror(NULL, rrc), pool->to_string());
                }
            }

            pool->release(handle, NULL);
        }
#endif

        free(piped_results);

        return result;
    }
Beispiel #15
0
void _PG_init(void)
{
  MemoryContext old_ctxt;

  globals.pg_ctxt = AllocSetContextCreate(TopMemoryContext,
					  "pgmemcache global context",
					  ALLOCSET_SMALL_MINSIZE,
					  ALLOCSET_SMALL_INITSIZE,
					  ALLOCSET_SMALL_MAXSIZE);

  old_ctxt = MemoryContextSwitchTo(globals.pg_ctxt);
  globals.mc = memcached_create(NULL);

  if (memcached_set_memory_allocators(globals.mc,
				      (memcached_malloc_fn) pgmemcache_malloc,
				      (memcached_free_fn) pgmemcache_free,
				      (memcached_realloc_fn) pgmemcache_realloc,
				      (memcached_calloc_fn) pgmemcache_calloc,
				      NULL) != MEMCACHED_SUCCESS) {
    elog(ERROR, "pgmemcache: unable to set memory allocators");
  }

  MemoryContextSwitchTo(old_ctxt);

  DefineCustomStringVariable("pgmemcache.default_servers",
			     "Comma-separated list of memcached servers to connect to.",
			     "Specified as a comma-separated list of host:port (port is optional).",
			     &memcache_default_servers,
			     NULL,
			     PGC_USERSET,
			     GUC_LIST_INPUT,
#if defined(PG_VERSION_NUM) && (PG_VERSION_NUM >= 90100)
			     NULL,
#endif
			     assign_default_servers_guc,
			     show_default_servers_guc);

  DefineCustomStringVariable ("pgmemcache.default_behavior",
			      "Comma-separated list of memcached behavior (optional).",
			      "Specified as a comma-separated list of behavior_flag:behavior_data.",
			      &memcache_default_behavior,
			      NULL,
			      PGC_USERSET,
			      GUC_LIST_INPUT,
#if defined(PG_VERSION_NUM) && (PG_VERSION_NUM >= 90100)
			      NULL,
#endif
			      assign_default_behavior_guc,
			      show_default_behavior_guc);

  DefineCustomStringVariable ("pgmemcache.sasl_authentication_username",
			      "pgmemcache SASL user authentication username",
			      "Simple string pgmemcache.sasl_authentication_username = '******'",
			      &memcache_sasl_authentication_username,
			      NULL,
			      PGC_USERSET,
			      GUC_LIST_INPUT,
#if defined(PG_VERSION_NUM) && (PG_VERSION_NUM >= 90100)
			      NULL,
#endif
			      NULL,
			      show_memcache_sasl_authentication_username_guc);

  DefineCustomStringVariable ("pgmemcache.sasl_authentication_password",
			      "pgmemcache SASL user authentication password",
			      "Simple string pgmemcache.sasl_authentication_password = '******'",
			      &memcache_sasl_authentication_password,
			      NULL,
			      PGC_USERSET,
			      GUC_LIST_INPUT,
#if defined(PG_VERSION_NUM) && (PG_VERSION_NUM >= 90100)
			      NULL,
#endif
			      NULL,
			      show_memcache_sasl_authentication_password_guc);
#if LIBMEMCACHED_WITH_SASL_SUPPORT
  if ((strlen(memcache_sasl_authentication_username) > 0 && strlen(memcache_sasl_authentication_password) > 0) || (memcache_sasl_authentication_username != NULL && memcache_sasl_authentication_password != NULL)) {

        rc = memcached_set_sasl_auth_data(globals.mc, memcache_sasl_authentication_username, memcache_sasl_authentication_password);
        if (rc != MEMCACHED_SUCCESS) {
	    elog(ERROR, "%s ", memcached_strerror(globals.mc, rc));
        }
        _init_sasl();
      }
#endif
}
Beispiel #16
0
//Remove -gw and -did keys that are no longer in db
void DelOldKeys(char const *cCluster)
{
	memcached_return rc;

	if(!guSilent) printf("DelOldKeys() start\n");
	unsigned uCluster=uGetCluster(cCluster);
	if(!uCluster)
	{
		logfileLine("DelOldKeys cluster not found",cCluster);
		return;
	}

	void vKeyPrinter(const memcached_st *gsMemc, const char *cKey)
	{
        	MYSQL_RES *res;
		char *cp;
		unsigned uRc;
		memcached_st *gsLocalMemc;
		memcached_server_st *servers = NULL;
		gsLocalMemc=memcached_create(NULL);
		servers=memcached_server_list_append(servers,"localhost",11211,&rc);
		rc=memcached_server_push(gsLocalMemc,servers);
		if(rc!=MEMCACHED_SUCCESS)
		{
			sprintf(gcQuery,"couldn't add server: %s",memcached_strerror(gsLocalMemc,rc));
			logfileLine("vKeyPrinter",gcQuery);
			if(!guSilent) printf("%s\n",gcQuery);
			return;
		}

		if(strstr(cKey,"-did"))
		{
			if((cp=strchr(cKey,'-')))
				*cp=0;
			if(!guSilent) printf("%s-did\n",cKey);
			sprintf(gcQuery,"SELECT uDID FROM tDID WHERE cDID='%s' AND uCluster=%u",cKey,uCluster);
			mysql_query(&gMysql,gcQuery);
			if(mysql_errno(&gMysql))
			{
				printf(gcQuery);
				logfileLine("DelOldKeys",mysql_error(&gMysql));
				mysql_close(&gMysql);
				exit(2);
			}
        		res=mysql_store_result(&gMysql);
			if(mysql_num_rows(res)<1)
			{
				*cp='-';
				uRc=memcached_delete(gsLocalMemc,cKey,strlen(cKey),(time_t)0);
				if(uRc!=MEMCACHED_SUCCESS)
				{
					if(guLogLevel>2)
					{
						logfileLine("DelOldKeys not found",cKey);
					}
					if(!guSilent) printf("DelOldKeys() %s not found\n",cKey);
				}
				else
				{
					if(guLogLevel>2)
					{
						logfileLine("DelOldKeys",cKey);
					}
					if(!guSilent) printf("DelOldKeys() %s\n",cKey);
				}
			}
		}
		else if(strstr(cKey,"-gw"))
		{
			unsigned uPort=5060;
			char *cp2=NULL;
			if((cp=strchr(cKey,'-')))
				*cp=0;
			if((cp2=strchr(cKey,':')))
			{
				*cp2=0;
				sscanf(cp2+1,"%u",&uPort);
			}
			if(!guSilent)
			{
				if(cp2)
					printf("%s:%u-gw\n",cKey,uPort);
				else
					printf("%s-gw\n",cKey);
			}
			sprintf(gcQuery,"SELECT tAddress.uAddress FROM tAddress,tGateway,tPBX"
					" WHERE tAddress.cIP='%s' AND tAddress.uPort=%u"
					" AND ("
					" ( tAddress.uGateway=tGateway.uGateway"
					" AND tGateway.uCluster=%u"
					" ) OR ("
					" ( tAddress.uPBX=tPBX.uPBX"
					" AND tPBX.uCluster=%u) )"
					" )",cKey,uPort,uCluster,uCluster);
			mysql_query(&gMysql,gcQuery);
			if(mysql_errno(&gMysql))
			{
				printf(gcQuery);
				logfileLine("DelOldKeys",mysql_error(&gMysql));
				mysql_close(&gMysql);
				exit(2);
			}
        		res=mysql_store_result(&gMysql);
			if(mysql_num_rows(res)<1)
			{
				*cp='-';
				if(cp2)
					*cp2=':';
				uRc=memcached_delete(gsLocalMemc,cKey,strlen(cKey),(time_t)0);
				if(uRc!=MEMCACHED_SUCCESS)
				{
					if(guLogLevel>2)
					{
						logfileLine("DelOldKeys not found",cKey);
					}
					if(!guSilent) printf("DelOldKeys() %s not found\n",cKey);
				}
				else
				{
					if(guLogLevel>2)
					{
						logfileLine("DelOldKeys",cKey);
					}
					if(!guSilent) printf("DelOldKeys() %s\n",cKey);
				}
			}
		}
	}
Beispiel #17
0
          /* Ready to send data to the server. */
          debug_msg("carbon proxy:: %s is ready to receive",gmetad_config.carbon_server);
          nbytes = write (carbon_socket, graphite_msg, strlen(graphite_msg) + 1);
          if (nbytes < 0) {
            err_msg("write: %s", strerror(errno));
            close(carbon_socket);
            return EXIT_FAILURE;
          }
        } else if ( carbon_struct_poll.revents & POLLHUP ) {
          debug_msg("carbon proxy:: Recvd an RST from %s during transmission",gmetad_config.carbon_server);
         close(carbon_socket);
         return EXIT_FAILURE;
        } else if ( carbon_struct_poll.revents & POLLERR ) {
          debug_msg("carbon proxy:: Recvd an POLLERR from %s during transmission",gmetad_config.carbon_server);
          close(carbon_socket);
          return EXIT_FAILURE;
        }
      }
      close (carbon_socket);
      ganglia_scoreboard_inc(METS_SENT_GRAPHITE);
      ganglia_scoreboard_inc(METS_SENT_ALL);
      return EXIT_SUCCESS;

  } else {

      int nbytes;

      pthread_mutex_lock( &carbon_mutex );
      nbytes = sendto (carbon_udp_socket->sockfd, graphite_msg, strlen(graphite_msg), 0,
                         (struct sockaddr_in*)&carbon_udp_socket->sa, sizeof (struct sockaddr_in));
      pthread_mutex_unlock( &carbon_mutex );

      if (nbytes != strlen(graphite_msg))
      {
             err_msg("sendto socket (client): %s", strerror(errno));
             return EXIT_FAILURE;
      }
      ganglia_scoreboard_inc(METS_SENT_GRAPHITE);
      ganglia_scoreboard_inc(METS_SENT_ALL);
      return EXIT_SUCCESS;
  }
}

#ifdef WITH_MEMCACHED
#define MEMCACHED_MAX_KEY_LENGTH 250 /* Maximum allowed by memcached */
int
write_data_to_memcached ( const char *cluster, const char *host, const char *metric, 
                    const char *sum, unsigned int process_time, unsigned int expiry )
{
   apr_time_t start = apr_time_now(), now;
   time_t expiry_time;
   char s_path[MEMCACHED_MAX_KEY_LENGTH];
   
   // Check whether we are including cluster in the memcached key
   if ( gmetad_config.memcached_include_cluster_in_key ) {
      if (strlen(cluster) + strlen(host) + strlen(metric) + 3 > MEMCACHED_MAX_KEY_LENGTH) {
	  debug_msg("Cluster + host + metric + 3 > %d", MEMCACHED_MAX_KEY_LENGTH);
	  return EXIT_FAILURE;
      }
      sprintf(s_path, "%s/%s/%s", cluster, host, metric);
    } else {
      if ( strlen(host) + strlen(metric) + 3 > MEMCACHED_MAX_KEY_LENGTH) {
	  debug_msg("host + metric + 3 > %d", MEMCACHED_MAX_KEY_LENGTH);
	  return EXIT_FAILURE;
      }
      sprintf(s_path, "%s/%s", host, metric);     
   }
    
    
   if (expiry != 0) {
      expiry_time = expiry;
   } else {
      expiry_time = (time_t) 0;
   }

   memcached_return_t rc;
   memcached_st *memc = memcached_pool_pop(memcached_connection_pool, false, &rc);
   if (rc != MEMCACHED_SUCCESS) {
      debug_msg("Unable to retrieve a memcached connection from the pool");
      return EXIT_FAILURE;
   }
   rc = memcached_set(memc, s_path, strlen(s_path), sum, strlen(sum), expiry_time, (uint32_t)0);
   if (rc != MEMCACHED_SUCCESS) {
      debug_msg("Unable to push %s value %s to the memcached server(s) - %s", s_path, sum, memcached_strerror(memc, rc));
      memcached_pool_push(memcached_connection_pool, memc);
      return EXIT_FAILURE;
   } else {
      debug_msg("Pushed %s value %s to the memcached server(s)", s_path, sum);
      memcached_pool_push(memcached_connection_pool, memc);
      now = apr_time_now();
      last_memcached = now;  //Updating global variable
      ganglia_scoreboard_inc(METS_SENT_MEMCACHED);
      ganglia_scoreboard_inc(METS_SENT_ALL);
      ganglia_scoreboard_incby(METS_ALL_DURATION, now - start);
      ganglia_scoreboard_incby(METS_MEMCACHED_DURATION, now - start);
      return EXIT_SUCCESS;
   }
}
Beispiel #18
0
int main(int argc, char *argv[])
{
  memcached_st *memc;
  memcached_return_t rc;
  memcached_server_st *servers;

  int return_code= 0;

  options_parse(argc, argv);
  initialize_sockets();

  memc= memcached_create(NULL);
  process_hash_option(memc, opt_hash);

  if (!opt_servers)
  {
    char *temp;

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

  if (opt_servers)
    servers= memcached_servers_parse(opt_servers);
  else
    servers= memcached_servers_parse(argv[--argc]);

  memcached_server_push(memc, servers);
  memcached_server_list_free(servers);
  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
                         (uint64_t)opt_binary);
  if (!initialize_sasl(memc, opt_username, opt_passwd))
  {
    memcached_free(memc);
    return 1;
  }

  while (optind < argc)
  {
    struct stat sbuf;
    int fd;
    char *ptr;
    ssize_t read_length;
    char *file_buffer_ptr;

    fd= open(argv[optind], O_RDONLY);
    if (fd < 0)
    {
      fprintf(stderr, "memcp: %s: %s\n", argv[optind], strerror(errno));
      optind++;
      continue;
    }

    (void)fstat(fd, &sbuf);

    ptr= rindex(argv[optind], '/');
    if (ptr)
      ptr++;
    else
      ptr= argv[optind];

    if (opt_verbose)
    {
      static const char *opstr[] = { "set", "add", "replace" };
      printf("op: %s\nsource file: %s\nlength: %zu\n"
	     "key: %s\nflags: %x\nexpires: %llu\n",
	     opstr[opt_method - OPT_SET], argv[optind], (size_t)sbuf.st_size,
	     ptr, opt_flags, (unsigned long long)opt_expires);
    }

    if ((file_buffer_ptr= (char *)malloc(sizeof(char) * (size_t)sbuf.st_size)) == NULL)
    {
      fprintf(stderr, "malloc: %s\n", strerror(errno));
      exit(1);
    }

    if ((read_length= read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
    {
      fprintf(stderr, "read: %s\n", strerror(errno));
      exit(1);
    }

    if (read_length != sbuf.st_size)
    {
      fprintf(stderr, "Failure reading from file\n");
      exit(1);
    }

    if (opt_method == OPT_ADD)
      rc= memcached_add(memc, ptr, strlen(ptr),
                        file_buffer_ptr, (size_t)sbuf.st_size,
			opt_expires, opt_flags);
    else if (opt_method == OPT_REPLACE)
      rc= memcached_replace(memc, ptr, strlen(ptr),
			    file_buffer_ptr, (size_t)sbuf.st_size,
			    opt_expires, opt_flags);
    else
      rc= memcached_set(memc, ptr, strlen(ptr),
                        file_buffer_ptr, (size_t)sbuf.st_size,
                        opt_expires, opt_flags);

    if (rc != MEMCACHED_SUCCESS)
    {
      fprintf(stderr, "memcp: %s: memcache error %s",
	      ptr, memcached_strerror(memc, rc));
      if (memc->cached_errno)
	fprintf(stderr, " system error %s", strerror(memc->cached_errno));
      fprintf(stderr, "\n");

      return_code= -1;
    }

    free(file_buffer_ptr);
    close(fd);
    optind++;
  }

  memcached_free(memc);

  if (opt_servers)
    free(opt_servers);
  if (opt_hash)
    free(opt_hash);
  shutdown_sasl();

  return return_code;
}
Beispiel #19
0
//原型: char* memcached_get(memcached_st* ptr, const char* key, size_t keylen, size_t* valuelen, uint32_t* flags, memcached_return* error);
int32_t CVDCMemcache::MemcacheGet(memcached_st* memc, const char* szKey, const size_t keyLen, char*& szValue, size_t& valueLen)
{
	DB_MUTEX_GUARD(cf_mutex, m_dbcrit);
	memcached_return rc;
	szValue = memcached_get(memc, szKey, keyLen, &valueLen, 0, &rc);
	if(rc != MEMCACHED_SUCCESS)
	{
		WRITE_ERROR_LOG( "Error: get memcache object failed! szKey=%s, keylen=%d, szValue=%s, valuelen=%d, errorcode=%d, errordesc=%s\n", szKey, (int32_t)keyLen, szValue, (int32_t)valueLen, rc, memcached_strerror(memc, rc));
		return E_MEMCACHED_GET;
	}

	//WRITE_DEBUG_LOG( "get memcache object success! szKey=%s, keylen=%d\n", szKey, (int32_t)keyLen);

	return S_OK;
}
Beispiel #20
0
static VALUE mc_get(int argc, VALUE *argv, VALUE self) {
  memcached_st *mc;
  VALUE cas, keys, results, key, result;
  VALUE scalar_key = Qnil;
  memcached_return status;

  Data_Get_Struct(self, memcached_st, mc);
  rb_scan_args(argc, argv, "11", &keys, &cas);
  memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, RTEST(cas) ? 1 : 0);

  if (RTEST(cas) && TYPE(keys) != T_ARRAY) {
    scalar_key = keys;
    keys = rb_ary_new4(1, &keys);
  }

  if (TYPE(keys) != T_ARRAY) {
    char*    str;
    size_t   len;
    uint32_t flags;

    key = use_binary(mc) ? keys : escape_key(keys, NULL);
    str = memcached_get(mc, RSTRING_PTR(key), RSTRING_LEN(key), &len, &flags, &status);
    if (str == NULL) return Qnil;

    if (status == MEMCACHED_SUCCESS) {
      result = rb_hash_new();
      rb_hash_aset(result, sym_value, rb_str_new(str, len));
      rb_hash_aset(result, sym_flags, INT2NUM(flags));
      free(str);
      return result;
    } else {
      printf("Memcache read error: %s %u\n", memcached_strerror(mc, status), status);
      return Qnil;
    }
  } else {
    memcached_result_st* mc_result;
    size_t       num_keys, i;
    const char** key_strings;
    size_t*      key_lengths;
    bool         escaped;

    results = rb_hash_new();
    num_keys = RARRAY_LEN(keys);
    if (num_keys == 0) return results;

    key_strings = (const char**) malloc(num_keys * sizeof(char *));
    key_lengths = (size_t *) malloc(num_keys * sizeof(size_t));
    for (i = 0; i < RARRAY_LEN(keys); i++) {
      key = RARRAY_PTR(keys)[i];
      if (!use_binary(mc)) key = escape_key(key, &escaped);

      key_lengths[i] = RSTRING_LEN(key);
      key_strings[i] = RSTRING_PTR(key);
    }

    memcached_mget(mc, key_strings, key_lengths, num_keys);

    while ((mc_result = memcached_fetch_result(mc, NULL, &status))) {
      if (escaped) {
        key = unescape_key(memcached_result_key_value(mc_result), memcached_result_key_length(mc_result));
      } else {
        key = rb_str_new(memcached_result_key_value(mc_result), memcached_result_key_length(mc_result));
      }

      if (status == MEMCACHED_SUCCESS) {
        result = rb_hash_new();
        rb_hash_aset(result, sym_value, rb_str_new(memcached_result_value(mc_result),
                                                   memcached_result_length(mc_result)));
        rb_hash_aset(result, sym_flags, INT2NUM(memcached_result_flags(mc_result)));
        if (RTEST(cas)) rb_hash_aset(result, sym_cas, ULL2NUM(memcached_result_cas(mc_result)));
        memcached_result_free(mc_result);
        rb_hash_aset(results, key, result);
      } else {
        printf("Memcache read error: %s %u\n", memcached_strerror(mc, status), status);
      }
    }
    free(key_strings);
    free(key_lengths);
    if (!NIL_P(scalar_key)) return rb_hash_aref(results, scalar_key);
    return results;
  }
}
Beispiel #21
0
int32_t CVDCMemcache::MemcacheFlush(memcached_st* memc, time_t expiration)
{
	DB_MUTEX_GUARD(cf_mutex, m_dbcrit);
	memcached_return rc;
	rc = memcached_flush(memc, expiration);
	if(rc != MEMCACHED_SUCCESS)
	{
		WRITE_WARNING_LOG( "wipe clean the contents of memcached servers failed! errorcode=%d, errordesc=%s\n", rc, memcached_strerror(memc, rc));
		return E_MEMCACHE_FLUSH;
	}
	WRITE_DEBUG_LOG( "wipe clean the contents of memcached servers!\n");

	return S_OK;
}
Beispiel #22
0
/*!
 * \brief Module initialization function
 * \return 0 on success, -1 on failure
 */
static int mod_init(void) {
	char *server, *port;
	unsigned int len = 0;
	memcached_return rc;
	struct memcached_server_st *svt;

	if ((port = strchr(mcd_srv_str, ':')) != NULL) {
		port = port + 1;
		len = strlen(mcd_srv_str) - strlen(port) - 1;
	} else {
		LM_DBG("no port definition, using default port\n");
		port = "11211";
		len = strlen(mcd_srv_str) ;
	}

	server = pkg_malloc(len+1);
	if (server == NULL) {
		PKG_MEM_ERROR;
		return -1;
	}

	strncpy(server, mcd_srv_str, len);
	server[len] = '\0';

	memcached_h = memcached_create(NULL);
	if (memcached_h == NULL) {
		LM_ERR("could not create memcached structure\n");
		pkg_free(server);
		return -1;
	}
	LM_DBG("allocated new server handle at %p", memcached_h);

        if (mcd_memory == 1) {
                LM_INFO("Use internal kamailio memory manager for memcached client library\n");

#if LIBMEMCACHED_VERSION_HEX >= 0x00038000
                rc = memcached_set_memory_allocators(memcached_h, (memcached_malloc_fn)mcd_malloc,
                                             (memcached_free_fn)mcd_free, (memcached_realloc_fn)mcd_realloc,
                                             (memcached_calloc_fn)mcd_calloc, NULL);
#else
                rc = memcached_set_memory_allocators(memcached_h, (memcached_malloc_function)mcd_malloc_compat,
                                             (memcached_free_function)mcd_free_compat, (memcached_realloc_function)mcd_realloc_compat,
                                             (memcached_calloc_function)mcd_calloc_compat);
#endif

		if (rc == MEMCACHED_SUCCESS) {
			LM_DBG("memory manager callbacks set\n");
		} else {
			LM_ERR("memory manager callbacks not set, returned %s.\n", memcached_strerror(memcached_h, rc));
			pkg_free(server);
			return -1;
		}
	} else {
		LM_INFO("Use system memory manager for memcached client library\n");
	}

	svt = memcached_server_list_append(servers, server, atoi(port), &rc);
	if(svt==NULL) {
		LM_ERR("failed to append server\n");
		if(servers) {
			memcached_server_list_free(servers);
			servers = NULL;
		}
		pkg_free(server);
		return -1;
	}

	servers = svt;
	if (memcached_behavior_set(memcached_h, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, mcd_timeout) != MEMCACHED_SUCCESS) {
		LM_ERR("could not set server connection timeout\n");
		pkg_free(server);
		return -1;
	}
	rc = memcached_server_push(memcached_h, servers);
	if (rc == MEMCACHED_SUCCESS) {
		LM_DBG("added server list to structure\n");
	} else {
		LM_ERR("attempt to add server list to structure returned %s.\n", memcached_strerror(memcached_h, rc));
		pkg_free(server);
		return -1;
	}

	pkg_free(server);

	/** \todo FIXME logic to handle connection errors on startup
	memcached_server_cursor(memcached_h, (const memcached_server_fn*) &mcd_check_connection, NULL, 1);
	*/

	LM_INFO("libmemcached version is %s\n", memcached_lib_version());
	return 0;
}
Beispiel #23
0
memcached_con* memcached_new_connection(struct cachedb_id *id)
{
	memcached_con *con;
	memcached_server_st *server_list;
	memcached_return  rc;

	char *srv_list;
	int ret;

	if (id == NULL) {
		LM_ERR("null cached_id\n");
		return 0;
	}

	con = pkg_malloc(sizeof(memcached_con));
	if (con == NULL) {
		LM_ERR("no more pkg\n");
		return 0;
	}

	memset(con,0,sizeof(memcached_con));
	con->id = id;
	con->ref = 1;

	con->memc = memcached_create(NULL);

	memset(host_buff,0,MAX_HOSTPORT_SIZE);

	if (id->flags & CACHEDB_ID_MULTIPLE_HOSTS)
		srv_list = id->host;
	else {
		ret = snprintf(host_buff,MAX_HOSTPORT_SIZE,"%s:%d",id->host,id->port);
		if (ret<0 || ret>MAX_HOSTPORT_SIZE) {
			LM_ERR("failed to init con\n");
			pkg_free(con);
			return 0;
		}
		srv_list = host_buff;
	}

	server_list = memcached_servers_parse(srv_list);
	rc = memcached_server_push(con->memc,server_list);

	if( rc != MEMCACHED_SUCCESS) {
		LM_ERR("Push:%s\n",memcached_strerror(con->memc,rc));
		pkg_free(con);
		return 0;
	}


	rc = memcached_behavior_set(con->memc,
		MEMCACHED_BEHAVIOR_NO_BLOCK,1);

	if( rc != MEMCACHED_SUCCESS) {
		LM_ERR("Behavior Set:%s\n",memcached_strerror(con->memc,rc));
		pkg_free(con);
		return 0;
	}

	LM_DBG("succesfully inited memcached connection\n");
	return con;
}
Beispiel #24
0
/// Update the data for the specified namespace and key.  Writes the data
/// atomically, so if the underlying data has changed since it was last
/// read, the update is rejected and this returns Store::Status::CONTENTION.
Store::Status MemcachedStore::set_data(const std::string& table,
                                       const std::string& key,
                                       const std::string& data,
                                       uint64_t cas,
                                       int expiry,
                                       SAS::TrailId trail)
{
  Store::Status status = Store::Status::OK;

  LOG_DEBUG("Writing %d bytes to table %s key %s, CAS = %ld, expiry = %d",
            data.length(), table.c_str(), key.c_str(), cas, expiry);

  // Construct the fully qualified key.
  std::string fqkey = table + "\\\\" + key;
  const char* key_ptr = fqkey.data();
  const size_t key_len = fqkey.length();

  const std::vector<memcached_st*>& replicas = get_replicas(fqkey, Op::WRITE);

  if (trail != 0)
  {
    SAS::Event start(trail, SASEvent::MEMCACHED_SET_START, 0);
    start.add_var_param(fqkey);
    start.add_var_param(data);
    start.add_static_param(cas);
    start.add_static_param(expiry);
    SAS::report_event(start);
  }

  LOG_DEBUG("%d write replicas for key %s", replicas.size(), fqkey.c_str());

  // Calculate the rough expected expiry time.  We store this in the flags
  // as it may be useful in future for read repair function.
  uint32_t now = time(NULL);
  uint32_t exptime = now + expiry;

  // Memcached uses a flexible mechanism for specifying expiration.
  // - 0 indicates never expire.
  // - <= MEMCACHED_EXPIRATION_MAXDELTA indicates a relative (delta) time.
  // - > MEMCACHED_EXPIRATION_MAXDELTA indicates an absolute time.
  // Absolute time is the only way to force immediate expiry.  Unfortunately,
  // it's not reliable - see https://github.com/Metaswitch/cpp-common/issues/160
  // for details.  Instead, we use relative time for future times (expiry > 0)
  // and the earliest absolute time for immediate expiry (expiry == 0).
  time_t memcached_expiration =
    (time_t)((expiry > 0) ? expiry : MEMCACHED_EXPIRATION_MAXDELTA + 1);

  // First try to write the primary data record to the first responding
  // server.
  memcached_return_t rc = MEMCACHED_ERROR;
  size_t ii;
  size_t replica_idx;
  // If we only have one replica, we should try it twice -
  // libmemcached won't notice a dropped TCP connection until it tries
  // to make a request on it, and will fail the request then
  // reconnect, so the second attempt could still work.
  size_t attempts = (replicas.size() == 1) ? 2: replicas.size();

  for (ii = 0; ii < attempts; ++ii)
  {
    if ((replicas.size() == 1) && (ii == 1)) {
      if (rc != MEMCACHED_CONNECTION_FAILURE)
      {
        // This is a legitimate error, not a transient server failure, so we
        // shouldn't retry.
        break;
      }
      replica_idx = 0;
      LOG_WARNING("Failed to write to sole memcached replica: retrying once");
    }
    else
    {
      replica_idx = ii;
    }

    LOG_DEBUG("Attempt conditional write to replica %d (connection %p), CAS = %ld",
              replica_idx,
              replicas[replica_idx],
              cas);

    if (cas == 0)
    {
      // New record, so attempt to add.  This will fail if someone else
      // gets there first.
      rc = memcached_add(replicas[replica_idx],
                         key_ptr,
                         key_len,
                         data.data(),
                         data.length(),
                         memcached_expiration,
                         exptime);
    }
    else
    {
      // This is an update to an existing record, so use memcached_cas
      // to make sure it is atomic.
      rc = memcached_cas(replicas[replica_idx],
                         key_ptr,
                         key_len,
                         data.data(),
                         data.length(),
                         memcached_expiration,
                         exptime,
                         cas);

    }

    if (memcached_success(rc))
    {
      LOG_DEBUG("Conditional write succeeded to replica %d", replica_idx);
      break;
    }
    else
    {
      LOG_DEBUG("memcached_%s command for %s failed on replica %d, rc = %d (%s), expiry = %d\n%s",
                (cas == 0) ? "add" : "cas",
                fqkey.c_str(),
                replica_idx,
                rc,
                memcached_strerror(replicas[replica_idx], rc),
                expiry,
                memcached_last_error_message(replicas[replica_idx]));

      if ((rc == MEMCACHED_NOTSTORED) ||
          (rc == MEMCACHED_DATA_EXISTS))
      {
        if (trail != 0)
        {
          SAS::Event err(trail, SASEvent::MEMCACHED_SET_CONTENTION, 0);
          err.add_var_param(fqkey);
          SAS::report_event(err);
        }

        // A NOT_STORED or EXISTS response indicates a concurrent write failure,
        // so return this to the application immediately - don't go on to
        // other replicas.
        LOG_INFO("Contention writing data for %s to store", fqkey.c_str());
        status = Store::Status::DATA_CONTENTION;
        break;
      }
    }
  }

  if ((rc == MEMCACHED_SUCCESS) &&
      (replica_idx < replicas.size()))
  {
    // Write has succeeded, so write unconditionally (and asynchronously)
    // to the replicas.
    for (size_t jj = replica_idx + 1; jj < replicas.size(); ++jj)
    {
      LOG_DEBUG("Attempt unconditional write to replica %d", jj);
      memcached_behavior_set(replicas[jj], MEMCACHED_BEHAVIOR_NOREPLY, 1);
      memcached_set(replicas[jj],
                    key_ptr,
                    key_len,
                    data.data(),
                    data.length(),
                    memcached_expiration,
                    exptime);
      memcached_behavior_set(replicas[jj], MEMCACHED_BEHAVIOR_NOREPLY, 0);
    }
  }

  if ((!memcached_success(rc)) &&
      (rc != MEMCACHED_NOTSTORED) &&
      (rc != MEMCACHED_DATA_EXISTS))
  {
    if (trail != 0)
    {
      SAS::Event err(trail, SASEvent::MEMCACHED_SET_FAILED, 0);
      err.add_var_param(fqkey);
      SAS::report_event(err);
    }

    LOG_ERROR("Failed to write data for %s to %d replicas",
              fqkey.c_str(), replicas.size());
    status = Store::Status::ERROR;
  }

  return status;
}
int main()
{

	memcached_st *local_memc;
	memcached_return rc;

	local_memc = memcached_create(NULL);

	unsigned int set= 1;
	//memcached_behavior_set(local_memc, MEMCACHED_DISTRIBUTION_CONSISTENT, set);
	memcached_behavior_set(local_memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, set);
	//memcached_behavior_set(local_memc, MEMCACHED_BEHAVIOR_KETAMA, set);
	//memcached_behavior_set(local_memc, MEMCACHED_BEHAVIOR_KETAMA_HASH, set);

	rc = memcached_server_add(local_memc, "127.0.0.1", 11211);
	if(rc != MEMCACHED_SUCCESS)
	{
		fprintf(stderr, "memcached_server_add error.");
	}

	rc = memcached_server_add(local_memc, "127.0.0.1", 11212);
	if(rc != MEMCACHED_SUCCESS)
	{
		fprintf(stderr, "memcached_server_add error.");
	}

	rc = memcached_server_add(local_memc, "127.0.0.1", 11213);
	if(rc != MEMCACHED_SUCCESS)
	{
		fprintf(stderr, "memcached_server_add error.");
	}

	rc = memcached_server_add(local_memc, "127.0.0.1", 11214);
	if(rc != MEMCACHED_SUCCESS)
	{
		fprintf(stderr, "memcached_server_add error.");
	}
	rc = memcached_server_add(local_memc, "127.0.0.1", 11215);
	if(rc != MEMCACHED_SUCCESS)
	{
		fprintf(stderr, "memcached_server_add error.");
	}
	uint32_t num =  memcached_server_count(local_memc);
	printf("num:%d\n", num);


	rc= memcached_flush(local_memc, 0);
	if (!(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED))
	{
		fprintf(stderr, "memcached_flush:%d rc:%d\n", MEMCACHED_SUCCESS, rc);
		char const *retVal = memcached_strerror(NULL, rc);
		fprintf(stderr, "error memcached_flush:%s rc:%d\n", retVal, rc);
		goto ERROR;
	}

	int i = 0;
	//for(i = 0; i < 1; i++)
	for(i = 0; i < 100000; i++)
	{
		char key[64];
		char value[64];
		snprintf(key, sizeof(key), "tkey_%05d", i);
		snprintf(value, sizeof(value), "tvalue_%05d", i);
		rc= memcached_set(local_memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0);
		if (!(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED))
		{
			char const *retVal = memcached_strerror(NULL, rc);
			fprintf(stderr, "error memcached_set .%s\n", retVal);
			goto ERROR;
		}

	}
	memcached_free(local_memc);

	printf("success \n");
	return 0;
ERROR:
	printf("error \n");
	return 1;

}
Beispiel #26
0
void *pr_memcache_kget(pr_memcache_t *mcache, module *m, const char *key,
    size_t keysz, size_t *valuesz, uint32_t *flags) {
  char *data = NULL;
  void *ptr = NULL;
  memcached_return res;
  int xerrno = 0;

  if (mcache == NULL ||
      m == NULL ||
      key == NULL ||
      valuesz == NULL ||
      flags == NULL) {
    errno = EINVAL;
    return NULL;
  }

  mcache_set_module_namespace(mcache, m);
  data = memcached_get(mcache->mc, key, keysz, valuesz, flags, &res);
  xerrno = errno;
  mcache_set_module_namespace(mcache, NULL);

  if (data == NULL) {
    switch (res) {
      case MEMCACHED_NOTFOUND:
        pr_trace_msg(trace_channel, 8,
          "no data found for key (%lu bytes)", (unsigned long) keysz);
        errno = ENOENT;
        break;

      case MEMCACHED_ERRNO:
        if (errno != EINPROGRESS) {
          pr_trace_msg(trace_channel, 3,
            "no data found for key (%lu bytes): system error: %s",
            (unsigned long) keysz, strerror(xerrno));

          errno = xerrno;

        } else {
          /* We know that we're not using nonblocking IO; this value usually
           * means that libmemcached could not connect to the configured
           * memcached servers.  So set the value to something more
           * indicative, and fall through.
           */
          res = MEMCACHED_CONNECTION_FAILURE;
        }
        break;

      case MEMCACHED_SERVER_MARKED_DEAD:
      case MEMCACHED_CONNECTION_FAILURE: {
        memcached_server_instance_st server;

        server = memcached_server_get_last_disconnect(mcache->mc);
        if (server != NULL) {
          pr_trace_msg(trace_channel, 3,
            "unable to connect to %s:%d", memcached_server_name(server),
            memcached_server_port(server));
        }

        break;
      }

      default:
        pr_trace_msg(trace_channel, 6,
          "error getting data for key (%lu bytes): [%d] %s",
          (unsigned long) keysz, res, memcached_strerror(mcache->mc, res));
        errno = EPERM;
        break;
    }

    return NULL;
  }

  /* Create a duplicate of the returned data from the mcache's pool, so that
   * we can call free(3) on the data returned by libmemcached.
   */

  ptr = palloc(mcache->pool, *valuesz);
  memcpy(ptr, data, *valuesz);
  free(data);

  return ptr;
}
/**
 * @function memcached.error
 * 
 * ### Synopsis
 * var msg = memcached.error(handle, rc);
 * 
 * Get error message for last memcached error.
 * 
 * @param {object} handle - handle to memcached connection.
 * @param {int} rc - return code from the memcached that failed.
 * @return {string} msg - text of the error message.
 */
JSVAL _memcached_error (JSARGS args) {
    HandleScope scope;
    M* handle = HANDLE(args[0]);
    R rc = (R) args[1]->IntegerValue();
    return scope.Close(String::New(memcached_strerror(handle, rc)));
}