Arcus-Client

 view release on metacpan or  search on metacpan

Base.xs  view on Meta::CPAN

  int arg = 4;
  CODE:
  RETVAL = NULL;
  memcached_return_t ret;
  STRLEN key_length, value_length;
  char *key_ptr = NULL;
  uint64_t cas_value = 0;
  char *value_ptr = NULL;
  SV *sv;

  memcached_st *mc = memcached_pool_pop(arcus->pool, true, &ret);
  if (mc == NULL) {
    warn("Failed to create the memcached object : %d (%s)", ret, memcached_strerror(NULL, ret));
    goto do_return;
  }

  if (!SvOK(key) || (key_ptr = SvPV(key, key_length)) == NULL) {
    warn("key argument is invalid.");
    goto do_return;
  }
  if (!SvIOK(cas) || (cas_value = SvIV(cas)) == 0) {
    warn("cas argument is invalid.");
    goto do_return;
  }
  if (!SvOK(value) || (value_ptr = SvPV(value, value_length)) == NULL) {
    warn("value argument is invalid.");
    goto do_return;
  }

  if (items > arg && (sv = safe_sv(aTHX_ ST(arg++))) != NULL) {
    if (!SvIOK(sv)) {
      warn("exptime argument is invalid.");
      goto do_return;
    }
    exptime = (time_t) SvIV(sv);
  }
  if (items > arg && (sv = safe_sv(aTHX_ ST(arg++))) != NULL) {
    if (!SvIOK(sv)) {
      warn("flags argument is invalid.");
      goto do_return;
    }
    flags = (int) SvIV(sv);
  }

  ret = memcached_cas(mc, key_ptr, key_length, value_ptr, value_length, exptime, flags, cas_value);
  if (memcached_success(ret)) {
    RETVAL = newSViv(true);
  } else if (ret == MEMCACHED_DATA_EXISTS || ret == MEMCACHED_NOTFOUND) {
    RETVAL = newSViv(false);
  } else {
    warn("failed to memcached_cas: %d (%s)", ret, memcached_strerror(mc, ret));
  }

  do_return:
  if (mc != NULL) {
    memcached_pool_push(arcus->pool, mc);
  }
  if (RETVAL == NULL) {
    RETVAL = &PL_sv_undef;
  }
OUTPUT:
RETVAL

SV *
set(arcus, key, value, ...)
  Arcus_API *arcus
  SV *key
  SV *value
  ALIAS:
  set     = ARCUS_SET
  add     = ARCUS_ADD
  replace = ARCUS_REPLACE
  append  = ARCUS_APPEND
  prepend = ARCUS_PREPEND
  PREINIT:
  time_t exptime = 0;
  int flags = 0;
  int arg = 3;
  CODE:
  RETVAL = NULL;
  memcached_return_t ret;
  STRLEN key_length, value_length;
  char *key_ptr = NULL;
  char *value_ptr = NULL;
  SV *sv;

  memcached_st *mc = memcached_pool_pop(arcus->pool, true, &ret);
  if (mc == NULL) {
    warn("Failed to create the memcached object : %d (%s)", ret, memcached_strerror(NULL, ret));
    goto do_return;
  }

  if (!SvOK(key) || (key_ptr = SvPV(key, key_length)) == NULL) {
    warn("key argument is invalid.");
    goto do_return;
  }
  if (!SvOK(value) || (value_ptr = SvPV(value, value_length)) == NULL) {
    warn("value argument is invalid.");
    goto do_return;
  }

  if (items > arg && (sv = safe_sv(aTHX_ ST(arg++))) != NULL) {
    if (!SvIOK(sv)) {
      warn("exptime argument is invalid.");
      goto do_return;
    }
    exptime = (time_t) SvIV(sv);
  }
  if (items > arg && (sv = safe_sv(aTHX_ ST(arg++))) != NULL) {
    if (!SvIOK(sv)) {
      warn("flags argument is invalid.");
      goto do_return;
    }
    flags = (int) SvIV(sv);
  }

  switch (ix) {
    case ARCUS_SET:
      ret = memcached_set(mc, key_ptr, key_length, value_ptr, value_length, exptime, flags);
      break;
    case ARCUS_ADD:
      ret = memcached_add(mc, key_ptr, key_length, value_ptr, value_length, exptime, flags);
      break;
    case ARCUS_REPLACE:
      ret = memcached_replace(mc, key_ptr, key_length, value_ptr, value_length, exptime, flags);
      break;
    case ARCUS_APPEND:
      ret = memcached_append(mc, key_ptr, key_length, value_ptr, value_length, exptime, flags);
      break;
    case ARCUS_PREPEND:
      ret = memcached_prepend(mc, key_ptr, key_length, value_ptr, value_length, exptime, flags);
      break;
    default:
      ret = MEMCACHED_FAILURE;
      break;
  }
  if (memcached_success(ret)) {
    RETVAL = newSViv(true);
  } else if (ret == MEMCACHED_NOTSTORED) {
    RETVAL = newSViv(false);
  } else {
    warn("failed to memcached_%s: %d (%s)", ARCUS_OP_NAME[ix], ret, memcached_strerror(mc, ret));
  }

  do_return:
  if (mc != NULL) {
    memcached_pool_push(arcus->pool, mc);
  }
  if (RETVAL == NULL) {
    RETVAL = &PL_sv_undef;
  }
