annotate core/lib/Drupal/Core/Lock/LockBackendAbstract.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 4c8ae668cc8c
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Core\Lock;
Chris@0 4
Chris@0 5 /**
Chris@0 6 * Non backend related common methods implementation for lock backends.
Chris@0 7 *
Chris@0 8 * @ingroup lock
Chris@0 9 */
Chris@0 10 abstract class LockBackendAbstract implements LockBackendInterface {
Chris@0 11
Chris@0 12 /**
Chris@0 13 * Current page lock token identifier.
Chris@0 14 *
Chris@0 15 * @var string
Chris@0 16 */
Chris@0 17 protected $lockId;
Chris@0 18
Chris@0 19 /**
Chris@0 20 * Existing locks for this page.
Chris@0 21 *
Chris@0 22 * @var array
Chris@0 23 */
Chris@0 24 protected $locks = [];
Chris@0 25
Chris@0 26 /**
Chris@0 27 * {@inheritdoc}
Chris@0 28 */
Chris@0 29 public function wait($name, $delay = 30) {
Chris@0 30 // Pause the process for short periods between calling
Chris@0 31 // lock_may_be_available(). This prevents hitting the database with constant
Chris@0 32 // database queries while waiting, which could lead to performance issues.
Chris@0 33 // However, if the wait period is too long, there is the potential for a
Chris@0 34 // large number of processes to be blocked waiting for a lock, especially
Chris@0 35 // if the item being rebuilt is commonly requested. To address both of these
Chris@0 36 // concerns, begin waiting for 25ms, then add 25ms to the wait period each
Chris@0 37 // time until it reaches 500ms. After this point polling will continue every
Chris@0 38 // 500ms until $delay is reached.
Chris@0 39
Chris@0 40 // $delay is passed in seconds, but we will be using usleep(), which takes
Chris@0 41 // microseconds as a parameter. Multiply it by 1 million so that all
Chris@0 42 // further numbers are equivalent.
Chris@0 43 $delay = (int) $delay * 1000000;
Chris@0 44
Chris@0 45 // Begin sleeping at 25ms.
Chris@0 46 $sleep = 25000;
Chris@0 47 while ($delay > 0) {
Chris@0 48 // This function should only be called by a request that failed to get a
Chris@0 49 // lock, so we sleep first to give the parallel request a chance to finish
Chris@0 50 // and release the lock.
Chris@0 51 usleep($sleep);
Chris@0 52 // After each sleep, increase the value of $sleep until it reaches
Chris@0 53 // 500ms, to reduce the potential for a lock stampede.
Chris@0 54 $delay = $delay - $sleep;
Chris@0 55 $sleep = min(500000, $sleep + 25000, $delay);
Chris@0 56 if ($this->lockMayBeAvailable($name)) {
Chris@0 57 // No longer need to wait.
Chris@0 58 return FALSE;
Chris@0 59 }
Chris@0 60 }
Chris@0 61 // The caller must still wait longer to get the lock.
Chris@0 62 return TRUE;
Chris@0 63 }
Chris@0 64
Chris@0 65 /**
Chris@0 66 * {@inheritdoc}
Chris@0 67 */
Chris@0 68 public function getLockId() {
Chris@0 69 if (!isset($this->lockId)) {
Chris@0 70 $this->lockId = uniqid(mt_rand(), TRUE);
Chris@0 71 }
Chris@0 72 return $this->lockId;
Chris@0 73 }
Chris@0 74
Chris@0 75 }