| 2680 | } |
| 2681 | |
| 2682 | static void clusterManagerOptimizeAntiAffinity(clusterManagerNodeArray *ipnodes, |
| 2683 | int ip_count) |
| 2684 | { |
| 2685 | clusterManagerNode **offenders = NULL; |
| 2686 | int score = clusterManagerGetAntiAffinityScore(ipnodes, ip_count, |
| 2687 | NULL, NULL); |
| 2688 | if (score == 0) goto cleanup; |
| 2689 | clusterManagerLogInfo(">>> Trying to optimize slaves allocation " |
| 2690 | "for anti-affinity\n"); |
| 2691 | int node_len = cluster_manager.nodes->len; |
| 2692 | int maxiter = 500 * node_len; // Effort is proportional to cluster size... |
| 2693 | srand(time(NULL)); |
| 2694 | while (maxiter > 0) { |
| 2695 | int offending_len = 0; |
| 2696 | if (offenders != NULL) { |
| 2697 | zfree(offenders); |
| 2698 | offenders = NULL; |
| 2699 | } |
| 2700 | score = clusterManagerGetAntiAffinityScore(ipnodes, |
| 2701 | ip_count, |
| 2702 | &offenders, |
| 2703 | &offending_len); |
| 2704 | if (score == 0 || offending_len == 0) break; // Optimal anti affinity reached |
| 2705 | /* We'll try to randomly swap a slave's assigned master causing |
| 2706 | * an affinity problem with another random slave, to see if we |
| 2707 | * can improve the affinity. */ |
| 2708 | int rand_idx = rand() % offending_len; |
| 2709 | clusterManagerNode *first = offenders[rand_idx], |
| 2710 | *second = NULL; |
| 2711 | clusterManagerNode **other_replicas = zcalloc((node_len - 1) * |
| 2712 | sizeof(*other_replicas), MALLOC_LOCAL); |
| 2713 | int other_replicas_count = 0; |
| 2714 | listIter li; |
| 2715 | listNode *ln; |
| 2716 | listRewind(cluster_manager.nodes, &li); |
| 2717 | while ((ln = listNext(&li)) != NULL) { |
| 2718 | clusterManagerNode *n = ln->value; |
| 2719 | if (n != first && n->replicate != NULL) |
| 2720 | other_replicas[other_replicas_count++] = n; |
| 2721 | } |
| 2722 | if (other_replicas_count == 0) { |
| 2723 | zfree(other_replicas); |
| 2724 | break; |
| 2725 | } |
| 2726 | rand_idx = rand() % other_replicas_count; |
| 2727 | second = other_replicas[rand_idx]; |
| 2728 | char *first_master = first->replicate, |
| 2729 | *second_master = second->replicate; |
| 2730 | first->replicate = second_master, first->dirty = 1; |
| 2731 | second->replicate = first_master, second->dirty = 1; |
| 2732 | int new_score = clusterManagerGetAntiAffinityScore(ipnodes, |
| 2733 | ip_count, |
| 2734 | NULL, NULL); |
| 2735 | /* If the change actually makes thing worse, revert. Otherwise |
| 2736 | * leave as it is because the best solution may need a few |
| 2737 | * combined swaps. */ |
| 2738 | if (new_score > score) { |
| 2739 | first->replicate = first_master; |
no test coverage detected