39 $status = StatusValue::newGood();
41 $pathsByTypeByBucket = [];
43 foreach ( $pathsByType as
$type => $paths ) {
44 foreach ( $paths as
$path ) {
45 if ( isset( $this->locksHeld[
$path][
$type] ) ) {
49 $pathsByTypeByBucket[$bucket][
$type][] =
$path;
56 ksort( $pathsByTypeByBucket );
60 foreach ( $pathsByTypeByBucket as $bucket => $bucketPathsByType ) {
63 if ( !$status->isOK() ) {
69 foreach ( $bucketPathsByType as
$type => $paths ) {
70 foreach ( $paths as
$path ) {
82 $status = StatusValue::newGood();
84 $pathsByTypeByBucket = [];
85 foreach ( $pathsByType as
$type => $paths ) {
86 foreach ( $paths as
$path ) {
87 if ( !isset( $this->locksHeld[
$path][
$type] ) ) {
88 $status->warning(
'lockmanager-notlocked',
$path );
95 $pathsByTypeByBucket[$bucket][
$type][] =
$path;
97 if ( $this->locksHeld[
$path] === [] ) {
98 unset( $this->locksHeld[
$path] );
106 foreach ( $pathsByTypeByBucket as $bucket => $bucketPathsByType ) {
109 if ( $this->locksHeld === [] ) {
111 $this->degradedBuckets = [];
128 function ( $lockSrv ) use ( $pathsByType ) {
144 function ( $lockSrv ) use ( $pathsByType ) {
159 $status = StatusValue::newGood();
162 $votesLeft = count( $this->srvsByBucket[$bucket] );
163 $quorum = floor( $votesLeft / 2 + 1 );
165 foreach ( $this->srvsByBucket[$bucket] as $lockSrv ) {
168 $status->warning(
'lockmanager-fail-svr-acquire', $lockSrv );
169 $this->degradedBuckets[$bucket] = time();
173 $status->merge( $callback( $lockSrv ) );
174 if ( !$status->isOK() ) {
178 if ( $yesVotes >= $quorum ) {
182 $votesNeeded = $quorum - $yesVotes;
183 if ( $votesNeeded > $votesLeft ) {
188 $status->setResult(
false );
201 $status = StatusValue::newGood();
204 $votesLeft = count( $this->srvsByBucket[$bucket] );
205 $quorum = floor( $votesLeft / 2 + 1 );
206 $isDegraded = isset( $this->degradedBuckets[$bucket] );
207 foreach ( $this->srvsByBucket[$bucket] as $lockSrv ) {
209 $status->warning(
'lockmanager-fail-svr-release', $lockSrv );
212 $status->merge( $callback( $lockSrv ) );
216 if ( $yesVotes >= $quorum && !$isDegraded ) {
223 $status->setResult( $yesVotes >= $quorum );
236 $prefix = substr( sha1(
$path ), 0, 2 );
237 return (
int)base_convert( $prefix, 16, 10 ) % count( $this->srvsByBucket );
279 throw new LogicException( __METHOD__ .
': proxy class does not need this method.' );
283 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)
doLock(array $paths, $type)
Lock resources with the given keys and lock type.
getBucketFromPath( $path)
Get the bucket for resource path.