@@ -157,6 +157,16 @@ static int le_memc;
157157
158158static zend_class_entry * memcached_ce = NULL ;
159159static 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+
160170static 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);
190200static void php_memc_getDelayed_impl (INTERNAL_FUNCTION_PARAMETERS , zend_bool by_key );
191201static 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 );
192202static 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 */
14731487PHP_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 */
15421546PHP_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)
16121582PHP_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+
19281959static 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