Skip to content

Commit 9a48162

Browse files
committed
Fix memcached_server_list() problem.
1 parent 011afc7 commit 9a48162

File tree

1 file changed

+112
-81
lines changed

1 file changed

+112
-81
lines changed

php_memcached.c

Lines changed: 112 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,16 @@ static int le_memc;
157157

158158
static zend_class_entry *memcached_ce = NULL;
159159
static zend_class_entry *memcached_exception_ce = NULL;
160+
161+
static struct callbackContext
162+
{
163+
zval *array;
164+
zval *entry;
165+
memcached_stat_st *stats; /* for use with functions that need stats */
166+
void *return_value;
167+
unsigned int i; /* for use with structures mapped against servers */
168+
};
169+
160170
static zend_class_entry *spl_ce_RuntimeException = NULL;
161171

162172
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3)
@@ -190,6 +200,9 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool incr);
190200
static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key);
191201
static memcached_return php_memc_do_cache_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char *key, size_t key_len, zval *value TSRMLS_DC);
192202
static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result TSRMLS_DC);
203+
static memcached_return php_memc_do_serverlist_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context);
204+
static memcached_return php_memc_do_stats_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context);
205+
static memcached_return php_memc_do_version_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context);
193206

194207

195208
/****************************************
@@ -1447,7 +1460,7 @@ PHP_METHOD(Memcached, addServers)
14471460
}
14481461

14491462
list = memcached_server_list_append_with_weight(list, Z_STRVAL_PP(z_host),
1450-
Z_LVAL_PP(z_port), weight, &status);
1463+
Z_LVAL_PP(z_port), weight, &status);
14511464

14521465
if (php_memc_handle_error(status TSRMLS_CC) == 0) {
14531466
continue;
@@ -1468,13 +1481,14 @@ PHP_METHOD(Memcached, addServers)
14681481
}
14691482
/* }}} */
14701483

1484+
14711485
/* {{{ Memcached::getServerList()
14721486
Returns the list of the memcache servers in use */
14731487
PHP_METHOD(Memcached, getServerList)
14741488
{
1475-
memcached_server_st *servers;
1476-
unsigned int i, servers_count;
14771489
zval *array;
1490+
struct callbackContext context = {0};
1491+
memcached_server_function callbacks[1];
14781492
MEMC_METHOD_INIT_VARS;
14791493

14801494
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
@@ -1483,21 +1497,11 @@ PHP_METHOD(Memcached, getServerList)
14831497

14841498
MEMC_METHOD_FETCH_OBJECT;
14851499

1500+
callbacks[0] = php_memc_do_serverlist_callback;
14861501
array_init(return_value);
1487-
servers = memcached_server_list(i_obj->memc);
1488-
servers_count = memcached_server_count(i_obj->memc);
1489-
if (servers == NULL) {
1490-
return;
1491-
}
1492-
1493-
for (i = 0; i < servers_count; i++) {
1494-
MAKE_STD_ZVAL(array);
1495-
array_init(array);
1496-
add_assoc_string(array, "host", servers[i].hostname, 1);
1497-
add_assoc_long(array, "port", servers[i].port);
1498-
add_assoc_long(array, "weight", servers[i].weight);
1499-
add_next_index_zval(return_value, array);
1500-
}
1502+
context.array = array;
1503+
context.return_value = return_value;
1504+
memcached_server_cursor(i_obj->memc, callbacks, &context, 1);
15011505
}
15021506
/* }}} */
15031507

@@ -1541,13 +1545,12 @@ PHP_METHOD(Memcached, getServerByKey)
15411545
Returns statistics for the memcache servers */
15421546
PHP_METHOD(Memcached, getStats)
15431547
{
1544-
memcached_stat_st *stats;
1548+
memcached_stat_st *stats;
15451549
memcached_server_st *servers;
1546-
unsigned int i, servers_count;
15471550
memcached_return status;
1548-
char *hostport = NULL;
1549-
int hostport_len;
15501551
zval *entry;
1552+
struct callbackContext context = {0};
1553+
memcached_server_function callbacks[1];
15511554
MEMC_METHOD_INIT_VARS;
15521555

15531556
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
@@ -1562,46 +1565,13 @@ PHP_METHOD(Memcached, getStats)
15621565
}
15631566

