@@ -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