예제 #1
0
 /**
  * @see JobQueue::doIsEmpty()
  * @return bool
  */
 protected function doIsEmpty()
 {
     $key = $this->getCacheKey('empty');
     $isEmpty = $this->cache->get($key);
     if ($isEmpty === 'true') {
         return true;
     } elseif ($isEmpty === 'false') {
         return false;
     }
     list($dbr, $scope) = $this->getSlaveDB();
     $found = $dbr->selectField('job', '1', array('job_cmd' => $this->type, 'job_token' => ''), __METHOD__);
     $this->cache->add($key, $found ? 'false' : 'true', self::CACHE_TTL_LONG);
     return !$found;
 }
 /**
  * @see JobQueueAggregator::doAllGetReadyWikiQueues()
  */
 protected function doGetAllReadyWikiQueues()
 {
     $key = $this->getReadyQueueCacheKey();
     // If the cache entry wasn't present, is stale, or in .1% of cases otherwise,
     // regenerate the cache. Use any available stale cache if another process is
     // currently regenerating the pending DB information.
     $pendingDbInfo = $this->cache->get($key);
     if (!is_array($pendingDbInfo) || time() - $pendingDbInfo['timestamp'] > $this->cacheTTL || mt_rand(0, 999) == 0) {
         if ($this->cache->add("{$key}:rebuild", 1, 1800)) {
             // lock
             $pendingDbInfo = array('pendingDBs' => $this->findPendingWikiQueues(), 'timestamp' => time());
             for ($attempts = 1; $attempts <= 25; ++$attempts) {
                 if ($this->cache->add("{$key}:lock", 1, 60)) {
                     // lock
                     $this->cache->set($key, $pendingDbInfo);
                     $this->cache->delete("{$key}:lock");
                     // unlock
                     break;
                 }
             }
             $this->cache->delete("{$key}:rebuild");
             // unlock
         }
     }
     return is_array($pendingDbInfo) ? $pendingDbInfo['pendingDBs'] : array();
     // cache is both empty and locked
 }
 /**
  * Set the cached stat info for a file path.
  * Negatives (404s) are not cached. By not caching negatives, we can skip cache
  * salting for the case when a file is created at a path were there was none before.
  *
  * @param $path string Storage path
  * @param $val mixed Information to cache
  */
 protected final function setFileCache($path, $val)
 {
     $path = FileBackend::normalizeStoragePath($path);
     if ($path === null) {
         return;
         // invalid storage path
     }
     $this->memCache->add($this->fileCacheKey($path), $val, 7 * 86400);
 }
예제 #4
0
	/**
	 * Set the cached stat info for a file path.
	 * Negatives (404s) are not cached. By not caching negatives, we can skip cache
	 * salting for the case when a file is created at a path were there was none before.
	 *
	 * @param string $path Storage path
	 * @param array $val Stat information to cache
	 * @return void
	 */
	final protected function setFileCache( $path, array $val ) {
		$path = FileBackend::normalizeStoragePath( $path );
		if ( $path === null ) {
			return; // invalid storage path
		}
		$age = time() - wfTimestamp( TS_UNIX, $val['mtime'] );
		$ttl = min( 7 * 86400, max( 300, floor( .1 * $age ) ) );
		$this->memCache->add( $this->fileCacheKey( $path ), $val, $ttl );
	}
예제 #5
0
 /**
  * Log a lock request failure to the cache
  *
  * @param $lockDb string
  * @return bool Success
  */
 protected function cacheRecordFailure($lockDb)
 {
     if ($this->statusCache && $this->safeDelay > 0) {
         $path = $this->getMissKey($lockDb);
         $misses = $this->statusCache->get($path);
         if ($misses) {
             return $this->statusCache->incr($path);
         } else {
             return $this->statusCache->add($path, 1, $this->safeDelay);
         }
     }
     return true;
 }
예제 #6
0
 /**
  * @covers BagOStuff::getMulti
  */
 public function testGetMulti()
 {
     $value1 = array('this' => 'is', 'a' => 'test');
     $value2 = array('this' => 'is', 'another' => 'test');
     $key1 = wfMemcKey('test1');
     $key2 = wfMemcKey('test2');
     $this->cache->add($key1, $value1);
     $this->cache->add($key2, $value2);
     $this->assertEquals($this->cache->getMulti(array($key1, $key2)), array($key1 => $value1, $key2 => $value2));
     // cleanup
     $this->cache->delete($key1);
     $this->cache->delete($key2);
 }
