41 $map = array_filter( $map,
function ( $w ) {
44 if ( !count( $map ) ) {
45 throw new UnexpectedValueException(
"Ring is empty or all weights are zero." );
47 $this->sourceMap = $map;
50 foreach ( $map
as $location => $weight ) {
51 $hashes[$location] = sha1( $location );
53 uksort( $map,
function ( $a, $b ) use (
$hashes ) {
57 $sum = array_sum( $map );
58 $standardMap =
array();
59 foreach ( $map
as $location => $weight ) {
60 $standardMap[$location] = (int)floor( $weight / $sum * self::RING_SIZE );
64 foreach ( $standardMap
as $location => $weight ) {
66 $this->ring[$location] =
array( $index, $index + $weight );
95 $primaryLocation =
null;
96 $spot = hexdec( substr( sha1( $item ), 0, 7 ) );
97 foreach ( $this->ring
as $location => $range ) {
98 if ( count( $locations ) >=
$limit ) {
103 if ( ( $range[0] <= $spot && $spot < $range[1] ) || $primaryLocation !==
null ) {
104 if ( $primaryLocation ===
null ) {
105 $primaryLocation = $location;
107 $locations[] = $location;
111 reset( $this->ring );
112 while ( count( $locations ) <
$limit ) {
113 list( $location, ) = each( $this->ring );
114 if ( $location === $primaryLocation ) {
117 $locations[] = $location;
140 unset( $map[$location] );
141 if ( count( $map ) ) {
142 return new self( $map );