MediaWiki  1.32.0
BagOStuff.php
Go to the documentation of this file.
1 <?php
29 use Psr\Log\LoggerAwareInterface;
30 use Psr\Log\LoggerInterface;
31 use Psr\Log\NullLogger;
32 use Wikimedia\ScopedCallback;
33 use Wikimedia\WaitConditionLoop;
34 
58 abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
60  protected $locks = [];
64  protected $keyspace = 'local';
66  protected $logger;
68  protected $asyncHandler;
70  protected $syncTimeout;
71 
73  private $debugMode = false;
75  private $duplicateKeyLookups = [];
77  private $reportDupes = false;
79  private $dupeTrackScheduled = false;
80 
82  protected $busyCallbacks = [];
83 
86 
88  protected $attrMap = [];
89 
91  const ERR_NONE = 0; // no error
92  const ERR_NO_RESPONSE = 1; // no response
93  const ERR_UNREACHABLE = 2; // can't connect
94  const ERR_UNEXPECTED = 3; // response gave some error
95 
97  const READ_LATEST = 1; // use latest data for replicated stores
98  const READ_VERIFIED = 2; // promise that caller can tell when keys are stale
100  const WRITE_SYNC = 1; // synchronously write to all locations for replicated stores
101  const WRITE_CACHE_ONLY = 2; // Only change state of the in-memory cache
102 
114  public function __construct( array $params = [] ) {
115  if ( isset( $params['logger'] ) ) {
116  $this->setLogger( $params['logger'] );
117  } else {
118  $this->setLogger( new NullLogger() );
119  }
120 
121  if ( isset( $params['keyspace'] ) ) {
122  $this->keyspace = $params['keyspace'];
123  }
124 
125  $this->asyncHandler = $params['asyncHandler'] ?? null;
126 
127  if ( !empty( $params['reportDupes'] ) && is_callable( $this->asyncHandler ) ) {
128  $this->reportDupes = true;
129  }
130 
131  $this->syncTimeout = $params['syncTimeout'] ?? 3;
132  }
133 
138  public function setLogger( LoggerInterface $logger ) {
139  $this->logger = $logger;
140  }
141 
145  public function setDebug( $bool ) {
146  $this->debugMode = $bool;
147  }
148 
161  final public function getWithSetCallback( $key, $ttl, $callback, $flags = 0 ) {
162  $value = $this->get( $key, $flags );
163 
164  if ( $value === false ) {
165  if ( !is_callable( $callback ) ) {
166  throw new InvalidArgumentException( "Invalid cache miss callback provided." );
167  }
168  $value = call_user_func( $callback );
169  if ( $value !== false ) {
170  $this->set( $key, $value, $ttl );
171  }
172  }
173 
174  return $value;
175  }
176 
191  public function get( $key, $flags = 0, $oldFlags = null ) {
192  // B/C for ( $key, &$casToken = null, $flags = 0 )
193  $flags = is_int( $oldFlags ) ? $oldFlags : $flags;
194 
195  $this->trackDuplicateKeys( $key );
196 
197  return $this->doGet( $key, $flags );
198  }
199 
204  private function trackDuplicateKeys( $key ) {
205  if ( !$this->reportDupes ) {
206  return;
207  }
208 
209  if ( !isset( $this->duplicateKeyLookups[$key] ) ) {
210  // Track that we have seen this key. This N-1 counting style allows
211  // easy filtering with array_filter() later.
212  $this->duplicateKeyLookups[$key] = 0;
213  } else {
214  $this->duplicateKeyLookups[$key] += 1;
215 
216  if ( $this->dupeTrackScheduled === false ) {
217  $this->dupeTrackScheduled = true;
218  // Schedule a callback that logs keys processed more than once by get().
219  call_user_func( $this->asyncHandler, function () {
220  $dups = array_filter( $this->duplicateKeyLookups );
221  foreach ( $dups as $key => $count ) {
222  $this->logger->warning(
223  'Duplicate get(): "{key}" fetched {count} times',
224  // Count is N-1 of the actual lookup count
225  [ 'key' => $key, 'count' => $count + 1, ]
226  );
227  }
228  } );
229  }
230  }
231  }
232 
238  abstract protected function doGet( $key, $flags = 0 );
239 
249  protected function getWithToken( $key, &$casToken, $flags = 0 ) {
250  throw new Exception( __METHOD__ . ' not implemented.' );
251  }
252 
262  abstract public function set( $key, $value, $exptime = 0, $flags = 0 );
263 
270  abstract public function delete( $key );
271 
288  public function merge( $key, callable $callback, $exptime = 0, $attempts = 10, $flags = 0 ) {
289  return $this->mergeViaLock( $key, $callback, $exptime, $attempts, $flags );
290  }
291 
301  protected function mergeViaCas( $key, $callback, $exptime = 0, $attempts = 10 ) {
302  do {
303  $this->clearLastError();
305  $this->reportDupes = false;
306  $casToken = null; // passed by reference
307  $currentValue = $this->getWithToken( $key, $casToken, self::READ_LATEST );
308  $this->reportDupes = $reportDupes;
309 
310  if ( $this->getLastError() ) {
311  $this->logger->warning(
312  __METHOD__ . ' failed due to I/O error on get() for {key}.',
313  [ 'key' => $key ]
314  );
315 
316  return false; // don't spam retries (retry only on races)
317  }
318 
319  // Derive the new value from the old value
320  $value = call_user_func( $callback, $this, $key, $currentValue, $exptime );
321 
322  $this->clearLastError();
323  if ( $value === false ) {
324  $success = true; // do nothing
325  } elseif ( $currentValue === false ) {
326  // Try to create the key, failing if it gets created in the meantime
327  $success = $this->add( $key, $value, $exptime );
328  } else {
329  // Try to update the key, failing if it gets changed in the meantime
330  $success = $this->cas( $casToken, $key, $value, $exptime );
331  }
332  if ( $this->getLastError() ) {
333  $this->logger->warning(
334  __METHOD__ . ' failed due to I/O error for {key}.',
335  [ 'key' => $key ]
336  );
337 
338  return false; // IO error; don't spam retries
339  }
340  } while ( !$success && --$attempts );
341 
342  return $success;
343  }
344 
355  protected function cas( $casToken, $key, $value, $exptime = 0 ) {
356  if ( !$this->lock( $key, 0 ) ) {
357  return false; // non-blocking
358  }
359 
360  $curCasToken = null; // passed by reference
361  $this->getWithToken( $key, $curCasToken, self::READ_LATEST );
362  if ( $casToken === $curCasToken ) {
363  $success = $this->set( $key, $value, $exptime );
364  } else {
365  $this->logger->info(
366  __METHOD__ . ' failed due to race condition for {key}.',
367  [ 'key' => $key ]
368  );
369 
370  $success = false; // mismatched or failed
371  }
372 
373  $this->unlock( $key );
374 
375  return $success;
376  }
377 
388  protected function mergeViaLock( $key, $callback, $exptime = 0, $attempts = 10, $flags = 0 ) {
389  if ( $attempts <= 1 ) {
390  $timeout = 0; // clearly intended to be "non-blocking"
391  } else {
392  $timeout = 3;
393  }
394 
395  if ( !$this->lock( $key, $timeout ) ) {
396  return false;
397  }
398 
399  $this->clearLastError();
401  $this->reportDupes = false;
402  $currentValue = $this->get( $key, self::READ_LATEST );
403  $this->reportDupes = $reportDupes;
404 
405  if ( $this->getLastError() ) {
406  $this->logger->warning(
407  __METHOD__ . ' failed due to I/O error on get() for {key}.',
408  [ 'key' => $key ]
409  );
410 
411  $success = false;
412  } else {
413  // Derive the new value from the old value
414  $value = call_user_func( $callback, $this, $key, $currentValue, $exptime );
415  if ( $value === false ) {
416  $success = true; // do nothing
417  } else {
418  $success = $this->set( $key, $value, $exptime, $flags ); // set the new value
419  }
420  }
421 
422  if ( !$this->unlock( $key ) ) {
423  // this should never happen
424  trigger_error( "Could not release lock for key '$key'." );
425  }
426 
427  return $success;
428  }
429 
438  public function changeTTL( $key, $expiry = 0 ) {
439  $value = $this->get( $key );
440 
441  return ( $value === false ) ? false : $this->set( $key, $value, $expiry );
442  }
443 
455  public function lock( $key, $timeout = 6, $expiry = 6, $rclass = '' ) {
456  // Avoid deadlocks and allow lock reentry if specified
457  if ( isset( $this->locks[$key] ) ) {
458  if ( $rclass != '' && $this->locks[$key]['class'] === $rclass ) {
459  ++$this->locks[$key]['depth'];
460  return true;
461  } else {
462  return false;
463  }
464  }
465 
466  $fname = __METHOD__;
467  $expiry = min( $expiry ?: INF, self::TTL_DAY );
468  $loop = new WaitConditionLoop(
469  function () use ( $key, $timeout, $expiry, $fname ) {
470  $this->clearLastError();
471  if ( $this->add( "{$key}:lock", 1, $expiry ) ) {
472  return true; // locked!
473  } elseif ( $this->getLastError() ) {
474  $this->logger->warning(
475  $fname . ' failed due to I/O error for {key}.',
476  [ 'key' => $key ]
477  );
478 
479  return WaitConditionLoop::CONDITION_ABORTED; // network partition?
480  }
481 
482  return WaitConditionLoop::CONDITION_CONTINUE;
483  },
484  $timeout
485  );
486 
487  $code = $loop->invoke();
488  $locked = ( $code === $loop::CONDITION_REACHED );
489  if ( $locked ) {
490  $this->locks[$key] = [ 'class' => $rclass, 'depth' => 1 ];
491  } elseif ( $code === $loop::CONDITION_TIMED_OUT ) {
492  $this->logger->warning(
493  "$fname failed due to timeout for {key}.",
494  [ 'key' => $key, 'timeout' => $timeout ]
495  );
496  }
497 
498  return $locked;
499  }
500 
507  public function unlock( $key ) {
508  if ( isset( $this->locks[$key] ) && --$this->locks[$key]['depth'] <= 0 ) {
509  unset( $this->locks[$key] );
510 
511  $ok = $this->delete( "{$key}:lock" );
512  if ( !$ok ) {
513  $this->logger->warning(
514  __METHOD__ . ' failed to release lock for {key}.',
515  [ 'key' => $key ]
516  );
517  }
518 
519  return $ok;
520  }
521 
522  return true;
523  }
524 
541  final public function getScopedLock( $key, $timeout = 6, $expiry = 30, $rclass = '' ) {
542  $expiry = min( $expiry ?: INF, self::TTL_DAY );
543 
544  if ( !$this->lock( $key, $timeout, $expiry, $rclass ) ) {
545  return null;
546  }
547 
548  $lSince = $this->getCurrentTime(); // lock timestamp
549 
550  return new ScopedCallback( function () use ( $key, $lSince, $expiry ) {
551  $latency = 0.050; // latency skew (err towards keeping lock present)
552  $age = ( $this->getCurrentTime() - $lSince + $latency );
553  if ( ( $age + $latency ) >= $expiry ) {
554  $this->logger->warning(
555  "Lock for {key} held too long ({age} sec).",
556  [ 'key' => $key, 'age' => $age ]
557  );
558  return; // expired; it's not "safe" to delete the key
559  }
560  $this->unlock( $key );
561  } );
562  }
563 
573  public function deleteObjectsExpiringBefore( $date, $progressCallback = false ) {
574  // stub
575  return false;
576  }
577 
584  public function getMulti( array $keys, $flags = 0 ) {
585  $res = [];
586  foreach ( $keys as $key ) {
587  $val = $this->get( $key );
588  if ( $val !== false ) {
589  $res[$key] = $val;
590  }
591  }
592  return $res;
593  }
594 
602  public function setMulti( array $data, $exptime = 0 ) {
603  $res = true;
604  foreach ( $data as $key => $value ) {
605  if ( !$this->set( $key, $value, $exptime ) ) {
606  $res = false;
607  }
608  }
609  return $res;
610  }
611 
618  public function add( $key, $value, $exptime = 0 ) {
619  // @note: avoid lock() here since that method uses *this* method by default
620  if ( $this->get( $key ) === false ) {
621  return $this->set( $key, $value, $exptime );
622  }
623  return false; // key already set
624  }
625 
632  public function incr( $key, $value = 1 ) {
633  if ( !$this->lock( $key, 1 ) ) {
634  return false;
635  }
636  $n = $this->get( $key );
637  if ( $this->isInteger( $n ) ) { // key exists?
638  $n += intval( $value );
639  $this->set( $key, max( 0, $n ) ); // exptime?
640  } else {
641  $n = false;
642  }
643  $this->unlock( $key );
644 
645  return $n;
646  }
647 
654  public function decr( $key, $value = 1 ) {
655  return $this->incr( $key, - $value );
656  }
657 
670  public function incrWithInit( $key, $ttl, $value = 1, $init = 1 ) {
671  $this->clearLastError();
672  $newValue = $this->incr( $key, $value );
673  if ( $newValue === false && !$this->getLastError() ) {
674  // No key set; initialize
675  $newValue = $this->add( $key, (int)$init, $ttl ) ? $init : false;
676  if ( $newValue === false && !$this->getLastError() ) {
677  // Raced out initializing; increment
678  $newValue = $this->incr( $key, $value );
679  }
680  }
681 
682  return $newValue;
683  }
684 
690  public function getLastError() {
691  return $this->lastError;
692  }
693 
698  public function clearLastError() {
699  $this->lastError = self::ERR_NONE;
700  }
701 
707  protected function setLastError( $err ) {
708  $this->lastError = $err;
709  }
710 
731  public function addBusyCallback( callable $workCallback ) {
732  $this->busyCallbacks[] = $workCallback;
733  }
734 
749  public function modifySimpleRelayEvent( array $event ) {
750  return $event;
751  }
752 
756  protected function debug( $text ) {
757  if ( $this->debugMode ) {
758  $this->logger->debug( "{class} debug: $text", [
759  'class' => static::class,
760  ] );
761  }
762  }
763 
769  protected function convertExpiry( $exptime ) {
770  if ( $exptime != 0 && $exptime < ( 10 * self::TTL_YEAR ) ) {
771  return (int)$this->getCurrentTime() + $exptime;
772  } else {
773  return $exptime;
774  }
775  }
776 
784  protected function convertToRelative( $exptime ) {
785  if ( $exptime >= ( 10 * self::TTL_YEAR ) ) {
786  $exptime -= (int)$this->getCurrentTime();
787  if ( $exptime <= 0 ) {
788  $exptime = 1;
789  }
790  return $exptime;
791  } else {
792  return $exptime;
793  }
794  }
795 
802  protected function isInteger( $value ) {
803  return ( is_int( $value ) || ctype_digit( $value ) );
804  }
805 
814  public function makeKeyInternal( $keyspace, $args ) {
815  $key = $keyspace;
816  foreach ( $args as $arg ) {
817  $arg = str_replace( ':', '%3A', $arg );
818  $key = $key . ':' . $arg;
819  }
820  return strtr( $key, ' ', '_' );
821  }
822 
831  public function makeGlobalKey( $class, $component = null ) {
832  return $this->makeKeyInternal( 'global', func_get_args() );
833  }
834 
843  public function makeKey( $class, $component = null ) {
844  return $this->makeKeyInternal( $this->keyspace, func_get_args() );
845  }
846 
852  public function getQoS( $flag ) {
853  return $this->attrMap[$flag] ?? self::QOS_UNKNOWN;
854  }
855 
862  protected function mergeFlagMaps( array $bags ) {
863  $map = [];
864  foreach ( $bags as $bag ) {
865  foreach ( $bag->attrMap as $attr => $rank ) {
866  if ( isset( $map[$attr] ) ) {
867  $map[$attr] = min( $map[$attr], $rank );
868  } else {
869  $map[$attr] = $rank;
870  }
871  }
872  }
873 
874  return $map;
875  }
876 
881  protected function getCurrentTime() {
882  return $this->wallClockOverride ?: microtime( true );
883  }
884 
889  public function setMockTime( &$time ) {
890  $this->wallClockOverride =& $time;
891  }
892 }
BagOStuff\isInteger
isInteger( $value)
Check if a value is an integer.
Definition: BagOStuff.php:802
BagOStuff\add
add( $key, $value, $exptime=0)
Definition: BagOStuff.php:618
BagOStuff\setMulti
setMulti(array $data, $exptime=0)
Batch insertion.
Definition: BagOStuff.php:602
BagOStuff\$asyncHandler
callback null $asyncHandler
Definition: BagOStuff.php:68
BagOStuff\decr
decr( $key, $value=1)
Decrease stored value of $key by $value while preserving its TTL.
Definition: BagOStuff.php:654
false
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:187
BagOStuff\ERR_UNREACHABLE
const ERR_UNREACHABLE
Definition: BagOStuff.php:93
BagOStuff\getQoS
getQoS( $flag)
Definition: BagOStuff.php:852
BagOStuff\modifySimpleRelayEvent
modifySimpleRelayEvent(array $event)
Modify a cache update operation array for EventRelayer::notify()
Definition: BagOStuff.php:749
BagOStuff\getLastError
getLastError()
Get the "last error" registered; clearLastError() should be called manually.
Definition: BagOStuff.php:690
BagOStuff\WRITE_SYNC
const WRITE_SYNC
Bitfield constants for set()/merge()
Definition: BagOStuff.php:100
BagOStuff\$reportDupes
bool $reportDupes
Definition: BagOStuff.php:77
BagOStuff\deleteObjectsExpiringBefore
deleteObjectsExpiringBefore( $date, $progressCallback=false)
Delete all objects expiring before a certain date.
Definition: BagOStuff.php:573
BagOStuff\getWithToken
getWithToken( $key, &$casToken, $flags=0)
Definition: BagOStuff.php:249
BagOStuff\convertExpiry
convertExpiry( $exptime)
Convert an optionally relative time to an absolute time.
Definition: BagOStuff.php:769
BagOStuff\debug
debug( $text)
Definition: BagOStuff.php:756
BagOStuff\$locks
array[] $locks
Lock tracking.
Definition: BagOStuff.php:60
$params
$params
Definition: styleTest.css.php:44
BagOStuff\trackDuplicateKeys
trackDuplicateKeys( $key)
Track the number of times that a given key has been used.
Definition: BagOStuff.php:204
BagOStuff
Class representing a cache/ephemeral data store.
Definition: BagOStuff.php:58
BagOStuff\$duplicateKeyLookups
array $duplicateKeyLookups
Definition: BagOStuff.php:75
BagOStuff\makeKey
makeKey( $class, $component=null)
Make a cache key, scoped to this instance's keyspace.
Definition: BagOStuff.php:843
$res
$res
Definition: database.txt:21
BagOStuff\setDebug
setDebug( $bool)
Definition: BagOStuff.php:145
$success
$success
Definition: NoLocalSettings.php:42
BagOStuff\$logger
LoggerInterface $logger
Definition: BagOStuff.php:66
BagOStuff\ERR_NONE
const ERR_NONE
Possible values for getLastError()
Definition: BagOStuff.php:91
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
BagOStuff\setMockTime
setMockTime(&$time)
Definition: BagOStuff.php:889
BagOStuff\getWithSetCallback
getWithSetCallback( $key, $ttl, $callback, $flags=0)
Get an item with the given key, regenerating and setting it if not found.
Definition: BagOStuff.php:161
BagOStuff\unlock
unlock( $key)
Release an advisory lock on a key string.
Definition: BagOStuff.php:507
BagOStuff\clearLastError
clearLastError()
Clear the "last error" registry.
Definition: BagOStuff.php:698
IExpiringStore
Generic base class for storage interfaces.
Definition: IExpiringStore.php:31
BagOStuff\$lastError
int $lastError
ERR_* class constant.
Definition: BagOStuff.php:62
BagOStuff\setLogger
setLogger(LoggerInterface $logger)
Definition: BagOStuff.php:138
BagOStuff\incrWithInit
incrWithInit( $key, $ttl, $value=1, $init=1)
Increase stored value of $key by $value while preserving its TTL.
Definition: BagOStuff.php:670
BagOStuff\READ_LATEST
const READ_LATEST
Bitfield constants for get()/getMulti()
Definition: BagOStuff.php:97
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
$code
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable & $code
Definition: hooks.txt:813
BagOStuff\addBusyCallback
addBusyCallback(callable $workCallback)
Let a callback be run to avoid wasting time on special blocking calls.
Definition: BagOStuff.php:731
BagOStuff\$busyCallbacks
callable[] $busyCallbacks
Definition: BagOStuff.php:82
BagOStuff\$wallClockOverride
float null $wallClockOverride
Definition: BagOStuff.php:85
$time
see documentation in includes Linker php for Linker::makeImageLink & $time
Definition: hooks.txt:1841
array
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))
IExpiringStore\QOS_UNKNOWN
const QOS_UNKNOWN
Definition: IExpiringStore.php:58
$fname
if(defined( 'MW_SETUP_CALLBACK')) $fname
Customization point after all loading (constants, functions, classes, DefaultSettings,...
Definition: Setup.php:121
BagOStuff\mergeFlagMaps
mergeFlagMaps(array $bags)
Merge the flag maps of one or more BagOStuff objects into a "lowest common denominator" map.
Definition: BagOStuff.php:862
BagOStuff\__construct
__construct(array $params=[])
$params include:
Definition: BagOStuff.php:114
$value
$value
Definition: styleTest.css.php:49
BagOStuff\doGet
doGet( $key, $flags=0)
BagOStuff\makeGlobalKey
makeGlobalKey( $class, $component=null)
Make a global cache key.
Definition: BagOStuff.php:831
BagOStuff\incr
incr( $key, $value=1)
Increase stored value of $key by $value while preserving its TTL.
Definition: BagOStuff.php:632
BagOStuff\$syncTimeout
int $syncTimeout
Seconds.
Definition: BagOStuff.php:70
BagOStuff\changeTTL
changeTTL( $key, $expiry=0)
Reset the TTL on a key if it exists.
Definition: BagOStuff.php:438
BagOStuff\merge
merge( $key, callable $callback, $exptime=0, $attempts=10, $flags=0)
Merge changes into the existing cache value (possibly creating a new one)
Definition: BagOStuff.php:288
BagOStuff\mergeViaCas
mergeViaCas( $key, $callback, $exptime=0, $attempts=10)
Definition: BagOStuff.php:301
$args
if( $line===false) $args
Definition: cdb.php:64
BagOStuff\$debugMode
bool $debugMode
Definition: BagOStuff.php:73
BagOStuff\mergeViaLock
mergeViaLock( $key, $callback, $exptime=0, $attempts=10, $flags=0)
Definition: BagOStuff.php:388
BagOStuff\$attrMap
int[] $attrMap
Map of (ATTR_* class constant => QOS_* class constant)
Definition: BagOStuff.php:88
BagOStuff\READ_VERIFIED
const READ_VERIFIED
Definition: BagOStuff.php:98
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
BagOStuff\lock
lock( $key, $timeout=6, $expiry=6, $rclass='')
Acquire an advisory lock on a key string.
Definition: BagOStuff.php:455
$keys
$keys
Definition: testCompression.php:67
BagOStuff\getCurrentTime
getCurrentTime()
Definition: BagOStuff.php:881
BagOStuff\cas
cas( $casToken, $key, $value, $exptime=0)
Check and set an item.
Definition: BagOStuff.php:355
BagOStuff\$keyspace
string $keyspace
Definition: BagOStuff.php:64
class
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
BagOStuff\makeKeyInternal
makeKeyInternal( $keyspace, $args)
Construct a cache key.
Definition: BagOStuff.php:814
BagOStuff\getScopedLock
getScopedLock( $key, $timeout=6, $expiry=30, $rclass='')
Get a lightweight exclusive self-unlocking lock.
Definition: BagOStuff.php:541
BagOStuff\ERR_NO_RESPONSE
const ERR_NO_RESPONSE
Definition: BagOStuff.php:92
BagOStuff\setLastError
setLastError( $err)
Set the "last error" registry.
Definition: BagOStuff.php:707
BagOStuff\ERR_UNEXPECTED
const ERR_UNEXPECTED
Definition: BagOStuff.php:94
BagOStuff\getMulti
getMulti(array $keys, $flags=0)
Get an associative array containing the item for each of the keys that have items.
Definition: BagOStuff.php:584
BagOStuff\WRITE_CACHE_ONLY
const WRITE_CACHE_ONLY
Definition: BagOStuff.php:101
BagOStuff\convertToRelative
convertToRelative( $exptime)
Convert an optionally absolute expiry time to a relative time.
Definition: BagOStuff.php:784
BagOStuff\$dupeTrackScheduled
bool $dupeTrackScheduled
Definition: BagOStuff.php:79