'body' => $params['content']
) );
- $be = $this;
+ $that = $this;
$method = __METHOD__;
- $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $that, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $rcode === 201 ) {
// good
} elseif ( $rcode === 412 ) {
$status->fatal( 'backend-fail-contenttype', $params['dst'] );
} else {
- $be->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+ $that->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
}
};
'body' => $handle // resource
) );
- $be = $this;
+ $that = $this;
$method = __METHOD__;
- $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $that, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $rcode === 201 ) {
// good
} elseif ( $rcode === 412 ) {
$status->fatal( 'backend-fail-contenttype', $params['dst'] );
} else {
- $be->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+ $that->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
}
};
) + $this->sanitizeHdrs( $params ), // extra headers merged into object
) );
- $be = $this;
+ $that = $this;
$method = __METHOD__;
- $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $that, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $rcode === 201 ) {
// good
} elseif ( $rcode === 404 ) {
$status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
} else {
- $be->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+ $that->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
}
};
);
}
- $be = $this;
+ $that = $this;
$method = __METHOD__;
- $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $that, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $request['method'] === 'PUT' && $rcode === 201 ) {
// good
} elseif ( $rcode === 404 ) {
$status->fatal( 'backend-fail-move', $params['src'], $params['dst'] );
} else {
- $be->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+ $that->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
}
};
'headers' => array()
) );
- $be = $this;
+ $that = $this;
$method = __METHOD__;
- $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $that, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $rcode === 204 ) {
// good
$status->fatal( 'backend-fail-delete', $params['src'] );
}
} else {
- $be->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+ $that->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
}
};
'headers' => $metaHdrs + $customHdrs
) );
- $be = $this;
+ $that = $this;
$method = __METHOD__;
- $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $that, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $rcode === 202 ) {
// good
} elseif ( $rcode === 404 ) {
$status->fatal( 'backend-fail-describe', $params['src'] );
} else {
- $be->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+ $that->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
}
};
);
};
- $repo = $this;
+ $that = $this;
$applyMatchingFiles = function ( ResultWrapper $res, &$searchSet, &$finalFiles )
- use ( $repo, $fileMatchesSearch, $flags )
+ use ( $that, $fileMatchesSearch, $flags )
{
global $wgContLang;
- $info = $repo->getInfo();
+ $info = $that->getInfo();
foreach ( $res as $row ) {
- $file = $repo->newFileFromRow( $row );
+ $file = $that->newFileFromRow( $row );
// There must have been a search for this DB key, but this has to handle the
// cases were title capitalization is different on the client and repo wikis.
$dbKeysLook = array( str_replace( ' ', '_', $file->getName() ) );
// Hack: the lock()/unlock() pair is nested in a transaction so the locking is not
// tied to BEGIN/COMMIT. To avoid slow purges in the transaction, move them outside.
- $file = $this;
+ $that = $this;
$this->getRepo()->getMasterDB()->onTransactionIdle(
- function () use ( $file, $archiveNames ) {
+ function () use ( $that, $archiveNames ) {
global $wgUseSquid;
- $file->purgeEverything();
+ $that->purgeEverything();
foreach ( $archiveNames as $archiveName ) {
- $file->purgeOldThumbnails( $archiveName );
+ $that->purgeOldThumbnails( $archiveName );
}
if ( $wgUseSquid ) {
// Purge the squid
$purgeUrls = array();
foreach ( $archiveNames as $archiveName ) {
- $purgeUrls[] = $file->getArchiveUrl( $archiveName );
+ $purgeUrls[] = $that->getArchiveUrl( $archiveName );
}
SquidUpdate::purge( $purgeUrls );
}
/** Idiom for set()/getWithSetCallback() TTL */
const TTL_NONE = 0;
+ /** Idiom for getWithSetCallback() callbacks to avoid calling set() */
+ const TTL_UNCACHEABLE = -1;
/** Cache format version number */
const VERSION = 1;
/**
* Method to fetch/regenerate cache keys
*
- * On cache miss, the key will be set to the callback result.
+ * On cache miss, the key will be set to the callback result,
+ * unless the callback returns false. The arguments supplied are:
+ * (current value or false, &$ttl)
* The callback function returns the new value given the current
- * value (false if not present). If false is returned, then nothing
- * will be saved to cache.
+ * value (false if not present). Preemptive re-caching and $checkKeys
+ * can result in a non-false current value. The TTL of the new value
+ * can be set dynamically by altering $ttl in the callback (by reference).
*
* Usually, callbacks ignore the current value, but it can be used
* to maintain "most recent X" values that come from time or sequence
* @code
* $key = wfMemcKey( 'cat-recent-actions', $catId );
* // Function that derives the new key value given the old value
- * $callback = function( $cValue ) { ... };
+ * $callback = function( $cValue, &$ttl ) { ... };
* // Get the key value from cache or from source on cache miss;
* // try to only let one cluster thread manage doing cache updates
* $opts = array( 'lockTSE' => 5, 'lowTTL' => 10 );
*
* @param string $key Cache key
* @param callable $callback Value generation function
- * @param integer $ttl Seconds to live when the key is updated [0=forever]
+ * @param integer $ttl Seconds to live for key updates. Special values are:
+ * - WANObjectCache::TTL_NONE : cache forever
+ * - WANObjectCache::TTL_UNCACHEABLE : do not cache at all
* @param array $checkKeys List of "check" keys
* @param array $opts Options map:
* - lowTTL : consider pre-emptive updates when the current TTL (sec)
}
// Generate the new value from the callback...
- $value = call_user_func( $callback, $cValue );
+ $value = call_user_func_array( $callback, array( $cValue, &$ttl ) );
// When delete() is called, writes are write-holed by the tombstone,
// so use a special stash key to pass the new value around threads.
- if ( $value !== false && ( $isHot || $isTombstone ) ) {
+ if ( $value !== false && ( $isHot || $isTombstone ) && $ttl >= 0 ) {
$this->cache->set( self::STASH_KEY_PREFIX . $key, $value, $tempTTL );
}
$this->cache->unlock( $key );
}
- if ( $value !== false ) {
+ if ( $value !== false && $ttl >= 0 ) {
// Update the cache; this will fail if the key is tombstoned
$this->set( $key, $value, $ttl );
}
$limit,
$descending
);
- $pager = $this;
/*
* This hook will allow extensions to add in additional queries, so they can get their data
) );
Hooks::run(
'ContribsPager::reallyDoQuery',
- array( &$data, $pager, $offset, $limit, $descending )
+ array( &$data, $this, $offset, $limit, $descending )
);
$result = array();
* @return ResultWrapper
*/
function reallyDoQuery( $offset, $limit, $descending ) {
- $pager = $this;
-
$data = array( parent::reallyDoQuery( $offset, $limit, $descending ) );
// This hook will allow extensions to add in additional queries, nearly
// identical to ContribsPager::reallyDoQuery.
Hooks::run(
'DeletedContribsPager::reallyDoQuery',
- array( &$data, $pager, $offset, $limit, $descending )
+ array( &$data, $this, $offset, $limit, $descending )
);
$result = array();
}
function provideFindLowerBound() {
- $self = $this;
- $indexValueCallback = function ( $size ) use ( $self ) {
- return function ( $val ) use ( $self, $size ) {
- $self->assertTrue( $val >= 0 );
- $self->assertTrue( $val < $size );
+ $that = $this;
+ $indexValueCallback = function ( $size ) use ( $that ) {
+ return function ( $val ) use ( $that, $size ) {
+ $that->assertTrue( $val >= 0 );
+ $that->assertTrue( $val < $size );
return $val;
};
};
$cKey2 = wfRandomString();
$wasSet = 0;
- $func = function() use ( &$wasSet, $value ) { ++$wasSet; return $value; };
+ $func = function( $old, &$ttl ) use ( &$wasSet, $value ) {
+ ++$wasSet;
+ $ttl = 20; // override with another value
+ return $value;
+ };
$wasSet = 0;
$v = $cache->getWithSetCallback( $key, $func, 30, array(), array( 'lockTSE' => 5 ) );
$this->assertEquals( $v, $value );
$this->assertEquals( 1, $wasSet, "Value regenerated" );
+ $curTTL = null;
+ $v = $cache->get( $key, $curTTL );
+ $this->assertLessThanOrEqual( 20, $curTTL, 'Current TTL between 19-20 (overriden)' );
+ $this->assertGreaterThanOrEqual( 19, $curTTL, 'Current TTL between 19-20 (overriden)' );
+
$wasSet = 0;
$v = $cache->getWithSetCallback( $key, $func, 30, array(), array( 'lockTSE' => 5 ) );
$this->assertEquals( $v, $value );
->getMock();
// php 5.3 compatibility!
- $self = $this;
+ $that = $this;
$dbSiteStore->expects( $this->any() )
->method( 'getSite' )
- ->will( $this->returnValue( $self->getTestSite() ) );
+ ->will( $this->returnValue( $that->getTestSite() ) );
$dbSiteStore->expects( $this->any() )
->method( 'getSites' )
- ->will( $this->returnCallback( function() use( $self ) {
+ ->will( $this->returnCallback( function() use ( $that ) {
$siteList = new SiteList();
- $siteList->setSite( $self->getTestSite() );
+ $siteList->setSite( $that->getTestSite() );
return $siteList;
} ) );
private function newSiteImporter( array $expectedSites, $errorCount ) {
$store = $this->getMock( 'SiteStore' );
- $self = $this;
+ $that = $this;
$store->expects( $this->once() )
->method( 'saveSites' )
- ->will( $this->returnCallback( function ( $sites ) use ( $expectedSites, $self ) {
- $self->assertSitesEqual( $expectedSites, $sites );
+ ->will( $this->returnCallback( function ( $sites ) use ( $expectedSites, $that ) {
+ $that->assertSitesEqual( $expectedSites, $sites );
} ) );
$store->expects( $this->any() )