26use Psr\Log\LoggerAwareInterface;
27use Psr\Log\LoggerInterface;
28use Psr\Log\NullLogger;
29use Wikimedia\WaitConditionLoop;
65 const POSITION_TTL = 60;
67 const POS_STORE_WAIT_TIMEOUT = 5;
77 $this->clientId = md5( $client[
'ip'] .
"\n" . $client[
'agent'] );
79 $this->waitForPosIndex = $posIndex;
80 $this->logger =
new NullLogger();
123 isset( $this->startupPositions[$masterName] ) &&
124 $this->startupPositions[$masterName] instanceof
DBMasterPos
126 $pos = $this->startupPositions[$masterName];
127 $this->logger->debug( __METHOD__ .
": LB for '$masterName' set to pos $pos\n" );
140 if ( !$this->enabled ) {
151 $this->logger->debug( __METHOD__ .
": LB for '$masterName' has pos $pos\n" );
152 $this->shutdownPositions[$masterName] = $pos;
155 $this->logger->debug( __METHOD__ .
": DB '$masterName' touched\n" );
157 $this->shutdownTouchDBs[$masterName] = 1;
169 public function shutdown( callable $workCallback =
null, $mode =
'sync', &$cpIndex =
null ) {
170 if ( !$this->enabled ) {
177 foreach ( $this->shutdownTouchDBs as $dbName => $unused ) {
185 if ( !count( $this->shutdownPositions ) ) {
189 $this->logger->debug( __METHOD__ .
": saving master pos for " .
190 implode(
', ', array_keys( $this->shutdownPositions ) ) .
"\n"
197 if ( $workCallback ) {
206 $this->shutdownPositions,
210 ( $mode ===
'sync' ) ? $store::WRITE_SYNC : 0
221 $this->logger->warning( __METHOD__ .
": failed to save master pos for " .
222 implode(
', ', array_keys( $this->shutdownPositions ) ) .
"\n"
224 } elseif ( $mode ===
'sync' &&
225 $store->
getQoS( $store::ATTR_SYNCWRITES ) < $store::QOS_SYNCWRITES_BE
228 $this->logger->info( __METHOD__ .
": store may not support synchronous writes." );
231 $bouncedPositions = [];
234 return $bouncedPositions;
243 return $this->store->get( $this->
getTouchedKey( $this->store, $dbName ) );
259 if ( $this->initialized ) {
263 $this->initialized =
true;
270 if ( $this->waitForPosIndex > 0 ) {
272 $loop =
new WaitConditionLoop(
273 function () use ( &$data ) {
274 $data = $this->store->get( $this->
key );
275 if ( !is_array( $data ) ) {
276 return WaitConditionLoop::CONDITION_CONTINUE;
277 } elseif ( !isset( $data[
'writeIndex'] ) ) {
278 return WaitConditionLoop::CONDITION_REACHED;
281 return ( $data[
'writeIndex'] >= $this->waitForPosIndex )
282 ? WaitConditionLoop::CONDITION_REACHED
283 : WaitConditionLoop::CONDITION_CONTINUE;
287 $result = $loop->invoke();
288 $waitedMs = $loop->getLastWaitTime() * 1e3;
290 if ( $result == $loop::CONDITION_REACHED ) {
291 $msg =
"expected and found pos index {$this->waitForPosIndex} ({$waitedMs}ms)";
292 $this->logger->debug( $msg );
294 $msg =
"expected but missed pos index {$this->waitForPosIndex} ({$waitedMs}ms)";
295 $this->logger->info( $msg );
298 $data = $this->store->get( $this->
key );
301 $this->startupPositions = $data ? $data[
'positions'] : [];
302 $this->logger->debug( __METHOD__ .
": key is {$this->key} (read)\n" );
304 $this->startupPositions = [];
305 $this->logger->debug( __METHOD__ .
": key is {$this->key} (unread)\n" );
317 $curPositions = isset( $curValue[
'positions'] ) ? $curValue[
'positions'] : [];
321 !isset( $curPositions[$db] ) ||
323 $pos->asOfTime() > $curPositions[$db]->asOfTime()
325 $curPositions[$db] = $pos;
329 $cpIndex = isset( $curValue[
'writeIndex'] ) ? $curValue[
'writeIndex'] : 0;
332 'positions' => $curPositions,
333 'writeIndex' => ++$cpIndex
interface is intended to be more or less compatible with the PHP memcached client.
unlock( $key)
Release an advisory lock on a key string.
lock( $key, $timeout=6, $expiry=6, $rclass='')
Acquire an advisory lock on a key string.
set( $key, $value, $exptime=0, $flags=0)
Set an item.
get( $key, $flags=0, $oldFlags=null)
Get an item with the given key.
addBusyCallback(callable $workCallback)
Let a callback be run to avoid wasting time on special blocking calls.
makeGlobalKey( $class, $component=null)
Make a global cache key.
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add in any and then calling but I prefer the flexibility This should also do the output encoding The system allocates a global one in $wgOut Title Represents the title of an and does all the work of translating among various forms such as plain database key