Arcus-Client
view release on metacpan or search on metacpan
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
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)) {
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) {
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 )