예제 #7
0
 /**
  * Get an authenticated connection handle to the Swift proxy
  *
  * @throws CloudFilesException
  * @throws CloudFilesException|Exception
  * @return CF_Connection|bool False on failure
  */
 protected function getConnection()
 {
     if ($this->connException instanceof CloudFilesException) {
         if (time() - $this->connErrorTime < 60) {
             throw $this->connException;
             // failed last attempt; don't bother
         } else {
             // actually retry this time
             $this->connException = null;
             $this->connErrorTime = 0;
         }
     }
     // Session keys expire after a while, so we renew them periodically
     $reAuth = time() - $this->sessionStarted > $this->authTTL;
     // Authenticate with proxy and get a session key...
     if (!$this->conn || $reAuth) {
         $this->sessionStarted = 0;
         $this->connContainerCache->clear();
         $cacheKey = $this->getCredsCacheKey($this->auth->username);
         $creds = $this->srvCache->get($cacheKey);
         // credentials
         if (is_array($creds)) {
             // cache hit
             $this->auth->load_cached_credentials($creds['auth_token'], $creds['storage_url'], $creds['cdnm_url']);
             $this->sessionStarted = time() - ceil($this->authTTL / 2);
             // skew for worst case
         } else {
             // cache miss
             try {
                 $this->auth->authenticate();
                 $creds = $this->auth->export_credentials();
                 $this->srvCache->add($cacheKey, $creds, ceil($this->authTTL / 2));
                 // cache
                 $this->sessionStarted = time();
             } catch (CloudFilesException $e) {
                 $this->connException = $e;
                 // don't keep re-trying
                 $this->connErrorTime = time();
                 throw $e;
                 // throw it back
             }
         }
         if ($this->conn) {
             // re-authorizing?
             $this->conn->close();
             // close active cURL handles in CF_Http object
         }
         $this->conn = new CF_Connection($this->auth);
     }
     return $this->conn;
 }
예제 #8
0
 protected function doIsEmpty()
 {
     $key = $this->getCacheKey('empty');
     $isEmpty = $this->cache->get($key);
     if ($isEmpty === 'true') {
         return true;
     } elseif ($isEmpty === 'false') {
         return false;
     }
     foreach ($this->partitionQueues as $queue) {
         if (!$queue->doIsEmpty()) {
             $this->cache->add($key, 'false', self::CACHE_TTL_LONG);
             return false;
         }
     }
     $this->cache->add($key, 'true', self::CACHE_TTL_LONG);
     return true;
 }
예제 #9
0
 /**
  * @see JobQueue::doIsEmpty()
  * @return bool
  */
 protected function doIsEmpty()
 {
     $key = $this->getCacheKey('empty');
     $isEmpty = $this->cache->get($key);
     if ($isEmpty === 'true') {
         return true;
     } elseif ($isEmpty === 'false') {
         return false;
     }
     $dbr = $this->getSlaveDB();
     try {
         $found = $dbr->selectField('job', '1', array('job_cmd' => $this->type, 'job_token' => ''), __METHOD__);
     } catch (DBError $e) {
         $this->throwDBException($e);
     }
     $this->cache->add($key, $found ? 'false' : 'true', self::CACHE_TTL_LONG);
     return !$found;
 }
예제 #10
0
 /**
  * @covers BagOStuff::getMulti
  */
 public function testGetMulti()
 {
     $value1 = array('this' => 'is', 'a' => 'test');
     $value2 = array('this' => 'is', 'another' => 'test');
     $value3 = array('testing a key that may be encoded when sent to cache backend');
     $key1 = wfMemcKey('test1');
     $key2 = wfMemcKey('test2');
     $key3 = wfMemcKey('will-%-encode');
     // internally, MemcachedBagOStuffs will encode to will-%25-encode
     $this->cache->add($key1, $value1);
     $this->cache->add($key2, $value2);
     $this->cache->add($key3, $value3);
     $this->assertEquals(array($key1 => $value1, $key2 => $value2, $key3 => $value3), $this->cache->getMulti(array($key1, $key2, $key3)));
     // cleanup
     $this->cache->delete($key1);
     $this->cache->delete($key2);
     $this->cache->delete($key3);
 }
 /**
  * Set the cached stat info for a file path.
  * Negatives (404s) are not cached. By not caching negatives, we can skip cache
  * salting for the case when a file is created at a path were there was none before.
  *
  * @param string $path Storage path
  * @param array $val Stat information to cache
  */
 protected final function setFileCache($path, array $val)
 {
     $path = FileBackend::normalizeStoragePath($path);
     if ($path === null) {
         return;
         // invalid storage path
     }
     $age = time() - wfTimestamp(TS_UNIX, $val['mtime']);
     $ttl = min(7 * 86400, max(300, floor(0.1 * $age)));
     $key = $this->fileCacheKey($path);
     // Set the cache unless it is currently salted with the value "PURGED".
     // Using add() handles this except it also is a no-op in that case where
     // the current value is not "latest" but $val is, so use CAS in that case.
     if (!$this->memCache->add($key, $val, $ttl) && !empty($val['latest'])) {
         $this->memCache->merge($key, function (BagOStuff $cache, $key, $cValue) use($val) {
             return is_array($cValue) && empty($cValue['latest']) ? $val : false;
             // do nothing (cache is salted or some error happened)
         }, $ttl, 1);
     }
 }