15641567
array_init(return_value);
1565-
servers = memcached_server_list(i_obj->memc);
1566-
servers_count = memcached_server_count(i_obj->memc);
1567-
if (servers == NULL) {
1568-
return;
1569-
}
15701568

1571-
for (i = 0; i < servers_count; i++) {
1572-
hostport_len = spprintf(&hostport, 0, "%s:%d", servers[i].hostname, servers[i].port);
1573-
1574-
MAKE_STD_ZVAL(entry);
1575-
array_init(entry);
1576-
1577-
add_assoc_long(entry, "pid", stats[i].pid);
1578-
add_assoc_long(entry, "uptime", stats[i].uptime);
1579-
add_assoc_long(entry, "threads", stats[i].threads);
1580-
add_assoc_long(entry, "time", stats[i].time);
1581-
add_assoc_long(entry, "pointer_size", stats[i].pointer_size);
1582-
add_assoc_long(entry, "rusage_user_seconds", stats[i].rusage_user_seconds);
1583-
add_assoc_long(entry, "rusage_user_microseconds", stats[i].rusage_user_microseconds);
1584-
add_assoc_long(entry, "rusage_system_seconds", stats[i].rusage_system_seconds);
1585-
add_assoc_long(entry, "rusage_system_microseconds", stats[i].rusage_system_microseconds);
1586-
add_assoc_long(entry, "curr_items", stats[i].curr_items);
1587-
add_assoc_long(entry, "total_items", stats[i].total_items);
1588-
add_assoc_long(entry, "limit_maxbytes", stats[i].limit_maxbytes);
1589-
add_assoc_long(entry, "curr_connections", stats[i].curr_connections);
1590-
add_assoc_long(entry, "total_connections", stats[i].total_connections);
1591-
add_assoc_long(entry, "connection_structures", stats[i].connection_structures);
1592-
add_assoc_long(entry, "bytes", stats[i].bytes);
1593-
add_assoc_long(entry, "cmd_get", stats[i].cmd_get);
1594-
add_assoc_long(entry, "cmd_set", stats[i].cmd_set);
1595-
add_assoc_long(entry, "get_hits", stats[i].get_hits);
1596-
add_assoc_long(entry, "get_misses", stats[i].get_misses);
1597-
add_assoc_long(entry, "evictions", stats[i].evictions);
1598-
add_assoc_long(entry, "bytes_read", stats[i].bytes_read);
1599-
add_assoc_long(entry, "bytes_written", stats[i].bytes_written);
1600-
add_assoc_stringl(entry, "version", stats[i].version, strlen(stats[i].version), 1);
1601-
1602-
add_assoc_zval_ex(return_value, hostport, hostport_len+1, entry);
1603-
efree(hostport);
1604-
}
1569+
callbacks[0] = php_memc_do_stats_callback;
1570+
context.i = 0;
1571+
context.entry = entry;
1572+
context.stats = stats;
1573+
context.return_value = return_value;
1574+
memcached_server_cursor(i_obj->memc, callbacks, &context, 1);
16051575

