X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Flibs%2Fobjectcache%2FBagOStuff.php;h=d3deefb6fd0033547c6c64f2665ad8d160d0cd78;hb=12313956c58e88b98d4baf722464e09b4a351bf3;hp=a679be8f0cf7ac50cc3e7a4560e2fed98105d8f7;hpb=e99bb1b7dcc4c52a74b60ca445f20b8db649222c;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/libs/objectcache/BagOStuff.php b/includes/libs/objectcache/BagOStuff.php index a679be8f0c..d3deefb6fd 100644 --- a/includes/libs/objectcache/BagOStuff.php +++ b/includes/libs/objectcache/BagOStuff.php @@ -29,6 +29,7 @@ use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; +use Wikimedia\WaitConditionLoop; /** * interface is intended to be more or less compatible with @@ -410,35 +411,21 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface { } $expiry = min( $expiry ?: INF, self::TTL_DAY ); - - $this->clearLastError(); - $timestamp = microtime( true ); // starting UNIX timestamp - if ( $this->add( "{$key}:lock", 1, $expiry ) ) { - $locked = true; - } elseif ( $this->getLastError() || $timeout <= 0 ) { - $locked = false; // network partition or non-blocking - } else { - // Estimate the RTT (us); use 1ms minimum for sanity - $uRTT = max( 1e3, ceil( 1e6 * ( microtime( true ) - $timestamp ) ) ); - $sleep = 2 * $uRTT; // rough time to do get()+set() - - $attempts = 0; // failed attempts - do { - if ( ++$attempts >= 3 && $sleep <= 5e5 ) { - // Exponentially back off after failed attempts to avoid network spam. - // About 2*$uRTT*(2^n-1) us of "sleep" happen for the next n attempts. - $sleep *= 2; - } - usleep( $sleep ); // back off + $loop = new WaitConditionLoop( + function () use ( $key, $timeout, $expiry ) { $this->clearLastError(); - $locked = $this->add( "{$key}:lock", 1, $expiry ); - if ( $this->getLastError() ) { - $locked = false; // network partition - break; + if ( $this->add( "{$key}:lock", 1, $expiry ) ) { + return true; // locked! + } elseif ( $this->getLastError() ) { + return WaitConditionLoop::CONDITION_ABORTED; // network partition? } - } while ( !$locked && ( microtime( true ) - $timestamp ) < $timeout ); - } + return WaitConditionLoop::CONDITION_CONTINUE; + }, + $timeout + ); + + $locked = ( $loop->invoke() === $loop::CONDITION_REACHED ); if ( $locked ) { $this->locks[$key] = [ 'class' => $rclass, 'depth' => 1 ]; }