Aaron Schulz has uploaded a new change for review. https://gerrit.wikimedia.org/r/181209
Change subject: Moved "nowait:" key code to PoolCounter in core ...................................................................... Moved "nowait:" key code to PoolCounter in core Change-Id: I5286e6c6052289e1107314a04d72703b44a8fbc6 --- M includes/poolcounter/PoolCounter.php M includes/poolcounter/PoolCounterRedis.php 2 files changed, 70 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/09/181209/1 diff --git a/includes/poolcounter/PoolCounter.php b/includes/poolcounter/PoolCounter.php index e77ffd7..5692d73 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. @@ -68,6 +71,15 @@ 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 * @param string $key @@ -84,6 +96,7 @@ $key = $this->hashKeyIntoSlots( $key, $this->slots ); } $this->key = $key; + $this->isMightWaitKey = !preg_match( '/^nowait:/', $this->key ); } /** @@ -137,6 +150,48 @@ abstract public function release(); /** + * 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 diff --git a/includes/poolcounter/PoolCounterRedis.php b/includes/poolcounter/PoolCounterRedis.php index d609f61..0f025f3 100644 --- a/includes/poolcounter/PoolCounterRedis.php +++ b/includes/poolcounter/PoolCounterRedis.php @@ -123,11 +123,21 @@ function acquireForMe() { $section = new ProfileSection( __METHOD__ ); + $status = $this->precheckAcquire(); + if ( !$status->isGood() ) { + return $status; + } + return $this->waitForSlotOrNotif( self::AWAKE_ONE ); } function acquireForAnyone() { $section = new ProfileSection( __METHOD__ ); + + $status = $this->precheckAcquire(); + if ( !$status->isGood() ) { + return $status; + } return $this->waitForSlotOrNotif( self::AWAKE_ALL ); } @@ -207,6 +217,8 @@ $this->onRelease = null; unset( self::$active[$this->session] ); + $this->onRelease(); + return Status::newGood( PoolCounter::RELEASED ); } @@ -266,6 +278,8 @@ self::$active[$this->session] = $this; } + $this->onAcquire(); + return Status::newGood( $slot === 'w' ? PoolCounter::DONE : PoolCounter::LOCKED ); } -- To view, visit https://gerrit.wikimedia.org/r/181209 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I5286e6c6052289e1107314a04d72703b44a8fbc6 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Aaron Schulz <asch...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits