From fbf97f572cd26f3dadd323ee31036ba7a1d9d11f Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Wed, 2 Apr 2014 11:08:22 -0700 Subject: [PATCH] Re-organized PoolCounter files * No actual changes to the classes Change-Id: I4e35a2b097e4bc72315688d0390d3f5c4c1ca4ed --- includes/AutoLoader.php | 10 +- includes/poolcounter/PoolCounter.php | 142 ++++++++++++++++++ .../{ => poolcounter}/PoolCounterRedis.php | 0 .../PoolCounterWork.php} | 120 --------------- 4 files changed, 147 insertions(+), 125 deletions(-) create mode 100644 includes/poolcounter/PoolCounter.php rename includes/{ => poolcounter}/PoolCounterRedis.php (100%) rename includes/{PoolCounter.php => poolcounter/PoolCounterWork.php} (64%) diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index d9bb4bf613..b7d7d8c762 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -155,11 +155,11 @@ $wgAutoloadLocalClasses = array( 'PathRouter' => 'includes/PathRouter.php', 'PathRouterPatternReplacer' => 'includes/PathRouter.php', 'PhpHttpRequest' => 'includes/HttpFunctions.php', - 'PoolCounter' => 'includes/PoolCounter.php', - 'PoolCounter_Stub' => 'includes/PoolCounter.php', - 'PoolCounterRedis' => 'includes/PoolCounterRedis.php', - 'PoolCounterWork' => 'includes/PoolCounter.php', - 'PoolCounterWorkViaCallback' => 'includes/PoolCounter.php', + 'PoolCounter' => 'includes/poolcounter/PoolCounter.php', + 'PoolCounter_Stub' => 'includes/poolcounter/PoolCounter.php', + 'PoolCounterRedis' => 'includes/poolcounter/PoolCounterRedis.php', + 'PoolCounterWork' => 'includes/poolcounter/PoolCounterWork.php', + 'PoolCounterWorkViaCallback' => 'includes/poolcounter/PoolCounterWork.php', 'PoolWorkArticleView' => 'includes/WikiPage.php', 'Preferences' => 'includes/Preferences.php', 'PreferencesForm' => 'includes/Preferences.php', diff --git a/includes/poolcounter/PoolCounter.php b/includes/poolcounter/PoolCounter.php new file mode 100644 index 0000000000..1b209e4d04 --- /dev/null +++ b/includes/poolcounter/PoolCounter.php @@ -0,0 +1,142 @@ +key = $key; + $this->workers = $conf['workers']; + $this->maxqueue = $conf['maxqueue']; + $this->timeout = $conf['timeout']; + } + + /** + * Create a Pool counter. This should only be called from the PoolWorks. + * + * @param $type + * @param $key + * + * @return PoolCounter + */ + public static function factory( $type, $key ) { + global $wgPoolCounterConf; + if ( !isset( $wgPoolCounterConf[$type] ) ) { + return new PoolCounter_Stub; + } + $conf = $wgPoolCounterConf[$type]; + $class = $conf['class']; + + return new $class( $conf, $type, $key ); + } + + /** + * @return string + */ + public function getKey() { + return $this->key; + } + + /** + * I want to do this task and I need to do it myself. + * + * @return Status Value is one of Locked/Error + */ + abstract public function acquireForMe(); + + /** + * I want to do this task, but if anyone else does it + * instead, it's also fine for me. I will read its cached data. + * + * @return Status Value is one of Locked/Done/Error + */ + abstract public function acquireForAnyone(); + + /** + * I have successfully finished my task. + * Lets another one grab the lock, and returns the workers + * waiting on acquireForAnyone() + * + * @return Status value is one of Released/NotLocked/Error + */ + abstract public function release(); +} + +class PoolCounter_Stub extends PoolCounter { + public function __construct() { + /* No parameters needed */ + } + + public function acquireForMe() { + return Status::newGood( PoolCounter::LOCKED ); + } + + public function acquireForAnyone() { + return Status::newGood( PoolCounter::LOCKED ); + } + + public function release() { + return Status::newGood( PoolCounter::RELEASED ); + } +} diff --git a/includes/PoolCounterRedis.php b/includes/poolcounter/PoolCounterRedis.php similarity index 100% rename from includes/PoolCounterRedis.php rename to includes/poolcounter/PoolCounterRedis.php diff --git a/includes/PoolCounter.php b/includes/poolcounter/PoolCounterWork.php similarity index 64% rename from includes/PoolCounter.php rename to includes/poolcounter/PoolCounterWork.php index 85c4c79a34..50ddd90a77 100644 --- a/includes/PoolCounter.php +++ b/includes/poolcounter/PoolCounterWork.php @@ -21,126 +21,6 @@ * @file */ -/** - * When you have many workers (threads/servers) giving service, and a - * cached item expensive to produce expires, you may get several workers - * doing the job at the same time. - * - * Given enough requests and the item expiring fast (non-cacheable, - * lots of edits...) that single work can end up unfairly using most (all) - * of the cpu of the pool. This is also known as 'Michael Jackson effect' - * since this effect triggered on the english wikipedia on the day Michael - * Jackson died, the biographical article got hit with several edits per - * 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. - * - * By default PoolCounter_Stub is used, which provides no locking. You - * can get a useful one in the PoolCounter extension. - */ -abstract class PoolCounter { - /* Return codes */ - const LOCKED = 1; /* Lock acquired */ - const RELEASED = 2; /* Lock released */ - const DONE = 3; /* Another worker did the work for you */ - - const ERROR = -1; /* Indeterminate error */ - const NOT_LOCKED = -2; /* Called release() with no lock held */ - const QUEUE_FULL = -3; /* There are already maxqueue workers on this lock */ - const TIMEOUT = -4; /* Timeout exceeded */ - const LOCK_HELD = -5; /* Cannot acquire another lock while you have one lock held */ - - /** @var string All workers with the same key share the lock */ - protected $key; - /** @var integer Maximum number of workers doing the task simultaneously */ - protected $workers; - /** @var integer If this number of workers are already working/waiting, fail instead of wait */ - protected $maxqueue; - /** @var float Maximum time in seconds to wait for the lock */ - protected $timeout; - - /** - * @param array $conf - * @param string $type - * @param string $key - */ - protected function __construct( $conf, $type, $key ) { - $this->key = $key; - $this->workers = $conf['workers']; - $this->maxqueue = $conf['maxqueue']; - $this->timeout = $conf['timeout']; - } - - /** - * Create a Pool counter. This should only be called from the PoolWorks. - * - * @param $type - * @param $key - * - * @return PoolCounter - */ - public static function factory( $type, $key ) { - global $wgPoolCounterConf; - if ( !isset( $wgPoolCounterConf[$type] ) ) { - return new PoolCounter_Stub; - } - $conf = $wgPoolCounterConf[$type]; - $class = $conf['class']; - - return new $class( $conf, $type, $key ); - } - - /** - * @return string - */ - public function getKey() { - return $this->key; - } - - /** - * I want to do this task and I need to do it myself. - * - * @return Status Value is one of Locked/Error - */ - abstract public function acquireForMe(); - - /** - * I want to do this task, but if anyone else does it - * instead, it's also fine for me. I will read its cached data. - * - * @return Status Value is one of Locked/Done/Error - */ - abstract public function acquireForAnyone(); - - /** - * I have successfully finished my task. - * Lets another one grab the lock, and returns the workers - * waiting on acquireForAnyone() - * - * @return Status value is one of Released/NotLocked/Error - */ - abstract public function release(); -} - -class PoolCounter_Stub extends PoolCounter { - public function __construct() { - /* No parameters needed */ - } - - public function acquireForMe() { - return Status::newGood( PoolCounter::LOCKED ); - } - - public function acquireForAnyone() { - return Status::newGood( PoolCounter::LOCKED ); - } - - public function release() { - return Status::newGood( PoolCounter::RELEASED ); - } -} - /** * Class for dealing with PoolCounters using class members */ -- 2.20.1