/** @var Array (location => (start, end)) */
protected $ring = array();
- const RING_SIZE = 16777216; // 2^24
+ const RING_SIZE = 268435456; // 2^28
/**
* @param array $map (location => weight)
*/
public function __construct( array $map ) {
- $sum = array_sum( $map );
- if ( !count( $map ) || $sum <= 0 ) {
+ $map = array_filter( $map, function( $w ) { return $w > 0; } );
+ if ( !count( $map ) ) {
throw new MWException( "Ring is empty or all weights are zero." );
}
// Sort the locations based on the hash of their names
return strcmp( $hashes[$a], $hashes[$b] );
} );
// Fit the map to weight-proportionate one with a space of size RING_SIZE
+ $sum = array_sum( $map );
$standardMap = array();
foreach ( $map as $location => $weight ) {
- $standardMap[$location] = (int)floor( $weight/$sum * self::RING_SIZE );
+ $standardMap[$location] = (int)floor( $weight / $sum * self::RING_SIZE );
}
// Build a ring of RING_SIZE spots, with each location at a spot in location hash order
$index = 0;
public function getLocations( $item, $limit ) {
$locations = array();
$primaryLocation = null;
- $spot = hexdec( substr( sha1( $item ), 0, 6 ) ); // first 24 bits
+ $spot = hexdec( substr( sha1( $item ), 0, 7 ) ); // first 28 bits
foreach ( $this->ring as $location => $range ) {
if ( count( $locations ) >= $limit ) {
break;