X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Flibs%2Flockmanager%2FQuorumLockManager.php;h=83dcc6be56edc0e7382da05eb9fac139a23de85c;hp=950b283670bf44d5b96d503fff5a81ddcafa781b;hb=fa0f6f34972c0e0f4aac24a03b3efdfc45f256f6;hpb=316509d9083b4b86dea516b640a7e11dc3924b7c diff --git a/includes/libs/lockmanager/QuorumLockManager.php b/includes/libs/lockmanager/QuorumLockManager.php index 950b283670..83dcc6be56 100644 --- a/includes/libs/lockmanager/QuorumLockManager.php +++ b/includes/libs/lockmanager/QuorumLockManager.php @@ -38,7 +38,7 @@ abstract class QuorumLockManager extends LockManager { final protected function doLockByType( array $pathsByType ) { $status = StatusValue::newGood(); - $pathsToLock = []; // (bucket => type => paths) + $pathsByTypeByBucket = []; // (bucket => type => paths) // Get locks that need to be acquired (buckets => locks)... foreach ( $pathsByType as $type => $paths ) { foreach ( $paths as $path ) { @@ -46,23 +46,27 @@ abstract class QuorumLockManager extends LockManager { ++$this->locksHeld[$path][$type]; } else { $bucket = $this->getBucketFromPath( $path ); - $pathsToLock[$bucket][$type][] = $path; + $pathsByTypeByBucket[$bucket][$type][] = $path; } } } + // Acquire locks in each bucket in bucket order to reduce contention. Any blocking + // mutexes during the acquisition step will not involve circular waiting on buckets. + ksort( $pathsByTypeByBucket ); + $lockedPaths = []; // files locked in this attempt (type => paths) // Attempt to acquire these locks... - foreach ( $pathsToLock as $bucket => $pathsToLockByType ) { + foreach ( $pathsByTypeByBucket as $bucket => $bucketPathsByType ) { // Try to acquire the locks for this bucket - $status->merge( $this->doLockingRequestBucket( $bucket, $pathsToLockByType ) ); + $status->merge( $this->doLockingRequestBucket( $bucket, $bucketPathsByType ) ); if ( !$status->isOK() ) { $status->merge( $this->doUnlockByType( $lockedPaths ) ); return $status; } // Record these locks as active - foreach ( $pathsToLockByType as $type => $paths ) { + foreach ( $bucketPathsByType as $type => $paths ) { foreach ( $paths as $path ) { $this->locksHeld[$path][$type] = 1; // locked // Keep track of what locks were made in this attempt @@ -77,7 +81,7 @@ abstract class QuorumLockManager extends LockManager { protected function doUnlockByType( array $pathsByType ) { $status = StatusValue::newGood(); - $pathsToUnlock = []; // (bucket => type => paths) + $pathsByTypeByBucket = []; // (bucket => type => paths) foreach ( $pathsByType as $type => $paths ) { foreach ( $paths as $path ) { if ( !isset( $this->locksHeld[$path][$type] ) ) { @@ -88,7 +92,7 @@ abstract class QuorumLockManager extends LockManager { if ( $this->locksHeld[$path][$type] <= 0 ) { unset( $this->locksHeld[$path][$type] ); $bucket = $this->getBucketFromPath( $path ); - $pathsToUnlock[$bucket][$type][] = $path; + $pathsByTypeByBucket[$bucket][$type][] = $path; } if ( $this->locksHeld[$path] === [] ) { unset( $this->locksHeld[$path] ); // no SH or EX locks left for key @@ -99,8 +103,8 @@ abstract class QuorumLockManager extends LockManager { // Remove these specific locks if possible, or at least release // all locks once this process is currently not holding any locks. - foreach ( $pathsToUnlock as $bucket => $pathsToUnlockByType ) { - $status->merge( $this->doUnlockingRequestBucket( $bucket, $pathsToUnlockByType ) ); + foreach ( $pathsByTypeByBucket as $bucket => $bucketPathsByType ) { + $status->merge( $this->doUnlockingRequestBucket( $bucket, $bucketPathsByType ) ); } if ( $this->locksHeld === [] ) { $status->merge( $this->releaseAllLocks() ); @@ -148,7 +152,7 @@ abstract class QuorumLockManager extends LockManager { * This is all or nothing; if any key is already pledged then this totally fails. * * @param int $bucket - * @param callable $callback Pledge method taking a server name and yeilding a StatusValue + * @param callable $callback Pledge method taking a server name and yielding a StatusValue * @return StatusValue */ final protected function collectPledgeQuorum( $bucket, callable $callback ) { @@ -190,7 +194,7 @@ abstract class QuorumLockManager extends LockManager { * Attempt to release pledges with the peers for a bucket * * @param int $bucket - * @param callable $callback Pledge method taking a server name and yeilding a StatusValue + * @param callable $callback Pledge method taking a server name and yielding a StatusValue * @return StatusValue */ final protected function releasePledges( $bucket, callable $callback ) {