47 $map = array_filter( $map,
function ( $w ) {
50 if ( !count( $map ) ) {
51 throw new UnexpectedValueException(
"Ring is empty or all weights are zero." );
53 $this->sourceMap = $map;
56 foreach ( $map as $location => $weight ) {
57 $hashes[$location] = sha1( $location );
59 uksort( $map,
function ( $a, $b ) use (
$hashes ) {
63 $sum = array_sum( $map );
65 foreach ( $map as $location => $weight ) {
66 $standardMap[$location] = (int)floor( $weight / $sum * self::RING_SIZE );
70 foreach ( $standardMap as $location => $weight ) {
72 $this->ring[$location] = [ $index, $index + $weight ];
101 $primaryLocation =
null;
102 $spot = hexdec( substr( sha1( $item ), 0, 7 ) );
103 foreach ( $this->ring as $location => $range ) {
104 if ( count( $locations ) >= $limit ) {
109 if ( ( $range[0] <= $spot && $spot < $range[1] ) || $primaryLocation !==
null ) {
110 if ( $primaryLocation ===
null ) {
111 $primaryLocation = $location;
113 $locations[] = $location;
117 reset( $this->ring );
118 while ( count( $locations ) < $limit ) {
119 $location =
key( $this->ring );
120 if ( $location === $primaryLocation ) {
123 $locations[] = $location;
147 if ( !isset( $this->sourceMap[$location] ) ) {
148 throw new UnexpectedValueException(
"No location '$location' in the ring." );
150 $expiry = time() + $ttl;
151 $this->liveRing =
null;
152 $this->ejectionExpiries[$location] = $expiry;
153 $this->ejectionNextExpiry = min( $expiry, $this->ejectionNextExpiry );
155 return ( count( $this->ejectionExpiries ) < count( $this->sourceMap ) );
166 if ( $this->liveRing ===
null || $this->ejectionNextExpiry <= $now ) {
167 $this->ejectionExpiries = array_filter(
168 $this->ejectionExpiries,
169 function ( $expiry ) use ( $now ) {
170 return ( $expiry > $now );
173 if ( count( $this->ejectionExpiries ) ) {
174 $map = array_diff_key( $this->sourceMap, $this->ejectionExpiries );
175 $this->liveRing = count( $map ) ?
new self( $map ) :
false;
177 $this->ejectionNextExpiry = min( $this->ejectionExpiries );
179 $this->liveRing = clone $this;
180 $this->liveRing->ejectionExpiries = [];
181 $this->liveRing->ejectionNextExpiry = INF;
182 $this->liveRing->liveRing =
null;
184 $this->ejectionNextExpiry = INF;
187 if ( !$this->liveRing ) {
188 throw new UnexpectedValueException(
"The live ring is currently empty." );
214 return $this->
getLiveRing()->getLocations( $item, $limit );
Convenience class for weighted consistent hash rings.
getLiveLocations( $item, $limit)
Get the location of an item on the "live" ring, as well as the next locations.
getLiveLocationWeights()
Get the map of "live" locations to weight (ignores 0-weight items)
int $ejectionNextExpiry
UNIX timestamp.
getLiveLocation( $item)
Get the location of an item on the "live" ring.
array $sourceMap
(location => weight)
getLocation( $item)
Get the location of an item on the ring.
array $ejectionExpiries
(location => UNIX timestamp)
getLocations( $item, $limit)
Get the location of an item on the ring, as well as the next locations.
array $ring
(location => (start, end))
getLocationWeights()
Get the map of locations to weight (ignores 0-weight items)
getLiveRing()
Get the "live" hash ring (which does not include ejected locations)
ejectFromLiveRing( $location, $ttl)
Remove a location from the "live" hash ring.
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add in any and then calling but I prefer the flexibility This should also do the output encoding The system allocates a global one in $wgOut Title Represents the title of an and does all the work of translating among various forms such as plain database key