예제 #12
0
 /**
  * Represents a write lock on the messages key.
  *
  * Will retry MessageCache::MSG_WAIT_TIMEOUT times, each operations having
  * a timeout of MessageCache::MSG_LOCK_TIMEOUT.
  *
  * @param string $key
  * @return bool Success
  */
 function lock($key)
 {
     $lockKey = $key . ':lock';
     $acquired = false;
     $testDone = false;
     for ($i = 0; $i < MSG_WAIT_TIMEOUT && !$acquired; $i++) {
         $acquired = $this->mMemc->add($lockKey, 1, MSG_LOCK_TIMEOUT);
         if ($acquired) {
             break;
         }
         # Fail fast if memcached is totally down
         if (!$testDone) {
             $testDone = true;
             if (!$this->mMemc->set(wfMemcKey('test'), 'test', 1)) {
                 break;
             }
         }
         sleep(1);
     }
     return $acquired;
 }
예제 #13
0
 /**
  * @covers BagOStuff::getMulti
  */
 public function testGetMulti()
 {
     $value1 = ['this' => 'is', 'a' => 'test'];
     $value2 = ['this' => 'is', 'another' => 'test'];
     $value3 = ['testing a key that may be encoded when sent to cache backend'];
     $value4 = ['another test where chars in key will be encoded'];
     $key1 = wfMemcKey('test1');
     $key2 = wfMemcKey('test2');
     // internally, MemcachedBagOStuffs will encode to will-%25-encode
     $key3 = wfMemcKey('will-%-encode');
     $key4 = wfMemcKey('flowdb:flow_ref:wiki:by-source:v3:Parser\'s_"broken"_+_(page)_&_grill:testwiki:1:4.7');
     $this->cache->add($key1, $value1);
     $this->cache->add($key2, $value2);
     $this->cache->add($key3, $value3);
     $this->cache->add($key4, $value4);
     $this->assertEquals([$key1 => $value1, $key2 => $value2, $key3 => $value3, $key4 => $value4], $this->cache->getMulti([$key1, $key2, $key3, $key4]));
     // cleanup
     $this->cache->delete($key1);
     $this->cache->delete($key2);
     $this->cache->delete($key3);
     $this->cache->delete($key4);
 }
예제 #14
0
 protected function doIsEmpty()
 {
     $key = $this->getCacheKey('empty');
     $isEmpty = $this->cache->get($key);
     if ($isEmpty === 'true') {
         return true;
     } elseif ($isEmpty === 'false') {
         return false;
     }
     $empty = true;
     $failed = 0;
     foreach ($this->partitionQueues as $queue) {
         try {
             $empty = $empty && $queue->doIsEmpty();
         } catch (JobQueueError $e) {
             ++$failed;
             MWExceptionHandler::logException($e);
         }
     }
     $this->throwErrorIfAllPartitionsDown($failed);
     $this->cache->add($key, $empty ? 'true' : 'false', self::CACHE_TTL_LONG);
     return $empty;
 }
예제 #15
0
	protected function doIsEmpty() {
		$key = $this->getCacheKey( 'empty' );

		$isEmpty = $this->cache->get( $key );
		if ( $isEmpty === 'true' ) {
			return true;
		} elseif ( $isEmpty === 'false' ) {
			return false;
		}

		foreach ( $this->partitionQueues as $queue ) {
			try {
				if ( !$queue->doIsEmpty() ) {
					$this->cache->add( $key, 'false', self::CACHE_TTL_LONG );
					return false;
				}
			} catch ( JobQueueError $e ) {
				MWExceptionHandler::logException( $e );
			}
		}

		$this->cache->add( $key, 'true', self::CACHE_TTL_LONG );
		return true;
	}
예제 #16
0
 /**
  * Set the cached stat info for a file path.
  * Negatives (404s) are not cached. By not caching negatives, we can skip cache
  * salting for the case when a file is created at a path were there was none before.
  *
  * @param $path string Storage path
  * @param $val mixed Information to cache
  */
 protected final function setFileCache($path, $val)
 {
     $this->memCache->add($this->fileCacheKey($path), $val, 7 * 86400);
 }
예제 #17
0
 public function add($key, $value, $exptime = 0)
 {
     return $this->writeStore->add($key, $value, $exptime);
 }