[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/poolcounter/ -> PoolCounterWork.php (source)

   1  <?php
   2  /**
   3   * Provides of semaphore semantics for restricting the number
   4   * of workers that may be concurrently performing the same task.
   5   *
   6   * This program is free software; you can redistribute it and/or modify
   7   * it under the terms of the GNU General Public License as published by
   8   * the Free Software Foundation; either version 2 of the License, or
   9   * (at your option) any later version.
  10   *
  11   * This program is distributed in the hope that it will be useful,
  12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14   * GNU General Public License for more details.
  15   *
  16   * You should have received a copy of the GNU General Public License along
  17   * with this program; if not, write to the Free Software Foundation, Inc.,
  18   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19   * http://www.gnu.org/copyleft/gpl.html
  20   *
  21   * @file
  22   */
  23  
  24  /**
  25   * Class for dealing with PoolCounters using class members
  26   */
  27  abstract class PoolCounterWork {
  28      /** @var string */
  29      protected $type = 'generic';
  30      /** @var bool */
  31      protected $cacheable = false; // does this override getCachedWork() ?
  32  
  33      /**
  34       * @param string $type The type of PoolCounter to use
  35       * @param string $key Key that identifies the queue this work is placed on
  36       */
  37  	public function __construct( $type, $key ) {
  38          $this->type = $type;
  39          $this->poolCounter = PoolCounter::factory( $type, $key );
  40      }
  41  
  42      /**
  43       * Actually perform the work, caching it if needed
  44       * @return mixed Work result or false
  45       */
  46      abstract public function doWork();
  47  
  48      /**
  49       * Retrieve the work from cache
  50       * @return mixed Work result or false
  51       */
  52  	public function getCachedWork() {
  53          return false;
  54      }
  55  
  56      /**
  57       * A work not so good (eg. expired one) but better than an error
  58       * message.
  59       * @return mixed Work result or false
  60       */
  61  	public function fallback() {
  62          return false;
  63      }
  64  
  65      /**
  66       * Do something with the error, like showing it to the user.
  67       *
  68       * @param Status $status
  69       *
  70       * @return bool
  71       */
  72  	public function error( $status ) {
  73          return false;
  74      }
  75  
  76      /**
  77       * Log an error
  78       *
  79       * @param Status $status
  80       * @return void
  81       */
  82  	public function logError( $status ) {
  83          $key = $this->poolCounter->getKey();
  84  
  85          wfDebugLog( 'poolcounter', "Pool key '$key' ({$this->type}): "
  86              . $status->getMessage()->inLanguage( 'en' )->useDatabase( false )->text() );
  87      }
  88  
  89      /**
  90       * Get the result of the work (whatever it is), or the result of the error() function.
  91       * This returns the result of the first applicable method that returns a non-false value,
  92       * where the methods are checked in the following order:
  93       *   - a) doWork()       : Applies if the work is exclusive or no another process
  94       *                         is doing it, and on the condition that either this process
  95       *                         successfully entered the pool or the pool counter is down.
  96       *   - b) doCachedWork() : Applies if the work is cacheable and this blocked on another
  97       *                         process which finished the work.
  98       *   - c) fallback()     : Applies for all remaining cases.
  99       * If these all fall through (by returning false), then the result of error() is returned.
 100       *
 101       * @param bool $skipcache
 102       * @return mixed
 103       */
 104  	public function execute( $skipcache = false ) {
 105          if ( $this->cacheable && !$skipcache ) {
 106              $status = $this->poolCounter->acquireForAnyone();
 107          } else {
 108              $status = $this->poolCounter->acquireForMe();
 109          }
 110  
 111          if ( !$status->isOK() ) {
 112              // Respond gracefully to complete server breakage: just log it and do the work
 113              $this->logError( $status );
 114              return $this->doWork();
 115          }
 116  
 117          switch ( $status->value ) {
 118              case PoolCounter::LOCK_HELD:
 119                  // Better to ignore nesting pool counter limits than to fail.
 120                  // Assume that the outer pool limiting is reasonable enough.
 121                  /* no break */
 122              case PoolCounter::LOCKED:
 123                  $result = $this->doWork();
 124                  $this->poolCounter->release();
 125                  return $result;
 126  
 127              case PoolCounter::DONE:
 128                  $result = $this->getCachedWork();
 129                  if ( $result === false ) {
 130                      /* That someone else work didn't serve us.
 131                       * Acquire the lock for me
 132                       */
 133                      return $this->execute( true );
 134                  }
 135                  return $result;
 136  
 137              case PoolCounter::QUEUE_FULL:
 138              case PoolCounter::TIMEOUT:
 139                  $result = $this->fallback();
 140  
 141                  if ( $result !== false ) {
 142                      return $result;
 143                  }
 144                  /* no break */
 145  
 146              /* These two cases should never be hit... */
 147              case PoolCounter::ERROR:
 148              default:
 149                  $errors = array(
 150                      PoolCounter::QUEUE_FULL => 'pool-queuefull',
 151                      PoolCounter::TIMEOUT => 'pool-timeout' );
 152  
 153                  $status = Status::newFatal( isset( $errors[$status->value] )
 154                      ? $errors[$status->value]
 155                      : 'pool-errorunknown' );
 156                  $this->logError( $status );
 157                  return $this->error( $status );
 158          }
 159      }
 160  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1