mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-29 02:59:34 -05:00
ITS#8204 Improved RFC2782 shuffle when several, but not all, records have weight 0.
The fallback to a straight Fisher-Yates shuffle needs to occur whenever the sum of the *remaining* weights is zero, or else the remaining records will not be reordered. Testing only once at the beginning covers the case when all weights are zero, and obviously no shuffling is needed when only one weight is zero; but other weight combinations are possible, such as (1, 0, 0).
This commit is contained in:
parent
ee7502accd
commit
8006ee58b8
1 changed files with 17 additions and 26 deletions
|
|
@ -216,36 +216,27 @@ static void srv_shuffle(srv_record *a, int n) {
|
|||
for (i=0; i<n; i++)
|
||||
total += a[i].weight;
|
||||
|
||||
/* all weights are zero, do a straight Fisher-Yates shuffle */
|
||||
if (!total) {
|
||||
while (n) {
|
||||
srv_record t;
|
||||
i = srv_rand() * n--;
|
||||
t = a[n];
|
||||
a[n] = a[i];
|
||||
a[i] = t;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do a shuffle per RFC2782 Page 4 */
|
||||
p = n;
|
||||
for (i=0; i<n-1; i++) {
|
||||
r = srv_rand() * total;
|
||||
for (j=0; j<p; j++) {
|
||||
r -= a[j].weight;
|
||||
if (r < 0) {
|
||||
if (j) {
|
||||
srv_record t = a[0];
|
||||
a[0] = a[j];
|
||||
a[j] = t;
|
||||
for (p=n; p>1; a++, p--) {
|
||||
if (!total) {
|
||||
/* all remaining weights are zero,
|
||||
do a straight Fisher-Yates shuffle */
|
||||
j = srv_rand() * p;
|
||||
} else {
|
||||
r = srv_rand() * total;
|
||||
for (j=0; j<p; j++) {
|
||||
r -= a[j].weight;
|
||||
if (r < 0) {
|
||||
total -= a[j].weight;
|
||||
break;
|
||||
}
|
||||
total -= a[0].weight;
|
||||
a++;
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j && j<p) {
|
||||
srv_record t = a[0];
|
||||
a[0] = a[j];
|
||||
a[j] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_RES_QUERY */
|
||||
|
|
|
|||
Loading…
Reference in a new issue