Arcus-Client

 view release on metacpan or  search on metacpan

Base.xs  view on Meta::CPAN

      warn("io_timeout argument is invalid. it is ignored.");
    }
  }

  ps = hv_fetchs(conf, "nowait", 0);
  if (ps) {
    SvGETMAGIC(*ps);
  }
  if (ps && SvOK(*ps)) {
    memcached_behavior_set(arcus->global, MEMCACHED_BEHAVIOR_NOREPLY, SvTRUE(*ps));
  }

  ps = hv_fetchs(conf, "hash_namespace", 0);
  if (ps) {
    SvGETMAGIC(*ps);
  }
  if (ps && SvOK(*ps)) {
    memcached_behavior_set(arcus->global, MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY, SvTRUE(*ps));
  }

  ps = hv_fetchs(conf, "namespace", 0);
  if (ps) {
    SvGETMAGIC(*ps);
  }
  if (ps && SvOK(*ps)) {
    STRLEN name_len;
    char *namespace = SvPV(*ps, name_len);

    if (namespace && name_len > 0) {
      memcached_set_namespace(arcus->global, namespace, name_len);
    } else if (!namespace && name_len == 0) {
      warn("namespace argument is invalid. it is ignored.");
    }
  }

  arcus->pool = memcached_pool_create(arcus->global, MIN_THREAD, arcus->max_thread);
  if (arcus->pool == NULL) {
    arcus_proxy_close(arcus->proxy);
    memcached_free(arcus->proxy);
    memcached_free(arcus->global);
    croak("failed to create the memcached pool object.");
  }

  ret = arcus_proxy_connect(arcus->global, arcus->pool, arcus->proxy);
  if (ret != ARCUS_SUCCESS) {
    arcus_pool_close(arcus->pool);
    memcached_pool_destroy(arcus->pool);
    arcus_proxy_close(arcus->proxy);
    memcached_free(arcus->proxy);
    memcached_free(arcus->global);
    croak("failed to connect to the proxy: %d (%s)", ret, arcus_strerror(ret));
  }
}

MODULE = Arcus::Base		PACKAGE = Arcus::Base

void
new(class, self)
  char *class
  SV *self
  PPCODE:
  Arcus_API *arcus = NULL;
  if (SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV) {
    EXTEND(SP, 1);
    Newx(arcus, 1, Arcus_API);
    arcus->global = memcached_create(NULL);
    if (arcus->global == NULL) {
      croak("Failed to create the global memcached object");
    }
    arcus->proxy = memcached_create(NULL);
    if (arcus->proxy == NULL) {
      croak("Failed to create the proxy memcached object");
    }
    arcus->global = memcached_create(NULL);
    arcus->cur_thread = 0;
    arcus->main_proxy = true;
    initialize_arcus_api(aTHX_ arcus, (HV *) SvRV(self));
    SV* sv = newSV(0);
    sv_setref_pv(sv, class, (void*)arcus);
    mXPUSHs(sv);
  } else {
    arcus = (Arcus_API *)SvUV(self);
  }
  arcus->cur_thread++;

void
DESTROY(arcus)
  Arcus_API *arcus
  CODE:
  arcus->cur_thread--;
  if (!arcus->cur_thread) {
    destroy_arcus_api(arcus);
  }

void
connect_proxy(arcus)
  Arcus_API *arcus
  CODE:
  arcus->cur_thread = 1;
  arcus->main_proxy = false;
  arcus->global = memcached_clone(NULL, arcus->global);
  if (arcus->global == NULL) {
    croak("Failed to create the global memcached object");
  }
  arcus->pool = memcached_pool_create(arcus->global, MIN_THREAD, arcus->max_thread);
  if (arcus->pool == NULL) {
    memcached_free(arcus->global);
    arcus->global = NULL;
    croak("Failed to create the memcached pool object");
  }
  arcus_return_t arcus_ret = arcus_proxy_connect(arcus->global, arcus->pool, arcus->proxy);
  if (arcus_ret != ARCUS_SUCCESS) {
    arcus->proxy = NULL;
    destroy_arcus_api(arcus);
    croak("Failed to connect : %d (%s)", arcus_ret, arcus_strerror(arcus_ret));
  }

