Return the anti-affinity score, which is a measure of the amount of * violations of anti-affinity in the current cluster layout, that is, how * badly the masters and slaves are distributed in the different IP * addresses so that slaves of the same master are not in the master * host and are also in different hosts. * * The score is calculated as follows: * * SAME_AS_MASTER = 10000 * each r
| 368 | * so that the optimizer can try changing the configuration of the |
| 369 | * slaves violating the anti-affinity goals. */ |
| 370 | int clusterManagerGetAntiAffinityScore(clusterManagerNodeArray *ipnodes, |
| 371 | int ip_count, clusterManagerNode ***offending, int *offending_len) |
| 372 | { |
| 373 | int score = 0, i, j; |
| 374 | int node_len = cluster_manager.nodes->len; |
| 375 | clusterManagerNode **offending_p = NULL; |
| 376 | if (offending != NULL) { |
| 377 | *offending = (clusterManagerNode**)zcalloc(node_len * sizeof(clusterManagerNode*), MALLOC_LOCAL); |
| 378 | offending_p = *offending; |
| 379 | } |
| 380 | /* For each set of nodes in the same host, split by |
| 381 | * related nodes (masters and slaves which are involved in |
| 382 | * replication of each other) */ |
| 383 | for (i = 0; i < ip_count; i++) { |
| 384 | clusterManagerNodeArray *node_array = &(ipnodes[i]); |
| 385 | dict *related = dictCreate(&clusterManagerDictType, NULL); |
| 386 | char *ip = NULL; |
| 387 | for (j = 0; j < node_array->len; j++) { |
| 388 | clusterManagerNode *node = node_array->nodes[j]; |
| 389 | if (node == NULL) continue; |
| 390 | if (!ip) ip = node->ip; |
| 391 | sds types; |
| 392 | /* We always use the Master ID as key. */ |
| 393 | sds key = (!node->replicate ? node->name : node->replicate); |
| 394 | assert(key != NULL); |
| 395 | dictEntry *entry = dictFind(related, key); |
| 396 | if (entry) types = sdsdup((sds) dictGetVal(entry)); |
| 397 | else types = sdsempty(); |
| 398 | /* Master type 'm' is always set as the first character of the |
| 399 | * types string. */ |
| 400 | if (node->replicate) types = sdscat(types, "s"); |
| 401 | else { |
| 402 | sds s = sdscatsds(sdsnew("m"), types); |
| 403 | sdsfree(types); |
| 404 | types = s; |
| 405 | } |
| 406 | dictReplace(related, key, types); |
| 407 | } |
| 408 | /* Now it's trivial to check, for each related group having the |
| 409 | * same host, what is their local score. */ |
| 410 | dictIterator *iter = dictGetIterator(related); |
| 411 | dictEntry *entry; |
| 412 | while ((entry = dictNext(iter)) != NULL) { |
| 413 | sds types = (sds) dictGetVal(entry); |
| 414 | sds name = (sds) dictGetKey(entry); |
| 415 | int typeslen = sdslen(types); |
| 416 | if (typeslen < 2) continue; |
| 417 | if (types[0] == 'm') score += (10000 * (typeslen - 1)); |
| 418 | else score += (1 * typeslen); |
| 419 | if (offending == NULL) continue; |
| 420 | /* Populate the list of offending nodes. */ |
| 421 | listIter li; |
| 422 | listNode *ln; |
| 423 | listRewind(cluster_manager.nodes, &li); |
| 424 | while ((ln = listNext(&li)) != NULL) { |
| 425 | clusterManagerNode *n = (clusterManagerNode*)ln->value; |
| 426 | if (n->replicate == NULL) continue; |
| 427 | if (!strcmp(n->replicate, name) && !strcmp(n->ip, ip)) { |
no test coverage detected