OUTPUT:
RETVAL

void
set_multi(arcus, ...)
  Arcus_API *arcus
  ALIAS:
  set_multi     = ARCUS_SET
  add_multi     = ARCUS_ADD
  replace_multi = ARCUS_REPLACE
  append_multi  = ARCUS_APPEND
  prepend_multi = ARCUS_PREPEND
  PREINIT:
  size_t finished = 0;
  size_t arg = 1;
  PPCODE:
  memcached_return_t ret;
  memcached_storage_request_st req[MAX_KEYS_FOR_MULTI_STORE_OPERATION];
  memcached_return_t results[MAX_KEYS_FOR_MULTI_STORE_OPERATION];
  int req_index[MAX_KEYS_FOR_MULTI_STORE_OPERATION];
  SV **result_buf;

  memcached_st *mc = memcached_pool_pop(arcus->pool, true, &ret);
  if (mc == NULL) {
    warn("Failed to create the memcached object : %d (%s)", ret, memcached_strerror(NULL, ret));
    goto do_return;
  }

  size_t number_of_kvs = items - arg;
  if (number_of_kvs == 0) {
    warn("kvs argument is empty.");
    goto do_return;
  }

  size_t leftover = number_of_kvs;
  Newx(result_buf, number_of_kvs, SV *);

  SV *req_sv, **req_elem;
  size_t i, consume, valid_kvs;

  while (leftover > 0) {
    valid_kvs = 0;
    consume = leftover < MAX_KEYS_FOR_MULTI_STORE_OPERATION
            ? leftover : MAX_KEYS_FOR_MULTI_STORE_OPERATION;

    for (i = 0; i < consume; i++) {
      req_index[i] = -1;
      req_sv = safe_sv(aTHX_ ST(arg++));

      if (req_sv == NULL || !SvROK(req_sv) || SvTYPE(SvRV(req_sv)) != SVt_PVAV) {
        warn("kvs[%zu] arugment is not array reference.", finished + i);
        continue;
      }

      AV *req_av = (AV *) SvRV(req_sv);
      size_t idx = 0, size = av_count(req_av);

      if (size < 2) {
        warn("kvs[%zu] arugment is not sufficient.", finished + i);
        continue;
      }

Base.xs  view on Meta::CPAN

  decr    = ARCUS_DECR
  PROTOTYPE: $@
  PREINIT:
  int offset = 1;
  int arg = 2;
  CODE:
  RETVAL = NULL;
  memcached_return_t ret;
  char *key_ptr;
  size_t key_length;
  uint64_t value;

  memcached_st *mc = memcached_pool_pop(arcus->pool, true, &ret);
  if (mc == NULL) {
    warn("Failed to create the memcached object : %d (%s)", ret, memcached_strerror(NULL, ret));
    goto do_return;
  }

  if (!SvOK(key) || (key_ptr = SvPV(key, key_length)) == NULL) {
    warn("key argument is invalid.");
    goto do_return;
  }

  SV *sv;
  if (items > arg && (sv = safe_sv(aTHX_ ST(arg++))) != NULL) {
    if (!SvIOK(sv)) {
      warn("offset argument is invalid.");
      goto do_return;
    }
    offset = (int) SvIV(sv);
  }

  switch(ix) {
    case ARCUS_INCR:
      ret = memcached_increment(mc, key_ptr, key_length, offset, &value);
      break;
    case ARCUS_DECR:
      ret = memcached_decrement(mc, key_ptr, key_length, offset, &value);
      break;
    default:
      ret = MEMCACHED_FAILURE;
      break;
  }
  if (memcached_success(ret)) {
    if (value) {
      RETVAL = newSViv(value);
    } else {
      RETVAL = newSVpv("0E0", 0);
    }
  } else if (ret != MEMCACHED_NOTFOUND) {
    warn("failed to memcached_%s: %d (%s)", ARCUS_OP_NAME[ix], ret, memcached_strerror(mc, ret));
  }

  do_return:
  if (mc != NULL) {
    memcached_pool_push(arcus->pool, mc);
  }
  if (RETVAL == NULL) {
    RETVAL = &PL_sv_undef;
  }
OUTPUT:
RETVAL

void
get(arcus, key)
  Arcus_API *arcus
  SV *key
  ALIAS:
  get    = ARCUS_GET
  gets   = ARCUS_GETS
  PPCODE:
  memcached_return_t ret;
  size_t key_length = 0;
  char *key_ptr = NULL;
  size_t value_length;
  char *value;
  uint32_t flags;
  bool is_gets = false;
  bool do_free_value = true;

  dSP;
  PUSHMARK(SP);

  memcached_st *mc = memcached_pool_pop(arcus->pool, true, &ret);
  if (mc == NULL) {
    warn("Failed to create the memcached object : %d (%s)", ret, memcached_strerror(NULL, ret));
    goto do_return;
  }

  if (!SvOK(key) || (key_ptr = SvPV(key, key_length)) == NULL) {
    warn("key argument is invalid.");
    goto do_return;
  }

  if ((is_gets = (ix == ARCUS_GETS))) {
    memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, true);
  }

  value = memcached_get(mc, key_ptr, key_length, &value_length, &flags, &ret);
  if (memcached_success(ret) && value_length == 0 && value == NULL) {
    do_free_value = false;
    value = "";
  }

  if (value != NULL) {
    if (is_gets) {
      mXPUSHs(newSViv(((memcached_st *) mc)->result.item_cas));
    }
    mXPUSHs(newSVpv(value, value_length));
    mXPUSHs(newSViv(flags));

    if (do_free_value) {
      free(value);
    }
  } else if (ret != MEMCACHED_NOTFOUND) {
    warn("failed to memcached_get: %d (%s), value == NULL: %d",
         ret, memcached_strerror(mc, ret), value == NULL);
  }

  if (is_gets) {
    memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, false);
  }

  do_return:
  if (mc != NULL) {
    memcached_pool_push(arcus->pool, mc);
  }
  PUTBACK;

