Added Memcached::setBucket

This commit is contained in:
Mikko
2013-11-18 02:14:35 +08:00
parent 6d19890072
commit 80253e82c4
4 changed files with 150 additions and 89 deletions

View File

@@ -253,7 +253,7 @@ class Memcached {
public function setOptions( array $options ) {}
public function setBucket( array $host_map, array $forward_map, $buckets, $replicas ) {}
public function setBucket( array $host_map, array $forward_map, $replicas ) {}
public function addServer( $host, $port, $weight = 0 ) {}
@@ -285,7 +285,7 @@ class Memcached {
public function isPristine( ) {}
public function setSaslAuthData( $username, $password ) {}
public function setSaslAuthData( $username, $password ) {}
}

View File

@@ -116,6 +116,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
<file role='test' name='types.phpt'/>
<file role='test' name='types_multi.phpt'/>
<file role='test' name='undefined_set.phpt'/>
<file role='test' name='vbucket.phpt'/>
<file role='test' name='testdata.res'/>
</dir>
</dir>

View File

@@ -2522,100 +2522,115 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML
return 1;
}
/* {{{ Memcached::setBucket(array host_map, array forward_map, long buckets, long replicas)
static
uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements TSRMLS_DC)
{
zval **ppzval;
uint32_t *retval;
size_t i = 0;
*num_elements = zend_hash_num_elements(Z_ARRVAL_P(input));
if (!*num_elements) {
return NULL;
}
retval = ecalloc(*num_elements, sizeof(uint32_t));
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(input));
zend_hash_get_current_data(Z_ARRVAL_P(input), (void **) &ppzval) == SUCCESS;
zend_hash_move_forward(Z_ARRVAL_P(input)), i++) {
long value = 0;
if (Z_TYPE_PP(ppzval) == IS_LONG) {
value = Z_LVAL_PP(ppzval);
}
else {
zval tmp_zval, *tmp_pzval;
tmp_zval = **ppzval;
zval_copy_ctor(&tmp_zval);
tmp_pzval = &tmp_zval;
convert_to_long(tmp_pzval);
value = (Z_LVAL_P(tmp_pzval) > 0) ? Z_LVAL_P(tmp_pzval) : 0;
zval_dtor(tmp_pzval);
}
if (value < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "the map must contain positive integers");
efree (retval);
*num_elements = 0;
return NULL;
}
retval [i] = (uint32_t) value;
}
return retval;
}
/* {{{ Memcached::setBucket(array host_map, array forward_map, integer replicas)
Sets the memcached virtual buckets */
PHP_METHOD(Memcached, setBucket)
{
zval *host_map;
zval *forward_map;
long buckets;
long replicas;
uint32_t *hm = NULL,*fm = NULL;
zend_bool ok = 1;
uint key_len;
char *key;
ulong key_index;
zval **value;
zval *zserver_map;
zval *zforward_map = NULL;
long replicas = 0;
zend_bool retval = 1;
uint32_t *server_map = NULL, *forward_map = NULL;
size_t server_map_len = 0, forward_map_len = 0;
memcached_return rc;
MEMC_METHOD_INIT_VARS;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa!ll", &host_map, &forward_map, &buckets, &replicas) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa!l", &zserver_map, &zforward_map, &replicas) == FAILURE) {
return;
}
hm = (uint32_t*)malloc(buckets * sizeof(uint32_t));
int i = 0;
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(host_map));
zend_hash_get_current_data(Z_ARRVAL_P(host_map), (void *) &value) == SUCCESS;
zend_hash_move_forward(Z_ARRVAL_P(host_map))) {
if (i < buckets) {
if (zend_hash_get_current_key_ex(Z_ARRVAL_P(host_map), &key, &key_len, &key_index, 0, NULL) == HASH_KEY_IS_LONG) {
zval copy = **value;
zval_copy_ctor(&copy);
INIT_PZVAL(&copy);
convert_to_long(&copy);
hm[i] = Z_LVAL_P(&copy);
++i;
zval_dtor(&copy);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid configuration option");
ok = 0;
}
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "array size mismatch");
ok = 0;
break;
}
}
if (i != buckets) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "array size mismatch");
ok = 0;
}
i = 0;
if (ok != 0 && forward_map != NULL) {
fm = (uint32_t*)malloc(buckets * sizeof(uint32_t));
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(forward_map));
zend_hash_get_current_data(Z_ARRVAL_P(forward_map), (void *) &value) == SUCCESS;
zend_hash_move_forward(Z_ARRVAL_P(forward_map))) {
if (i < buckets) {
if (zend_hash_get_current_key_ex(Z_ARRVAL_P(forward_map), &key, &key_len, &key_index, 0, NULL) == HASH_KEY_IS_LONG) {
zval copy = **value;
zval_copy_ctor(&copy);
INIT_PZVAL(&copy);
convert_to_long(&copy);
fm[i] = Z_LVAL_P(&copy);
++i;
zval_dtor(&copy);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid configuration option");
ok = 0;
}
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "array size mismatch");
ok = 0;
}
}
}
MEMC_METHOD_FETCH_OBJECT;
if (memcached_bucket_set(m_obj->memc, hm, fm, buckets, replicas) != MEMCACHED_SUCCESS)
{
ok = 0;
php_error_docref(NULL TSRMLS_CC, E_WARNING,"memcached_bucket_set don't returned MEMCACHED_SUCCESS");
if (zend_hash_num_elements (Z_ARRVAL_P(zserver_map)) == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "server map cannot be empty");
RETURN_FALSE;
}
free(hm);
free(fm);
RETURN_BOOL(ok);
if (zforward_map && zend_hash_num_elements (Z_ARRVAL_P(zserver_map)) != zend_hash_num_elements (Z_ARRVAL_P(zforward_map))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "forward_map length must match the server_map length");
RETURN_FALSE;
}
if (replicas < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "replicas must be larger than zero");
RETURN_FALSE;
}
server_map = s_zval_to_uint32_array (zserver_map, &server_map_len TSRMLS_CC);
if (!server_map) {
RETURN_FALSE;
}
if (zforward_map) {
forward_map = s_zval_to_uint32_array (zforward_map, &forward_map_len TSRMLS_CC);
if (!forward_map) {
efree (server_map);
RETURN_FALSE;
}
}
rc = memcached_bucket_set (m_obj->memc, server_map, forward_map, (uint32_t) server_map_len, replicas);
if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) {
retval = 0;;
}
efree(server_map);
if (forward_map) {
efree(forward_map);
}
RETURN_BOOL(retval);
}
/* }}} */
@@ -3869,10 +3884,9 @@ ZEND_BEGIN_ARG_INFO(arginfo_setOptions, 0)
ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_setBucket, 0)
ZEND_BEGIN_ARG_INFO(arginfo_setBucket, 3)
ZEND_ARG_INFO(0, host_map)
ZEND_ARG_INFO(0, forward_map)
ZEND_ARG_INFO(0, buckets)
ZEND_ARG_INFO(0, replicas)
ZEND_END_ARG_INFO()
@@ -3963,7 +3977,7 @@ static zend_function_entry memcached_class_methods[] = {
MEMC_ME(getOption, arginfo_getOption)
MEMC_ME(setOption, arginfo_setOption)
MEMC_ME(setOptions, arginfo_setOptions)
MEMC_ME(setBucket, arginfo_setBucket)
MEMC_ME(setBucket, arginfo_setBucket)
#ifdef HAVE_MEMCACHED_SASL
MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData)
#endif

46
tests/vbucket.phpt Normal file
View File

@@ -0,0 +1,46 @@
--TEST--
Memcached virtual buckets
--SKIPIF--
<?php if (!extension_loaded("memcached")) print "skip"; ?>
--FILE--
<?php
$m = new Memcached();
var_dump ($m->setOption (Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_VIRTUAL_BUCKET));
$m->addServer('127.0.0.1', 11211, 1);
var_dump ($m->setBucket (array (1, 2, 3), null, 2));
var_dump ($m->setBucket (array (1,2,2), array (1,2,2), 2));
var_dump ($m->setBucket (array ('a', 'b', 'c'), null, 2));
var_dump ($m->setBucket (array (), null, 2));
var_dump ($m->setBucket (array (), array (), -1));
var_dump ($m->setBucket (null, array (), -1));
var_dump ($m->setBucket (array (-1), array (-1), 1));
echo "OK\n";
?>
--EXPECTF--
bool(true)
bool(true)
bool(true)
bool(true)
Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d
bool(false)
Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d
bool(false)
Warning: Memcached::setBucket() expects parameter 1 to be array, null given in %s on line %d
NULL
Warning: Memcached::setBucket(): the map must contain positive integers in %s on line %d
bool(false)
OK