2626#include "ext/standard/crc32.h"
2727#include "ext/standard/md5.h"
2828
29+ #include "ext/hash/php_hash.h"
30+
2931#define PHPREDIS_INDEX_NAME "__phpredis_array_index__"
3032
3133extern zend_class_entry * redis_ce ;
@@ -162,11 +164,12 @@ ra_find_name(const char *name) {
162164/* laod array from INI settings */
163165RedisArray * ra_load_array (const char * name TSRMLS_DC ) {
164166
165- zval * z_data , z_fun , z_dist ;
167+ zval * z_data , z_fun , z_dist , z_algo ;
166168 zval z_params_hosts ;
167169 zval z_params_prev ;
168170 zval z_params_funs ;
169171 zval z_params_dist ;
172+ zval z_params_algo ;
170173 zval z_params_index ;
171174 zval z_params_autorehash ;
172175 zval z_params_retry_interval ;
@@ -227,6 +230,16 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
227230 ZVAL_ZVAL (& z_dist , z_data , 1 , 0 );
228231 }
229232
233+ /* find hash algorithm */
234+ array_init (& z_params_algo );
235+ if ((iptr = INI_STR ("redis.arrays.algorithm" )) != NULL ) {
236+ sapi_module .treat_data (PARSE_STRING , estrdup (iptr ), & z_params_algo TSRMLS_CC );
237+ }
238+ ZVAL_NULL (& z_algo );
239+ if ((z_data = zend_hash_str_find (Z_ARRVAL (z_params_algo ), name , name_len )) != NULL ) {
240+ ZVAL_ZVAL (& z_algo , z_data , 1 , 0 );
241+ }
242+
230243 /* find index option */
231244 array_init (& z_params_index );
232245 if ((iptr = INI_STR ("redis.arrays.index" )) != NULL ) {
@@ -327,7 +340,7 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
327340
328341
329342 /* create RedisArray object */
330- ra = ra_make_array (hHosts , & z_fun , & z_dist , hPrev , b_index , b_pconnect , l_retry_interval , b_lazy_connect , d_connect_timeout , read_timeout , consistent TSRMLS_CC );
343+ ra = ra_make_array (hHosts , & z_fun , & z_dist , & z_algo , hPrev , b_index , b_pconnect , l_retry_interval , b_lazy_connect , d_connect_timeout , read_timeout , consistent TSRMLS_CC );
331344 if (ra ) {
332345 ra -> auto_rehash = b_autorehash ;
333346 if (ra -> prev ) ra -> prev -> auto_rehash = b_autorehash ;
@@ -338,6 +351,7 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
338351 zval_dtor (& z_params_prev );
339352 zval_dtor (& z_params_funs );
340353 zval_dtor (& z_params_dist );
354+ zval_dtor (& z_params_algo );
341355 zval_dtor (& z_params_index );
342356 zval_dtor (& z_params_autorehash );
343357 zval_dtor (& z_params_retry_interval );
@@ -346,6 +360,7 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
346360 zval_dtor (& z_params_read_timeout );
347361 zval_dtor (& z_params_lazy_connect );
348362 zval_dtor (& z_params_consistent );
363+ zval_dtor (& z_algo );
349364 zval_dtor (& z_dist );
350365 zval_dtor (& z_fun );
351366
@@ -393,7 +408,7 @@ ra_make_continuum(zend_string **hosts, int nb_hosts)
393408}
394409
395410RedisArray *
396- ra_make_array (HashTable * hosts , zval * z_fun , zval * z_dist , HashTable * hosts_prev , zend_bool b_index , zend_bool b_pconnect , long retry_interval , zend_bool b_lazy_connect , double connect_timeout , double read_timeout , zend_bool consistent TSRMLS_DC ) {
411+ ra_make_array (HashTable * hosts , zval * z_fun , zval * z_dist , zval * z_algo , HashTable * hosts_prev , zend_bool b_index , zend_bool b_pconnect , long retry_interval , zend_bool b_lazy_connect , double connect_timeout , double read_timeout , zend_bool consistent TSRMLS_DC ) {
397412
398413 int i , count ;
399414 RedisArray * ra ;
@@ -423,14 +438,15 @@ ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev
423438 efree (ra );
424439 return NULL ;
425440 }
426- ra -> prev = hosts_prev ? ra_make_array (hosts_prev , z_fun , z_dist , NULL , b_index , b_pconnect , retry_interval , b_lazy_connect , connect_timeout , read_timeout , consistent TSRMLS_CC ) : NULL ;
441+ ra -> prev = hosts_prev ? ra_make_array (hosts_prev , z_fun , z_dist , z_algo , NULL , b_index , b_pconnect , retry_interval , b_lazy_connect , connect_timeout , read_timeout , consistent TSRMLS_CC ) : NULL ;
427442
428443 /* init array data structures */
429444 ra_init_function_table (ra );
430445
431446 /* Set hash function and distribtor if provided */
432447 ZVAL_ZVAL (& ra -> z_fun , z_fun , 1 , 0 );
433448 ZVAL_ZVAL (& ra -> z_dist , z_dist , 1 , 0 );
449+ ZVAL_ZVAL (& ra -> z_algo , z_algo , 1 , 0 );
434450
435451 /* init continuum */
436452 if (consistent ) {
@@ -533,10 +549,26 @@ ra_find_node(RedisArray *ra, const char *key, int key_len, int *out_pos TSRMLS_D
533549 if (Z_TYPE (ra -> z_dist ) == IS_NULL ) {
534550 int i ;
535551 unsigned long ret = 0xffffffff ;
552+ const php_hash_ops * ops ;
536553
537554 /* hash */
538- for (i = 0 ; i < ZSTR_LEN (out ); ++ i ) {
539- CRC32 (ret , ZSTR_VAL (out )[i ]);
555+ if (Z_TYPE (ra -> z_algo ) == IS_STRING && (ops = php_hash_fetch_ops (Z_STRVAL (ra -> z_algo ), Z_STRLEN (ra -> z_algo ))) != NULL ) {
556+ void * ctx = emalloc (ops -> context_size );
557+ unsigned char * digest = emalloc (ops -> digest_size );
558+
559+ ops -> hash_init (ctx );
560+ ops -> hash_update (ctx , ZSTR_VAL (out ), ZSTR_LEN (out ));
561+ ops -> hash_final (digest , ctx );
562+
563+ memcpy (& ret , digest , MIN (sizeof (ret ), ops -> digest_size ));
564+ ret %= 0xffffffff ;
565+
566+ efree (digest );
567+ efree (ctx );
568+ } else {
569+ for (i = 0 ; i < ZSTR_LEN (out ); ++ i ) {
570+ CRC32 (ret , ZSTR_VAL (out )[i ]);
571+ }
540572 }
541573
542574 /* get position on ring */
0 commit comments