key = $key; $this->workers = $conf['workers']; $this->maxqueue = $conf['maxqueue']; $this->timeout = $conf['timeout']; } } class PoolCounter_Stub extends PoolCounter { function acquireForMe() { return Status::newGood( PoolCounter::LOCKED ); } function acquireForAnyone() { return Status::newGood( PoolCounter::LOCKED ); } 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. */ function error( $status ) { return false; } /** * Get the result of the work (whatever it is), or false. */ function execute( $skipcache = false ) { if ( $this->cacheable && !$skipcache ) { $status = $this->poolCounter->acquireForAnyone(); } else { $status = $this->poolCounter->acquireForMe(); } if ( $status->isOK() ) { 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' ); /* continue to the error */ } } return $this->error( $status ); } function __construct( $type, $key ) { $this->poolCounter = PoolCounter::factory( $type, $key ); } }