40 $status = StatusValue::newGood();
42 $pathsByTypeByBucket = [];
44 foreach ( $pathsByType as
$type => $paths ) {
45 foreach ( $paths as
$path ) {
46 if ( isset( $this->locksHeld[
$path][
$type] ) ) {
50 $pathsByTypeByBucket[$bucket][
$type][] =
$path;
57 ksort( $pathsByTypeByBucket );
61 foreach ( $pathsByTypeByBucket as $bucket => $bucketPathsByType ) {
64 if ( !$status->isOK() ) {
70 foreach ( $bucketPathsByType as
$type => $paths ) {
71 foreach ( $paths as
$path ) {
90 $status = StatusValue::newGood();
92 $pathsByTypeByBucket = [];
93 foreach ( $pathsByType as
$type => $paths ) {
94 foreach ( $paths as
$path ) {
95 if ( !isset( $this->locksHeld[
$path][
$type] ) ) {
96 $status->warning(
'lockmanager-notlocked',
$path );
103 $pathsByTypeByBucket[$bucket][
$type][] =
$path;
105 if ( $this->locksHeld[
$path] === [] ) {
106 unset( $this->locksHeld[
$path] );
114 foreach ( $pathsByTypeByBucket as $bucket => $bucketPathsByType ) {
117 if ( $this->locksHeld === [] ) {
119 $this->degradedBuckets = [];
136 function ( $lockSrv ) use ( $pathsByType ) {
152 function ( $lockSrv ) use ( $pathsByType ) {
167 $status = StatusValue::newGood();
170 $votesLeft = count( $this->srvsByBucket[$bucket] );
171 $quorum = floor( $votesLeft / 2 + 1 );
173 foreach ( $this->srvsByBucket[$bucket] as $lockSrv ) {
176 $status->warning(
'lockmanager-fail-svr-acquire', $lockSrv );
177 $this->degradedBuckets[$bucket] = time();
181 $status->merge( $callback( $lockSrv ) );
182 if ( !$status->isOK() ) {
186 if ( $yesVotes >= $quorum ) {
190 $votesNeeded = $quorum - $yesVotes;
191 if ( $votesNeeded > $votesLeft ) {
196 $status->setResult(
false );
209 $status = StatusValue::newGood();
212 $votesLeft = count( $this->srvsByBucket[$bucket] );
213 $quorum = floor( $votesLeft / 2 + 1 );
214 $isDegraded = isset( $this->degradedBuckets[$bucket] );
215 foreach ( $this->srvsByBucket[$bucket] as $lockSrv ) {
217 $status->warning(
'lockmanager-fail-svr-release', $lockSrv );
220 $status->merge( $callback( $lockSrv ) );
224 if ( $yesVotes >= $quorum && !$isDegraded ) {
231 $status->setResult( $yesVotes >= $quorum );
244 $prefix = substr( sha1(
$path ), 0, 2 );
245 return (
int)base_convert( $prefix, 16, 10 ) % count( $this->srvsByBucket );
287 throw new LogicException( __METHOD__ .
': proxy class does not need this method.' );
291 throw new LogicException( __METHOD__ .
': proxy class does not need this method.' );
Class for handling resource locking.
Version of LockManager that uses a quorum from peer servers for locks.
releasePledges( $bucket, callable $callback)
Attempt to release pledges with the peers for a bucket.
freeLocksOnServer( $lockSrv, array $pathsByType)
Get a connection to a lock server and release locks on $paths.
getLocksOnServer( $lockSrv, array $pathsByType)
Get a connection to a lock server and acquire locks.
doLockByType(array $pathsByType)
doLockingRequestBucket( $bucket, array $pathsByType)
Attempt to acquire locks with the peers for a bucket.
array $degradedBuckets
Map of degraded buckets.
isServerUp( $lockSrv)
Check if a lock server is up.
collectPledgeQuorum( $bucket, callable $callback)
Attempt to acquire pledges with the peers for a bucket.
doUnlockingRequestBucket( $bucket, array $pathsByType)
Attempt to release locks with the peers for a bucket.
releaseAllLocks()
Release all locks that this session is holding.
array $srvsByBucket
Map of bucket indexes to peer server lists.
doUnlock(array $paths, $type)
Unlock resources with the given keys and lock type.
doUnlockByType(array $pathsByType)
Stable to override.
doLock(array $paths, $type)
Lock resources with the given keys and lock type.
getBucketFromPath( $path)
Get the bucket for resource path.