X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fpoolcounter%2FPoolCounter.php;h=1ec14aa1480d63a37662ff594b46a10eed87e011;hb=c4f69827bc670fc0bed322d31cb1173bcd43db24;hp=e77ffd7cd6cb548c7973b91cbfd34cf27a28dbc9;hpb=627e33ed363478f54ec4053454b3f5f9f466cbd3;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/poolcounter/PoolCounter.php b/includes/poolcounter/PoolCounter.php index e77ffd7cd6..1ec14aa148 100644 --- a/includes/poolcounter/PoolCounter.php +++ b/includes/poolcounter/PoolCounter.php @@ -34,7 +34,10 @@ * minutes and hundreds of read hits. * * The PoolCounter provides semaphore semantics for restricting the number - * of workers that may be concurrently performing such single task. + * of workers that may be concurrently performing such single task. Only one + * key can be locked by any PoolCounter instance of a process, except for keys + * that start with "nowait:". However, only 0 timeouts (non-blocking requests) + * can be used with "nowait:" keys. * * By default PoolCounter_Stub is used, which provides no locking. You * can get a useful one in the PoolCounter extension. @@ -67,6 +70,15 @@ abstract class PoolCounter { /** @var float Maximum time in seconds to wait for the lock */ protected $timeout; + /** + * @var boolean Whether the key is a "might wait" key + */ + private $isMightWaitKey; + /** + * @var boolean Whether this process holds a "might wait" lock key + */ + private static $acquiredMightWaitKey = 0; + /** * @param array $conf * @param string $type @@ -84,6 +96,7 @@ abstract class PoolCounter { $key = $this->hashKeyIntoSlots( $key, $this->slots ); } $this->key = $key; + $this->isMightWaitKey = !preg_match( '/^nowait:/', $this->key ); } /** @@ -137,10 +150,53 @@ abstract class PoolCounter { abstract public function release(); /** - * Given a key (any string) and the number of lots, returns a slot number (an integer from the [0..($slots-1)] range). - * This is used for a global limit on the number of instances of a given type that can acquire a lock. - * The hashing is deterministic so that PoolCounter::$workers is always an upper limit of how many instances with - * the same key can acquire a lock. + * Checks that the lock request is sane. + * @return Status - good for sane requests fatal for insane + * @since 1.25 + */ + final protected function precheckAcquire() { + if ( $this->isMightWaitKey ) { + if ( self::$acquiredMightWaitKey ) { + /* + * The poolcounter itself is quite happy to allow you to wait + * on another lock while you have a lock you waited on already + * but we think that it is unlikely to be a good idea. So we + * made it an error. If you are _really_ _really_ sure it is a + * good idea then feel free to implement an unsafe flag or + * something. + */ + return Status::newFatal( 'poolcounter-usage-error', + 'You may only aquire a single non-nowait lock.' ); + } + } elseif ( $this->timeout !== 0 ) { + return Status::newFatal( 'poolcounter-usage-error', + 'Locks starting in nowait: must have 0 timeout.' ); + } + return Status::newGood(); + } + + /** + * Update any lock tracking information when the lock is acquired + * @since 1.25 + */ + final protected function onAcquire() { + self::$acquiredMightWaitKey |= $this->isMightWaitKey; + } + + /** + * Update any lock tracking information when the lock is released + * @since 1.25 + */ + final protected function onRelease() { + self::$acquiredMightWaitKey &= !$this->isMightWaitKey; + } + + /** + * Given a key (any string) and the number of lots, returns a slot number (an integer from + * the [0..($slots-1)] range). This is used for a global limit on the number of instances of + * a given type that can acquire a lock. The hashing is deterministic so that + * PoolCounter::$workers is always an upper limit of how many instances with the same key + * can acquire a lock. * * @param string $key PoolCounter instance key (any string) * @param int $slots The number of slots (max allowed value is 65536)