16061576
memcached_stat_free(i_obj->memc, stats);
16071577
}
@@ -1612,11 +1582,9 @@ PHP_METHOD(Memcached, getStats)
16121582
PHP_METHOD(Memcached, getVersion)
16131583
{
16141584
memcached_server_st *servers;
1615-
unsigned int i, servers_count;
1616-
char *hostport = NULL;
1617-
char version[16];
1618-
int hostport_len, version_len;
16191585
memcached_return status = MEMCACHED_SUCCESS;
1586+
struct callbackContext context = {0};
1587+
memcached_server_function callbacks[1];
16201588
MEMC_METHOD_INIT_VARS;
16211589

16221590
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
@@ -1626,27 +1594,17 @@ PHP_METHOD(Memcached, getVersion)
16261594
MEMC_METHOD_FETCH_OBJECT;
16271595

16281596
array_init(return_value);
1629-
servers = memcached_server_list(i_obj->memc);
1630-
servers_count = memcached_server_count(i_obj->memc);
1631-
if (servers == NULL) {
1632-
return;
1633-
}
16341597

16351598
status = memcached_version(i_obj->memc);
16361599
if (php_memc_handle_error(status TSRMLS_CC) < 0) {
16371600
zval_dtor(return_value);
16381601
RETURN_FALSE;
16391602
}
16401603

1641-
for (i = 0; i < servers_count; i++) {
1642-
hostport_len = spprintf(&hostport, 0, "%s:%d", servers[i].hostname, servers[i].port);
1643-
version_len = snprintf(version, sizeof(version), "%d.%d.%d",
1644-
servers[i].major_version, servers[i].minor_version,
1645-
servers[i].micro_version);
1604+
callbacks[0] = php_memc_do_version_callback;
1605+
context.return_value = return_value;
16461606

1647-
add_assoc_stringl_ex(return_value, hostport, hostport_len+1, version, version_len, 1);
1648-
efree(hostport);
1649-
}
1607+
memcached_server_cursor(i_obj->memc, callbacks, &context, 1);
16501608
}
16511609
/* }}} */
16521610

@@ -1925,6 +1883,79 @@ ZEND_RSRC_DTOR_FUNC(php_memc_dtor)
19251883
/* }}} */
19261884