HV *
get_multi(arcus, ...)
  Arcus_API *arcus
  ALIAS:
  get_multi    = ARCUS_GET
  gets_multi   = ARCUS_GETS
  PREINIT:
  size_t arg = 1;
  size_t i = 0;
  size_t valid_keys = 0;
  bool is_gets = false;
  CODE:
  memcached_return_t ret;
  char **keys_ptr = NULL;
  size_t *keys_length = NULL;
  SV *sv;

  RETVAL = newHV();
  memcached_st *mc = memcached_pool_pop(arcus->pool, true, &ret);
  if (mc == NULL) {
    warn("Failed to create the memcached object : %d (%s)", ret, memcached_strerror(NULL, ret));
    goto do_return;
  }

  size_t number_of_keys = items - arg;
  if (number_of_keys == 0) {
    warn("keys argument is empty.");
    goto do_return;
  }

  Newx(keys_ptr, number_of_keys, char *);
  Newx(keys_length, number_of_keys, size_t);

  for (i = 0; i < number_of_keys; i++) {
    if ((sv = safe_sv(aTHX_ ST(arg++))) != NULL) {
      keys_ptr[valid_keys] = SvPV(sv, keys_length[valid_keys]);
    } else {
      keys_ptr[valid_keys] = NULL;
    }

    if (keys_ptr[valid_keys] == NULL || keys_length[valid_keys] == 0) {
      warn("keys[%zu] argument is invalid.", i);
    } else {
      valid_keys++;
    }
  }

  if ((is_gets = (ix == ARCUS_GETS))) {
    memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, true);
  }

  ret = memcached_mget(mc, (const char * const *) keys_ptr, keys_length, valid_keys);
  if (memcached_failed(ret) && ret != MEMCACHED_SOME_ERRORS) {
    warn("failed to mget: %d (%s)\n", ret, memcached_strerror(mc, ret));
    goto do_return;
  }

  while (true) {
    size_t key_len, value_len;
    char key[MEMCACHED_MAX_KEY];
    uint32_t flags = 0;
    char *value = memcached_fetch(mc, key, &key_len, &value_len, &flags, &ret);
    bool do_free_value = true;

    if (ret == MEMCACHED_END) {
      break;
    }
    if (memcached_success(ret) && value_len == 0 && value == NULL) {
      do_free_value = false;
      value = "";
    }

    if (value == NULL || memcached_failed(ret)) {
      warn("failed to fetch: %d (%s), value == NULL: %d", ret, memcached_strerror(mc, ret), value == NULL);
      break;
    }

    AV *arr = newAV();
    if (is_gets) {
      av_push(arr, newSViv(((memcached_st *) mc)->result.item_cas));
    }
    av_push(arr, newSVpv(value, value_len));
    av_push(arr, newSViv(flags));
    hv_store(RETVAL, key, key_len, newRV_noinc((SV *) arr), 0);

    if (do_free_value) {
      free(value);
    }
    value = NULL;
  }

  do_return:
  if (is_gets) {
    memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, false);
  }
  if (mc != NULL) {
    memcached_pool_push(arcus->pool, mc);
  }
  if (keys_ptr != NULL) {
    Safefree(keys_ptr);
  }
  if (keys_length != NULL) {
    Safefree(keys_length);
  }
