diff --git a/src/mongo/s/balancer_policy.cpp b/src/mongo/s/balancer_policy.cpp index 5d6e186..b8231d1 100644 --- a/src/mongo/s/balancer_policy.cpp +++ b/src/mongo/s/balancer_policy.cpp @@ -138,16 +138,35 @@ namespace mongo { // It is possible for a donor ('from') shard to have less chunks than a receiver one ('to') // if the donor is in draining mode. - if ( to.size() == 0 ) - return from[0]; - - if ( from[0]["min"].Obj().woCompare( to[to.size()-1]["max"].Obj() , BSONObj() , false ) == 0 ) - return from[0]; + vector::const_iterator ifrom = from.begin(); + vector::const_iterator ito = to.begin(); + BSONObj chunk; + unsigned maxgap = 0; + do + { + // Seek to the following chunk on the receiver shard + while ( ito != to.end() && (*ifrom)["min"].Obj().woCompare( (*ito)["max"].Obj() , BSONObj() , false ) >= 0 ) + ito++; + + // Seek through the chunks on the donor shard until we catch up with the receiver, + // and count the span of the gap + unsigned gap = 0; + while ( ifrom != from.end() && ( ito == to.end() || (*ifrom)["max"].Obj().woCompare( (*ito)["min"].Obj() , BSONObj() , false ) <= 0 ) ) + { + ifrom++; + gap++; + } - if ( from[from.size()-1]["max"].Obj().woCompare( to[0]["min"].Obj() , BSONObj() , false ) == 0 ) - return from[from.size()-1]; + // Pick the chunk in the middle of the widest gap + if ( gap > maxgap ) + { + maxgap = gap; + chunk = *(ifrom - (gap/2 + 1)); + } + } + while ( ifrom != from.end() && ito != to.end() ); - return from[0]; + return chunk; } bool BalancerPolicy::isSizeMaxed( BSONObj limits ) {