@@ -608,6 +608,20 @@ static char **split_str_by_delim(char *str, char *delim, int *len) {
608608    return  array ;
609609}
610610
611+ /* Fisher-Yates shuffle for integer array */ 
612+ static  void  fyshuffle (int  * array , size_t  len ) {
613+     int  temp , n  =  len ;
614+     size_t  r ;
615+ 
616+     /* Randomize */ 
617+     while  (n  >  1 ) {
618+         r  =  ((int )((double )n --  *  (rand () / (RAND_MAX + 1.0 ))));
619+         temp  =  array [n ];
620+         array [n ] =  array [r ];
621+         array [r ] =  temp ;
622+     };
623+ }
624+ 
611625/* Execute a CLUSTER SLOTS command against the seed socket, and return the 
612626 * reply or NULL on failure. */ 
613627clusterReply *  cluster_get_slots (RedisSock  * redis_sock  TSRMLS_DC )
@@ -849,35 +863,60 @@ PHP_REDIS_API void cluster_free(redisCluster *c) {
849863    efree (c );
850864}
851865
866+ /* Takes our input hash table and returns a straigt C array with elements, 
867+  * which have been randomized.  The return value needs to be freed. */ 
868+ static  zval  * * cluster_shuffle_seeds (HashTable  * seeds , int  * len ) {
869+     zval  * * z_seeds , * * z_seed ;
870+     int  * map , i , count , index = 0 ;
871+ 
872+     /* How many */ 
873+     count  =  zend_hash_num_elements (seeds );
874+ 
875+     /* Allocate our return value and map */ 
876+     z_seeds  =  ecalloc (count , sizeof (zval * ));
877+     map  =  emalloc (sizeof (int )* count );
878+ 
879+     /* Fill in and shuffle our map */ 
880+     for  (i  =  0 ; i  <  count ; i ++ ) map [i ] =  i ;
881+     fyshuffle (map , count );
882+ 
883+     /* Iterate over our source array and use our map to create a random list */ 
884+     for  (zend_hash_internal_pointer_reset (seeds );
885+          zend_hash_has_more_elements (seeds ) ==  SUCCESS ;
886+          zend_hash_move_forward (seeds ))
887+     {
888+         zend_hash_get_current_data (seeds , (void * * )& z_seed );
889+         z_seeds [map [index ]] =  * z_seed ;
890+         index ++ ;
891+     }
892+ 
893+     efree (map );
894+ 
895+     * len  =  count ;
896+     return  z_seeds ;
897+ }
898+ 
852899/* Initialize seeds */ 
853900PHP_REDIS_API  int 
854901cluster_init_seeds (redisCluster  * cluster , HashTable  * ht_seeds ) {
855902    RedisSock  * redis_sock ;
856903    char  * str , * psep , key [1024 ];
857-     int  key_len ;
858-     zval  * * z_seed ;
859-     int  * seeds ;
860-     size_t  i , count ;
904+     int  key_len , count , i ;
905+     zval  * * z_seeds , * z_seed ;
861906
862-     count  =  zend_hash_num_elements (ht_seeds );
863-     seeds  =  emalloc (sizeof (int ) *  count );
864- 
865-     for  (i  =  0 ; i  <  count ; i ++ ) seeds [i ] =  i ;
866-     fyshuffle (seeds , count );
907+     /* Get our seeds in a randomized array */ 
908+     z_seeds  =  cluster_shuffle_seeds (ht_seeds , & count );
867909
868910    // Iterate our seeds array 
869911    for  (i  =  0 ; i  <  count ; i ++ ) {
870-         // Grab seed string 
871-         if  (zend_hash_index_find (ht_seeds , seeds [i ], (void * * )& z_seed ) !=  SUCCESS )  {
872-             continue ;
873-         }
912+         z_seed  =  z_seeds [i ];
874913
875-         // Skip anything that isn't  a string 
876-         if ( Z_TYPE_PP (z_seed )!= IS_STRING )
914+         /* Has to be  a string */  
915+         if  ( z_seed   ==   NULL   ||   Z_TYPE_P (z_seed )  !=   IS_STRING )
877916            continue ;
878917
879918        // Grab a copy of the string 
880-         str  =  Z_STRVAL_PP (z_seed );
919+         str  =  Z_STRVAL_P (z_seed );
881920
882921        // Must be in host:port form 
883922        if (!(psep  =  strchr (str , ':' )))
@@ -897,15 +936,14 @@ cluster_init_seeds(redisCluster *cluster, HashTable *ht_seeds) {
897936            sizeof (RedisSock * ),NULL );
898937    }
899938
900-     efree (seeds );
939+     efree (z_seeds );
901940
902941    // Success if at least one seed seems valid 
903942    return  zend_hash_num_elements (cluster -> seeds ) >  0  ? 0  : -1 ;
904943}
905944
906945/* Initial mapping of our cluster keyspace */ 
907- PHP_REDIS_API  int 
908- cluster_map_keyspace (redisCluster  * c  TSRMLS_DC ) {
946+ PHP_REDIS_API  int  cluster_map_keyspace (redisCluster  * c  TSRMLS_DC ) {
909947    RedisSock  * * seed ;
910948    clusterReply  * slots = NULL ;
911949    int  mapped = 0 ;
@@ -1060,20 +1098,6 @@ PHP_REDIS_API void cluster_disconnect(redisCluster *c TSRMLS_DC) {
10601098    }
10611099}
10621100
1063- /* Fisher-Yates shuffle for integer array */ 
1064- static  void  fyshuffle (int  * array , size_t  len ) {
1065-     int  temp , n  =  len ;
1066-     size_t  r ;
1067- 
1068-     /* Randomize */ 
1069-     while  (n  >  1 ) {
1070-         r  =  ((int )((double )n --  *  (rand () / (RAND_MAX + 1.0 ))));
1071-         temp  =  array [n ];
1072-         array [n ] =  array [r ];
1073-         array [r ] =  temp ;
1074-     };
1075- }
1076- 
10771101/* This method attempts to write our command at random to the master and any 
10781102 * attached slaves, until we either successufly do so, or fail. */ 
10791103static  int  cluster_dist_write (redisCluster  * c , const  char  * cmd , size_t  sz ,
0 commit comments