39 self::LOCK_SH => self::LOCK_SH,
40 self::LOCK_UW => self::LOCK_SH,
41 self::LOCK_EX => self::LOCK_EX
60 parent::__construct( $config );
62 $this->lockDir = $config[
'lockDirectory'];
63 $this->isWindows = ( PHP_OS_FAMILY ===
'Windows' );
73 $status = StatusValue::newGood();
76 foreach ( $paths as
$path ) {
78 if ( $status->isOK() ) {
79 $lockedPaths[] =
$path;
98 $status = StatusValue::newGood();
100 foreach ( $paths as
$path ) {
115 $status = StatusValue::newGood();
117 if ( isset( $this->locksHeld[
$path][
$type] ) ) {
119 } elseif ( isset( $this->locksHeld[
$path][self::LOCK_EX] ) ) {
122 if ( isset( $this->handles[
$path] ) ) {
123 $handle = $this->handles[
$path];
125 Wikimedia\suppressWarnings();
127 if ( !$handle && !is_dir( $this->lockDir ) ) {
129 if ( mkdir( $this->lockDir, 0777,
true ) ) {
132 $this->logger->error(
"Cannot create directory '{$this->lockDir}'." );
135 Wikimedia\restoreWarnings();
140 if ( flock( $handle, $lock | LOCK_NB ) ) {
143 $this->handles[
$path] = $handle;
146 $status->fatal(
'lockmanager-fail-acquirelock',
$path );
149 $status->fatal(
'lockmanager-fail-openlock',
$path );
164 $status = StatusValue::newGood();
166 if ( !isset( $this->locksHeld[
$path] ) ) {
167 $status->warning(
'lockmanager-notlocked',
$path );
168 } elseif ( !isset( $this->locksHeld[
$path][
$type] ) ) {
169 $status->warning(
'lockmanager-notlocked',
$path );
171 $handlesToClose = [];
176 if ( $this->locksHeld[
$path] === [] ) {
177 unset( $this->locksHeld[
$path] );
178 if ( isset( $this->handles[
$path] ) ) {
179 $handlesToClose[] = $this->handles[
$path];
180 unset( $this->handles[
$path] );
185 if ( $this->isWindows ) {
207 $status = StatusValue::newGood();
208 foreach ( $handlesToClose as $handle ) {
209 if ( !flock( $handle, LOCK_UN ) ) {
210 $status->fatal(
'lockmanager-fail-releaselock',
$path );
212 if ( !fclose( $handle ) ) {
213 $status->warning(
'lockmanager-fail-closelock',
$path );
225 $status = StatusValue::newGood();
226 if ( !isset( $this->locksHeld[
$path] ) ) {
227 # No locks are held for the lock file anymore
229 $status->warning(
'lockmanager-fail-deletelock',
$path );
231 unset( $this->handles[
$path] );
243 return "{$this->lockDir}/{$this->sha1Base36Absolute( $path )}.lock";
250 while ( count( $this->locksHeld ) ) {
251 foreach ( $this->locksHeld as
$path => $locks ) {
Simple version of LockManager based on using FS lock files.
doSingleLock( $path, $type)
Lock a single resource key.
pruneKeyLockFiles( $path)
string $lockDir
Global dir for all servers.
__destruct()
Make sure remaining locks get cleared for sanity.
doLock(array $paths, $type)
array $handles
Map of (locked key => lock file handle)
doSingleUnlock( $path, $type)
Unlock a single resource key.
__construct(array $config)
Construct a new instance from configuration.
closeLockHandles( $path, array $handlesToClose)
getLockPath( $path)
Get the path to the lock file for a key.
array $lockTypeMap
Mapping of lock types to the type actually used.
doUnlock(array $paths, $type)
Class for handling resource locking.
const LOCK_SH
Lock types; stronger locks have higher values.