OUTPUT:
RETVAL

SV *
delete(arcus, key)
  Arcus_API *arcus
  SV *key
  CODE:
  memcached_return_t ret;
  RETVAL = NULL;
  STRLEN key_length;
  char *key_ptr = NULL;

  memcached_st *mc = memcached_pool_pop(arcus->pool, true, &ret);
  if (mc == NULL) {
    warn("Failed to create the memcached object : %d (%s)", ret, memcached_strerror(NULL, ret));
    goto do_return;
  }

  if (!SvOK(key) || (key_ptr = SvPV(key, key_length)) == NULL) {
    warn("key argument is invalid.");
    goto do_return;
  }

  ret = memcached_delete(mc, key_ptr, key_length, 0);
  RETVAL = newSViv(memcached_success(ret));

  do_return:
  if (mc != NULL) {
    memcached_pool_push(arcus->pool, mc);
  }
  if (RETVAL == NULL) {
    RETVAL = &PL_sv_undef;
  }
OUTPUT:
RETVAL

SV *
flush_all(arcus, ...)
  Arcus_API *arcus
  PREINIT:
  time_t exptime = 0;
  int arg = 1;
  CODE:
  memcached_return_t ret;
  SV *sv = NULL;

  RETVAL = NULL;
  memcached_st *mc = memcached_pool_pop(arcus->pool, true, &ret);
  if (mc == NULL) {
    warn("Failed to create the memcached object : %d (%s)", ret, memcached_strerror(NULL, ret));
    goto do_return;
  }

  if (items > arg && (sv = safe_sv(aTHX_ ST(arg++))) != NULL) {
    if (!SvIOK(sv)) {
      warn("exptime argument is invalid.");
      goto do_return;
    }
    exptime = (time_t) SvIV(sv);
  }

  ret = memcached_flush(mc, exptime);
  RETVAL = newSViv(memcached_success(ret));

  do_return:
  if (mc != NULL) {
    memcached_pool_push(arcus->pool, mc);
  }
  if (RETVAL == NULL) {
    RETVAL = &PL_sv_undef;
  }
OUTPUT:
RETVAL

HV *
server_versions(arcus)
  Arcus_API *arcus
  CODE:
  memcached_return_t ret;
  RETVAL = newHV();
  int i;

  memcached_st *mc = arcus->global;
  if (mc == NULL) {
    warn("invalid mc.");
    goto do_return;
  }

  ret = memcached_version(mc);
  if (memcached_failed(ret)) {
    warn("failed to memcached_version: %d (%s)", ret, memcached_strerror(mc, ret));
    goto do_return;
  }

  for (i = 0; i < memcached_server_count(mc); i++) {
    memcached_server_instance_st server = memcached_server_instance_by_position(mc, i);
    SV *host = newSVpvf("%s:%d", server->hostname, server->port);
    SV *version = newSVpvf("%d.%d.%d", server->major_version,
                                       server->minor_version,
                                       server->micro_version);

    hv_store(RETVAL, SvPV_nolen(host), SvCUR(host), version, 0);
  }

  do_return:
  sv_2mortal((SV *) RETVAL);
OUTPUT:
RETVAL



( run in 1.311 second using v1.01-cache-2.11-cpan-39bf76dae61 )