MediaWiki  master
PoolCounter.php
Go to the documentation of this file.
1 <?php
22 
51 abstract class PoolCounter {
52  /* Return codes */
53  public const LOCKED = 1; /* Lock acquired */
54  public const RELEASED = 2; /* Lock released */
55  public const DONE = 3; /* Another worker did the work for you */
56 
57  public const ERROR = -1; /* Indeterminate error */
58  public const NOT_LOCKED = -2; /* Called release() with no lock held */
59  public const QUEUE_FULL = -3; /* There are already maxqueue workers on this lock */
60  public const TIMEOUT = -4; /* Timeout exceeded */
61  public const LOCK_HELD = -5; /* Cannot acquire another lock while you have one lock held */
62 
64  protected $key;
66  protected $workers;
73  protected $slots = 0;
75  protected $maxqueue;
77  protected $timeout;
78 
82  private $isMightWaitKey;
86  private static $acquiredMightWaitKey = 0;
87 
91  private $fastStale;
92 
98  public function __construct( array $conf, string $type, string $key ) {
99  $this->workers = $conf['workers'];
100  $this->maxqueue = $conf['maxqueue'];
101  $this->timeout = $conf['timeout'];
102  if ( isset( $conf['slots'] ) ) {
103  $this->slots = $conf['slots'];
104  }
105  $this->fastStale = $conf['fastStale'] ?? false;
106 
107  if ( $this->slots ) {
108  $key = $this->hashKeyIntoSlots( $type, $key, $this->slots );
109  }
110 
111  $this->key = $key;
112  $this->isMightWaitKey = !preg_match( '/^nowait:/', $this->key );
113  }
114 
118  public function getKey() {
119  return $this->key;
120  }
121 
129  abstract public function acquireForMe( $timeout = null );
130 
139  abstract public function acquireForAnyone( $timeout = null );
140 
148  abstract public function release();
149 
155  final protected function precheckAcquire() {
156  if ( $this->isMightWaitKey ) {
157  if ( self::$acquiredMightWaitKey ) {
158  /*
159  * The poolcounter itself is quite happy to allow you to wait
160  * on another lock while you have a lock you waited on already
161  * but we think that it is unlikely to be a good idea. So we
162  * made it an error. If you are _really_ _really_ sure it is a
163  * good idea then feel free to implement an unsafe flag or
164  * something.
165  */
166  return Status::newFatal( 'poolcounter-usage-error',
167  'You may only aquire a single non-nowait lock.' );
168  }
169  } elseif ( $this->timeout !== 0 ) {
170  return Status::newFatal( 'poolcounter-usage-error',
171  'Locks starting in nowait: must have 0 timeout.' );
172  }
173  return Status::newGood();
174  }
175 
180  final protected function onAcquire() {
181  self::$acquiredMightWaitKey |= $this->isMightWaitKey;
182  }
183 
188  final protected function onRelease() {
189  self::$acquiredMightWaitKey &= !$this->isMightWaitKey;
190  }
191 
204  protected function hashKeyIntoSlots( $type, $key, $slots ) {
205  return $type . ':' . ( hexdec( substr( sha1( $key ), 0, 4 ) ) % $slots );
206  }
207 
214  public function isFastStaleEnabled() {
215  return $this->fastStale;
216  }
217 }
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:58
Semaphore semantics to restrict how many workers may concurrently perform a task.
Definition: PoolCounter.php:51
const QUEUE_FULL
Definition: PoolCounter.php:59
int $workers
Maximum number of workers working on tasks with the same key simultaneously.
Definition: PoolCounter.php:66
acquireForAnyone( $timeout=null)
I want to do this task, but if anyone else does it instead, it's also fine for me.
const LOCKED
Definition: PoolCounter.php:53
onAcquire()
Update any lock tracking information when the lock is acquired.
const TIMEOUT
Definition: PoolCounter.php:60
__construct(array $conf, string $type, string $key)
Definition: PoolCounter.php:98
int $maxqueue
If this number of workers are already working/waiting, fail instead of wait.
Definition: PoolCounter.php:75
isFastStaleEnabled()
Is fast stale mode (T250248) enabled? This may be overridden by the PoolCounterWork subclass.
string $key
All workers with the same key share the lock.
Definition: PoolCounter.php:64
const RELEASED
Definition: PoolCounter.php:54
int $slots
Maximum number of workers working on this task type, regardless of key.
Definition: PoolCounter.php:73
hashKeyIntoSlots( $type, $key, $slots)
Given a key (any string) and the number of lots, returns a slot key (a prefix with a suffix integer f...
release()
I have successfully finished my task.
precheckAcquire()
Checks that the lock request is sensible.
acquireForMe( $timeout=null)
I want to do this task and I need to do it myself.
const NOT_LOCKED
Definition: PoolCounter.php:58
int $timeout
Maximum time in seconds to wait for the lock.
Definition: PoolCounter.php:77
const LOCK_HELD
Definition: PoolCounter.php:61
onRelease()
Update any lock tracking information when the lock is released.