31 $status = StatusValue::newGood();
33 $pathsByTypeByBucket = [];
35 foreach ( $pathsByType as $type => $paths ) {
36 foreach ( $paths as
$path ) {
37 if ( isset( $this->locksHeld[
$path][$type] ) ) {
38 ++$this->locksHeld[
$path][$type];
41 $pathsByTypeByBucket[$bucket][$type][] =
$path;
48 ksort( $pathsByTypeByBucket );
52 foreach ( $pathsByTypeByBucket as $bucket => $bucketPathsByType ) {
55 if ( !$status->isOK() ) {
61 foreach ( $bucketPathsByType as $type => $paths ) {
62 foreach ( $paths as
$path ) {
63 $this->locksHeld[
$path][$type] = 1;
65 $lockedPaths[$type][] =
$path;
81 $status = StatusValue::newGood();
83 $pathsByTypeByBucket = [];
84 foreach ( $pathsByType as $type => $paths ) {
85 foreach ( $paths as
$path ) {
86 if ( !isset( $this->locksHeld[
$path][$type] ) ) {
87 $status->warning(
'lockmanager-notlocked',
$path );
89 --$this->locksHeld[
$path][$type];
91 if ( $this->locksHeld[
$path][$type] <= 0 ) {
92 unset( $this->locksHeld[
$path][$type] );
94 $pathsByTypeByBucket[$bucket][$type][] =
$path;
96 if ( $this->locksHeld[
$path] === [] ) {
97 unset( $this->locksHeld[
$path] );
105 foreach ( $pathsByTypeByBucket as $bucket => $bucketPathsByType ) {
108 if ( $this->locksHeld === [] ) {
110 $this->degradedBuckets = [];
125 $status = StatusValue::newGood();
128 $votesLeft = count( $this->srvsByBucket[$bucket] );
129 $quorum = floor( $votesLeft / 2 + 1 );
131 foreach ( $this->srvsByBucket[$bucket] as $lockSrv ) {
134 $status->warning(
'lockmanager-fail-svr-acquire', $lockSrv );
135 $this->degradedBuckets[$bucket] = time();
140 if ( !$status->isOK() ) {
144 if ( $yesVotes >= $quorum ) {
148 $votesNeeded = $quorum - $yesVotes;
149 if ( $votesNeeded > $votesLeft ) {
154 $status->setResult(
false );
167 $status = StatusValue::newGood();
170 $votesLeft = count( $this->srvsByBucket[$bucket] );
171 $quorum = floor( $votesLeft / 2 + 1 );
172 $isDegraded = isset( $this->degradedBuckets[$bucket] );
173 foreach ( $this->srvsByBucket[$bucket] as $lockSrv ) {
175 $status->warning(
'lockmanager-fail-svr-release', $lockSrv );
182 if ( $yesVotes >= $quorum && !$isDegraded ) {
189 $status->setResult( $yesVotes >= $quorum );
202 $prefix = substr( sha1(
$path ), 0, 2 );
203 return (
int)base_convert( $prefix, 16, 10 ) % count( $this->srvsByBucket );
245 final protected function doLock( array $paths, $type ) {
247 throw new LogicException( __METHOD__ .
': proxy class does not need this method.' );
251 final protected function doUnlock( array $paths, $type ) {
253 throw new LogicException( __METHOD__ .
': proxy class does not need this method.' );
257class_alias( QuorumLockManager::class,
'QuorumLockManager' );
Generic operation result class Has warning/error list, boolean status and arbitrary value.