Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 200afe6

Browse files
Merging in logic from phpredis#777 to shuffle cluster seeds
1 parent ccecc62 commit 200afe6

File tree

2 files changed

+57
-35
lines changed

2 files changed

+57
-35
lines changed

cluster_library.c

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -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. */
613627
clusterReply* 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 */
853900
PHP_REDIS_API int
854901
cluster_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. */
10791103
static int cluster_dist_write(redisCluster *c, const char *cmd, size_t sz,

cluster_library.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,8 +458,6 @@ int mbulk_resp_loop_zipdbl(RedisSock *redis_sock, zval *z_result,
458458
int mbulk_resp_loop_assoc(RedisSock *redis_sock, zval *z_result,
459459
long long count, void *ctx TSRMLS_DC);
460460

461-
static void fyshuffle(int *array, size_t len);
462-
463461
#endif
464462

465463
/* vim: set tabstop=4 softtabstops=4 noexpandtab shiftwidth=4: */

0 commit comments

Comments
 (0)