SV *
cas(arcus, key, cas, value, ...)
  Arcus_API *arcus
  SV *key

Base.xs  view on Meta::CPAN

    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;
      }

      if ((req_elem = safe_av_fetch(aTHX_ req_av, idx++, 0)) == NULL ||
          (req[valid_kvs].key = SvPV(*req_elem, req[valid_kvs].key_length)) == NULL) {
        warn("key of kvs[%zu] argument is invalid.", finished + i);
        continue;
      }

      if ((req_elem = safe_av_fetch(aTHX_ req_av, idx++, 0)) == NULL ||
          (req[valid_kvs].value = SvPV(*req_elem, req[valid_kvs].value_length)) == NULL) {
        warn("value of kvs[%zu] argument is invalid.", finished + i);
        continue;
      }

      if (size > idx && (req_elem = safe_av_fetch(aTHX_ req_av, idx++, 0)) != NULL) {
        if (!SvIOK(*req_elem)) {

Base.xs  view on Meta::CPAN

        if (req_index[i] >= 0) {
          result_buf[finished + i] = newSViv(true);
        } else {
          result_buf[finished + i] = &PL_sv_undef;
        }
      }
    } else if (ret == MEMCACHED_FAILURE) {
      for (i = 0; i < consume; i++) {
        int idx = req_index[i];
        if (idx < 0) {
          result_buf[finished + i] = &PL_sv_undef;
          continue;
        }

        if (results[idx] == MEMCACHED_NOTSTORED) {
          result_buf[finished + i] = newSViv(false);
        } else {
          result_buf[finished + i] = &PL_sv_undef;
        }
      }
    } else { /* SOME ERRORS */
      for (i = 0; i < consume; i++) {
        int idx = req_index[i];
        if (idx < 0) {
          result_buf[finished + i] = &PL_sv_undef;
          continue;
        }

        if (memcached_success(results[idx])) {
          result_buf[finished + i] = newSViv(true);
        } else if (results[idx] == MEMCACHED_NOTSTORED) {
          result_buf[finished + i] = newSViv(false);
        } else {
          result_buf[finished + i] = &PL_sv_undef;
        }
      }
    }

    finished += consume;
    leftover -= consume;
  }

  EXTEND(SP, number_of_kvs);
  for (i = 0; i < number_of_kvs; i++) {
    mXPUSHs(result_buf[i]);
  }
  Safefree(result_buf);

  do_return:
  // nothing to do
  if (mc != NULL) {
    memcached_pool_push(arcus->pool, mc);
  }

void
cas_multi(arcus, ...)
  Arcus_API *arcus
  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 < 3) {
        warn("kvs[%zu] arugment is not sufficient.", finished + i);
        continue;
      }

      if ((req_elem = safe_av_fetch(aTHX_ req_av, idx++, 0)) == NULL ||
          (req[valid_kvs].key = SvPV(*req_elem, req[valid_kvs].key_length)) == NULL) {
        warn("key of kvs[%zu] argument is invalid.", finished + i);
        continue;
      }

      if ((req_elem = safe_av_fetch(aTHX_ req_av, idx++, 0)) == NULL ||
          !SvIOK(*req_elem) || (req[valid_kvs].cas = SvIV(*req_elem)) == 0) {
        warn("cas of kvs[%zu] argument is invalid.", finished + i);
        continue;
      }

      if ((req_elem = safe_av_fetch(aTHX_ req_av, idx++, 0)) == NULL ||
          (req[valid_kvs].value = SvPV(*req_elem, req[valid_kvs].value_length)) == NULL) {

Base.xs  view on Meta::CPAN

  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, ...)



( run in 2.068 seconds using v1.01-cache-2.11-cpan-71847e10f99 )