19271885
/* {{{ internal API functions */
1886+
static memcached_return php_memc_do_serverlist_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context)
1887+
{
1888+
struct callbackContext* context = (struct callbackContext*) in_context;
1889+
1890+
MAKE_STD_ZVAL(context->array);
1891+
array_init(context->array);
1892+
add_assoc_string(context->array, "host", instance->hostname, 1);
1893+
add_assoc_long(context->array, "port", instance->port);
1894+
add_assoc_long(context->array, "weight", instance->weight);
1895+
add_next_index_zval(context->return_value, context->array);
1896+
return MEMCACHED_SUCCESS;
1897+
}
1898+
1899+
static memcached_return php_memc_do_stats_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context)
1900+
{
1901+
char *hostport = NULL;
1902+
int hostport_len;
1903+
struct callbackContext* context = (struct callbackContext*) in_context;
1904+
hostport_len = spprintf(&hostport, 0, "%s:%d", instance->hostname, instance->port);
1905+
1906+
MAKE_STD_ZVAL(context->entry);
1907+
array_init(context->entry);
1908+
1909+
add_assoc_long(context->entry, "pid", context->stats[context->i].pid);
1910+
add_assoc_long(context->entry, "uptime", context->stats[context->i].uptime);
1911+
add_assoc_long(context->entry, "threads", context->stats[context->i].threads);
1912+
add_assoc_long(context->entry, "time", context->stats[context->i].time);
1913+
add_assoc_long(context->entry, "pointer_size", context->stats[context->i].pointer_size);
1914+
add_assoc_long(context->entry, "rusage_user_seconds", context->stats[context->i].rusage_user_seconds);
1915+
add_assoc_long(context->entry, "rusage_user_microseconds", context->stats[context->i].rusage_user_microseconds);
1916+
add_assoc_long(context->entry, "rusage_system_seconds", context->stats[context->i].rusage_system_seconds);
1917+
add_assoc_long(context->entry, "rusage_system_microseconds", context->stats[context->i].rusage_system_microseconds);
1918+
add_assoc_long(context->entry, "curr_items", context->stats[context->i].curr_items);
1919+
add_assoc_long(context->entry, "total_items", context->stats[context->i].total_items);
1920+
add_assoc_long(context->entry, "limit_maxbytes", context->stats[context->i].limit_maxbytes);
1921+
add_assoc_long(context->entry, "curr_connections", context->stats[context->i].curr_connections);
1922+
add_assoc_long(context->entry, "total_connections", context->stats[context->i].total_connections);
1923+
add_assoc_long(context->entry, "connection_structures", context->stats[context->i].connection_structures);
1924+
add_assoc_long(context->entry, "bytes", context->stats[context->i].bytes);
1925+
add_assoc_long(context->entry, "cmd_get", context->stats[context->i].cmd_get);
1926+
add_assoc_long(context->entry, "cmd_set", context->stats[context->i].cmd_set);
1927+
add_assoc_long(context->entry, "get_hits", context->stats[context->i].get_hits);
1928+
add_assoc_long(context->entry, "get_misses", context->stats[context->i].get_misses);
1929+
add_assoc_long(context->entry, "evictions", context->stats[context->i].evictions);
1930+
add_assoc_long(context->entry, "bytes_read", context->stats[context->i].bytes_read);
1931+
add_assoc_long(context->entry, "bytes_written", context->stats[context->i].bytes_written);
1932+
add_assoc_stringl(context->entry, "version", context->stats[context->i].version, strlen(context->stats[context->i].version), 1);
1933+
1934+
add_assoc_zval_ex(context->return_value, hostport, hostport_len+1, context->entry);
1935+
efree(hostport);
1936+
1937+
/* Increment the server count in our context structure. Failure to do so will cause only the stats for the last server to get displayed. */
1938+
context->i++;
1939+
return MEMCACHED_SUCCESS;
1940+
}
1941+
1942+
static memcached_return php_memc_do_version_callback(memcached_st *ptr, memcached_server_instance_st instance, void *in_context)
1943+
{
1944+
char *hostport = NULL;
1945+
char version[16];
1946+
int hostport_len, version_len;
1947+
struct callbackContext* context = (struct callbackContext*) in_context;
1948+
1949+
hostport_len = spprintf(&hostport, 0, "%s:%d", instance->hostname, instance->port);
1950+
version_len = snprintf(version, sizeof(version), "%d.%d.%d",
1951+
instance->major_version, instance->minor_version,
1952+
instance->micro_version);
1953+
1954+
add_assoc_stringl_ex(context->return_value, hostport, hostport_len+1, version, version_len, 1);
1955+
efree(hostport);
1956+
return MEMCACHED_SUCCESS;
1957+
}
1958+
19281959
static int php_memc_handle_error(memcached_return status TSRMLS_DC)
19291960
{
19301961
int result = 0;
@@ -1999,7 +2030,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t
19992030
#if HAVE_JSON_API
20002031
case SERIALIZER_JSON:
20012032
{
2002-
php_json_encode(&buf, value TSRMLS_CC);
2033+
php_json_encode(&buf, value, 0 TSRMLS_CC);
20032034
buf.c[buf.len] = 0;
20042035
MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON);
20052036
break;
@@ -2164,7 +2195,7 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload
21642195

21652196
case MEMC_VAL_IS_JSON:
21662197
#if HAVE_JSON_API
2167-
php_json_decode(value, payload, payload_len, 0 TSRMLS_CC);
2198+
php_json_decode(value, payload, payload_len, 0, 512 TSRMLS_CC);
21682199
#else
21692200
php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no json support");
21702201
return -1;
@@ -2777,8 +2808,8 @@ static zend_function_entry memcached_class_methods[] = {
27772808
MEMC_ME(getServerList, arginfo_getServerList)
27782809
MEMC_ME(getServerByKey, arginfo_getServerByKey)
27792810

2780-
MEMC_ME(getStats, arginfo_getStats)
2781-
MEMC_ME(getVersion, arginfo_getVersion)
2811+
MEMC_ME(getStats, arginfo_getStats)
2812+
MEMC_ME(getVersion, arginfo_getVersion)
27822813

27832814
MEMC_ME(flush, arginfo_flush)
27842815

0 commit comments

Comments
 (0)