function DatabaseLockBackend::acquire

Same name in this branch
  1. 8.9.x core/lib/Drupal/Core/ProxyClass/Lock/DatabaseLockBackend.php \Drupal\Core\ProxyClass\Lock\DatabaseLockBackend::acquire()
Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/ProxyClass/Lock/DatabaseLockBackend.php \Drupal\Core\ProxyClass\Lock\DatabaseLockBackend::acquire()
  2. 9 core/lib/Drupal/Core/Lock/DatabaseLockBackend.php \Drupal\Core\Lock\DatabaseLockBackend::acquire()
  3. 10 core/lib/Drupal/Core/ProxyClass/Lock/DatabaseLockBackend.php \Drupal\Core\ProxyClass\Lock\DatabaseLockBackend::acquire()
  4. 10 core/lib/Drupal/Core/Lock/DatabaseLockBackend.php \Drupal\Core\Lock\DatabaseLockBackend::acquire()
  5. 11.x core/lib/Drupal/Core/ProxyClass/Lock/DatabaseLockBackend.php \Drupal\Core\ProxyClass\Lock\DatabaseLockBackend::acquire()
  6. 11.x core/lib/Drupal/Core/Lock/DatabaseLockBackend.php \Drupal\Core\Lock\DatabaseLockBackend::acquire()

Overrides LockBackendInterface::acquire

File

core/lib/Drupal/Core/Lock/DatabaseLockBackend.php, line 45

Class

DatabaseLockBackend
Defines the database lock backend. This is the default backend in Drupal.

Namespace

Drupal\Core\Lock

Code

public function acquire($name, $timeout = 30.0) {
    $name = $this->normalizeName($name);
    // Insure that the timeout is at least 1 ms.
    $timeout = max($timeout, 0.001);
    $expire = microtime(TRUE) + $timeout;
    if (isset($this->locks[$name])) {
        // Try to extend the expiration of a lock we already acquired.
        $success = (bool) $this->database
            ->update('semaphore')
            ->fields([
            'expire' => $expire,
        ])
            ->condition('name', $name)
            ->condition('value', $this->getLockId())
            ->execute();
        if (!$success) {
            // The lock was broken.
            unset($this->locks[$name]);
        }
        return $success;
    }
    else {
        // Optimistically try to acquire the lock, then retry once if it fails.
        // The first time through the loop cannot be a retry.
        $retry = FALSE;
        // We always want to do this code at least once.
        do {
            try {
                $this->database
                    ->insert('semaphore')
                    ->fields([
                    'name' => $name,
                    'value' => $this->getLockId(),
                    'expire' => $expire,
                ])
                    ->execute();
                // We track all acquired locks in the global variable.
                $this->locks[$name] = TRUE;
                // We never need to try again.
                $retry = FALSE;
            } catch (IntegrityConstraintViolationException $e) {
                // Suppress the error. If this is our first pass through the loop,
                // then $retry is FALSE. In this case, the insert failed because some
                // other request acquired the lock but did not release it. We decide
                // whether to retry by checking lockMayBeAvailable(). This will clear
                // the offending row from the database table in case it has expired.
                $retry = $retry ? FALSE : $this->lockMayBeAvailable($name);
            } catch (\Exception $e) {
                // Create the semaphore table if it does not exist and retry.
                if ($this->ensureTableExists()) {
                    // Retry only once.
                    $retry = !$retry;
                }
                else {
                    throw $e;
                }
            }
            // We only retry in case the first attempt failed, but we then broke
            // an expired lock.
        } while ($retry);
    }
    return isset($this->locks[$name]);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.