/** * Add a list of targets. * @param array $targets * @chainable */ publicfunctionaddTargets($targets) { foreach ($targets as $target) { $this->addTarget($target); }
return$this; }
/** * Remove a target. * @param string $target * @chainable */ publicfunctionremoveTarget($target) { if (!isset($this->_targetToPositions[$target])) { thrownew Flexihash_Exception("Target '$target' does not exist."); }
foreach ($this->_targetToPositions[$target] as $position) { unset($this->_positionToTarget[$position]); }
unset($this->_targetToPositions[$target]);
$this->_targetCount--;
return$this; }
/** * A list of all potential targets * @return array */ publicfunctiongetAllTargets() { return array_keys($this->_targetToPositions); }
/** * Looks up the target for the given resource. * @param string $resource * @return string */ publicfunctionlookup($resource) { $targets = $this->lookupList($resource, 1); if (empty($targets)) thrownew Flexihash_Exception('No targets exist'); return $targets[0]; }
/** * Get a list of targets for the resource, in order of precedence. * Up to $requestedCount targets are returned, less if there are fewer in total. * * @param string $resource * @param int $requestedCount The length of the list to return * @return array List of targets * @comment 查找当前的资源对应的节点, * 节点为空则返回空,节点只有一个则返回该节点, * 对当前资源进行hash,对所有的位置进行排序,在有序的位置列上寻找当前资源的位置 * 当全部没有找到的时候,将资源的位置确定为有序位置的第一个(形成一个环) * 返回所找到的节点 */ publicfunctionlookupList($resource, $requestedCount) { if (!$requestedCount) thrownew Flexihash_Exception('Invalid count requested');
// handle no targets if (empty($this->_positionToTarget)) returnarray();
// optimize single target if ($this->_targetCount == 1) return array_unique(array_values($this->_positionToTarget));
// hash resource to a position $resourcePosition = $this->_hasher->hash($resource);
$results = array(); $collect = false;
$this->_sortPositionTargets();
// search values above the resourcePosition foreach ($this->_positionToTarget as $key => $value) { // start collecting targets after passing resource position if (!$collect && $key > $resourcePosition) { $collect = true; }
// only collect the first instance of any target if ($collect && !in_array($value, $results)) { $results []= $value; }
// return when enough results, or list exhausted if (count($results) == $requestedCount || count($results) == $this->_targetCount) { return $results; } }
// loop to start - search values below the resourcePosition foreach ($this->_positionToTarget as $key => $value) { if (!in_array($value, $results)) { $results []= $value; }
// return when enough results, or list exhausted if (count($results) == $requestedCount || count($results) == $this->_targetCount) { return $results; } }
// return results after iterating through both "parts" return $results; }
/** * Sorts the internal mapping (positions to targets) by position */ privatefunction_sortPositionTargets() { // sort by key (position) if not already if (!$this->_positionToTargetSorted) { ksort($this->_positionToTarget, SORT_REGULAR); $this->_positionToTargetSorted = true; } }
}
/** * Hashes given values into a sortable fixed size address space. * * @author Paul Annesley * @package Flexihash * @licence http://www.opensource.org/licenses/mit-license.php */ interfaceFlexihash_Hasher {
/** * Hashes the given string into a 32bit address space. * * Note that the output may be more than 32bits of raw data, for example * hexidecimal characters representing a 32bit value. * * The data must have 0xFFFFFFFF possible values, and be sortable by * PHP sort functions using SORT_REGULAR. * * @param string * @return mixed A sortable format with 0xFFFFFFFF possible values */ publicfunctionhash($string);
}
/** * Uses CRC32 to hash a value into a signed 32bit int address space. * Under 32bit PHP this (safely) overflows into negatives ints. * * @author Paul Annesley * @package Flexihash * @licence http://www.opensource.org/licenses/mit-license.php */ classFlexihash_Crc32Hasher implementsFlexihash_Hasher {
/** * Uses CRC32 to hash a value into a 32bit binary string data address space. * * @author Paul Annesley * @package Flexihash * @licence http://www.opensource.org/licenses/mit-license.php */ classFlexihash_Md5Hasher implementsFlexihash_Hasher {