key = $key; $this->workers = $conf['workers']; $this->maxqueue = $conf['maxqueue']; $this->timeout = $conf['timeout']; } } class PoolCounter_Stub extends PoolCounter { /** * @return Status */ function acquireForMe() { return Status::newGood( PoolCounter::LOCKED ); } /** * @return Status */ function acquireForAnyone() { return Status::newGood( PoolCounter::LOCKED ); } /** * @return Status */ function release() { return Status::newGood( PoolCounter::RELEASED ); } public function __construct() { /* No parameters needed */ } } /** * Handy class for dealing with PoolCounters using class members instead of callbacks. */ abstract class PoolCounterWork { protected $cacheable = false; //Does this override getCachedWork() ? /** * Actually perform the work, caching it if needed. */ abstract function doWork(); /** * Retrieve the work from cache * @return mixed work result or false */ function getCachedWork() { return false; } /** * A work not so good (eg. expired one) but better than an error * message. * @return mixed work result or false */ function fallback() { return false; } /** * Do something with the error, like showing it to the user. * @return bool */ function error( $status ) { return false; } /** * Log an error * * @param $status Status */ function logError( $status ) { wfDebugLog( 'poolcounter', $status->getWikiText() ); } /** * Get the result of the work (whatever it is), or false. * @param $skipcache bool * @return bool|mixed */ function execute( $skipcache = false ) { if ( $this->cacheable && !$skipcache ) { $status = $this->poolCounter->acquireForAnyone(); } else { $status = $this->poolCounter->acquireForMe(); } if ( !$status->isOK() ) { // Respond gracefully to complete server breakage: just log it and do the work $this->logError( $status ); return $this->doWork(); } switch ( $status->value ) { case PoolCounter::LOCKED: $result = $this->doWork(); $this->poolCounter->release(); return $result; case PoolCounter::DONE: $result = $this->getCachedWork(); if ( $result === false ) { /* That someone else work didn't serve us. * Acquire the lock for me */ return $this->execute( true ); } return $result; case PoolCounter::QUEUE_FULL: case PoolCounter::TIMEOUT: $result = $this->fallback(); if ( $result !== false ) { return $result; } /* no break */ /* These two cases should never be hit... */ case PoolCounter::ERROR: default: $errors = array( PoolCounter::QUEUE_FULL => 'pool-queuefull', PoolCounter::TIMEOUT => 'pool-timeout' ); $status = Status::newFatal( isset( $errors[$status->value] ) ? $errors[$status->value] : 'pool-errorunknown' ); $this->logError( $status ); return $this->error( $status ); } } function __construct( $type, $key ) { $this->poolCounter = PoolCounter::factory( $type, $key ); } }