@@ -608,6 +608,20 @@ static char **split_str_by_delim(char *str, char *delim, int *len) {
608
608
return array ;
609
609
}
610
610
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
+
611
625
/* Execute a CLUSTER SLOTS command against the seed socket, and return the
612
626
* reply or NULL on failure. */
613
627
clusterReply * cluster_get_slots (RedisSock * redis_sock TSRMLS_DC )
@@ -849,35 +863,60 @@ PHP_REDIS_API void cluster_free(redisCluster *c) {
849
863
efree (c );
850
864
}
851
865
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
+
852
899
/* Initialize seeds */
853
900
PHP_REDIS_API int
854
901
cluster_init_seeds (redisCluster * cluster , HashTable * ht_seeds ) {
855
902
RedisSock * redis_sock ;
856
903
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 ;
861
906
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 );
867
909
868
910
// Iterate our seeds array
869
911
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 ];
874
913
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 )
877
916
continue ;
878
917
879
918
// Grab a copy of the string
880
- str = Z_STRVAL_PP (z_seed );
919
+ str = Z_STRVAL_P (z_seed );
881
920
882
921
// Must be in host:port form
883
922
if (!(psep = strchr (str , ':' )))
@@ -897,15 +936,14 @@ cluster_init_seeds(redisCluster *cluster, HashTable *ht_seeds) {
897
936
sizeof (RedisSock * ),NULL );
898
937
}
899
938
900
- efree (seeds );
939
+ efree (z_seeds );
901
940
902
941
// Success if at least one seed seems valid
903
942
return zend_hash_num_elements (cluster -> seeds ) > 0 ? 0 : -1 ;
904
943
}
905
944
906
945
/* 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 ) {
909
947
RedisSock * * seed ;
910
948
clusterReply * slots = NULL ;
911
949
int mapped = 0 ;
@@ -1060,20 +1098,6 @@ PHP_REDIS_API void cluster_disconnect(redisCluster *c TSRMLS_DC) {
1060
1098
}
1061
1099
}
1062
1100
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
-
1077
1101
/* This method attempts to write our command at random to the master and any
1078
1102
* attached slaves, until we either successufly do so, or fail. */
1079
1103
static int cluster_dist_write (redisCluster * c , const char * cmd , size_t sz ,
0 commit comments