| 3069 | } |
| 3070 | |
| 3071 | static void clusterManagerOptimizeAntiAffinity(clusterManagerNodeArray *ipnodes, |
| 3072 | int ip_count) |
| 3073 | { |
| 3074 | clusterManagerNode **offenders = NULL; |
| 3075 | int score = clusterManagerGetAntiAffinityScore(ipnodes, ip_count, |
| 3076 | NULL, NULL); |
| 3077 | if (score == 0) goto cleanup; |
| 3078 | clusterManagerLogInfo(">>> Trying to optimize slaves allocation " |
| 3079 | "for anti-affinity\n"); |
| 3080 | int node_len = cluster_manager.nodes->len; |
| 3081 | int maxiter = 500 * node_len; // Effort is proportional to cluster size... |
| 3082 | srand(time(NULL)); |
| 3083 | while (maxiter > 0) { |
| 3084 | int offending_len = 0; |
| 3085 | if (offenders != NULL) { |
| 3086 | zfree(offenders); |
| 3087 | offenders = NULL; |
| 3088 | } |
| 3089 | score = clusterManagerGetAntiAffinityScore(ipnodes, |
| 3090 | ip_count, |
| 3091 | &offenders, |
| 3092 | &offending_len); |
| 3093 | if (score == 0 || offending_len == 0) break; // Optimal anti affinity reached |
| 3094 | /* We'll try to randomly swap a slave's assigned master causing |
| 3095 | * an affinity problem with another random slave, to see if we |
| 3096 | * can improve the affinity. */ |
| 3097 | int rand_idx = rand() % offending_len; |
| 3098 | clusterManagerNode *first = offenders[rand_idx], |
| 3099 | *second = NULL; |
| 3100 | clusterManagerNode **other_replicas = zcalloc((node_len - 1) * |
| 3101 | sizeof(*other_replicas)); |
| 3102 | int other_replicas_count = 0; |
| 3103 | listIter li; |
| 3104 | listNode *ln; |
| 3105 | listRewind(cluster_manager.nodes, &li); |
| 3106 | while ((ln = listNext(&li)) != NULL) { |
| 3107 | clusterManagerNode *n = ln->value; |
| 3108 | if (n != first && n->replicate != NULL) |
| 3109 | other_replicas[other_replicas_count++] = n; |
| 3110 | } |
| 3111 | if (other_replicas_count == 0) { |
| 3112 | zfree(other_replicas); |
| 3113 | break; |
| 3114 | } |
| 3115 | rand_idx = rand() % other_replicas_count; |
| 3116 | second = other_replicas[rand_idx]; |
| 3117 | char *first_master = first->replicate, |
| 3118 | *second_master = second->replicate; |
| 3119 | first->replicate = second_master, first->dirty = 1; |
| 3120 | second->replicate = first_master, second->dirty = 1; |
| 3121 | int new_score = clusterManagerGetAntiAffinityScore(ipnodes, |
| 3122 | ip_count, |
| 3123 | NULL, NULL); |
| 3124 | /* If the change actually makes thing worse, revert. Otherwise |
| 3125 | * leave as it is because the best solution may need a few |
| 3126 | * combined swaps. */ |
| 3127 | if (new_score > score) { |
| 3128 | first->replicate = first_master; |
no test coverage detected