| 1452 | |
| 1453 | |
| 1454 | static inline void sort_srvs(struct rdata **head) |
| 1455 | { |
| 1456 | #define rd2srv(_rd) ((struct srv_rdata*)_rd->rdata) |
| 1457 | struct rdata *rd = *head; |
| 1458 | struct rdata *tail = NULL; |
| 1459 | struct rdata *rd_next; |
| 1460 | struct rdata *crt; |
| 1461 | struct rdata *crt2; |
| 1462 | unsigned int weight_sum; |
| 1463 | unsigned int rand_no; |
| 1464 | |
| 1465 | |
| 1466 | *head = NULL; |
| 1467 | |
| 1468 | while( rd ) { |
| 1469 | rd_next = rd->next; |
| 1470 | if (rd->type!=T_SRV) { |
| 1471 | rd->next = NULL; |
| 1472 | free_rdata_list(rd); |
| 1473 | } else { |
| 1474 | /* only on element with same priority ? */ |
| 1475 | if (rd_next==NULL || |
| 1476 | rd2srv(rd)->priority!=rd2srv(rd_next)->priority) { |
| 1477 | if (tail) {tail->next=rd;tail=rd;} |
| 1478 | else {*head=tail=rd;} |
| 1479 | rd->next = NULL; |
| 1480 | } else { |
| 1481 | /* multiple nodes with same priority */ |
| 1482 | /* -> calculate running sums (and detect the end) */ |
| 1483 | weight_sum = rd2srv(rd)->running_sum = rd2srv(rd)->weight; |
| 1484 | crt = rd; |
| 1485 | while( crt && crt->next && |
| 1486 | (rd2srv(rd)->priority==rd2srv(crt->next)->priority) ) { |
| 1487 | crt = crt->next; |
| 1488 | weight_sum += rd2srv(crt)->weight; |
| 1489 | rd2srv(crt)->running_sum = weight_sum; |
| 1490 | } |
| 1491 | /* crt will point to last RR with same priority */ |
| 1492 | rd_next = crt->next; |
| 1493 | crt->next = NULL; |
| 1494 | |
| 1495 | /* order the elements between rd and crt */ |
| 1496 | while (rd->next) { |
| 1497 | rand_no = (unsigned int) |
| 1498 | (weight_sum*((float)rand()/(float)RAND_MAX)); |
| 1499 | for( crt=rd,crt2=NULL ; crt ; crt2=crt,crt=crt->next) { |
| 1500 | if (rd2srv(crt)->running_sum>=rand_no) break; |
| 1501 | } |
| 1502 | if (crt == NULL) { |
| 1503 | LM_CRIT("bug in sorting SRVs - rand>sum\n"); |
| 1504 | crt = rd; |
| 1505 | crt2 = NULL; |
| 1506 | } |
| 1507 | /* remove the element from the list ... */ |
| 1508 | if (crt2==NULL) { rd = rd->next;} |
| 1509 | else {crt2->next = crt->next;} |
| 1510 | /* .... and update the running sums */ |
| 1511 | for ( crt2=crt->next ; crt2 ; crt2=crt2->next) |
no test coverage detected