Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. Lock.php

class Lock

Same name in this branch
  1. 11.1.x core/lib/Drupal/Core/TempStore/Lock.php \Drupal\Core\TempStore\Lock

Lock is the default implementation of the LockInterface.

@author Jérémy Derussé <jeremy@derusse.com>

Hierarchy

  • class \Symfony\Component\Lock\Lock implements \Symfony\Component\Lock\SharedLockInterface, \Psr\Log\LoggerAwareInterface uses \Psr\Log\LoggerAwareTrait

Expanded class hierarchy of Lock

1 file declares its use of Lock
LockConflictedException.php in vendor/symfony/lock/Exception/LockConflictedException.php
18 string references to 'Lock'
BumpCommand::doBump in vendor/composer/composer/src/Composer/Command/BumpCommand.php
CheckPlatformReqsCommand::execute in vendor/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php
Executes the current command.
CKEditor5ImageController::create in core/modules/ckeditor5/src/Controller/CKEditor5ImageController.php
Instantiates a new instance of the implementing class using autowiring.
Config::get in vendor/composer/composer/src/Composer/Config.php
Returns a setting
Factory::createComposer in vendor/composer/composer/src/Composer/Factory.php
Creates a Composer instance

... See full list

File

vendor/symfony/lock/Lock.php, line 27

Namespace

Symfony\Component\Lock
View source
final class Lock implements SharedLockInterface, LoggerAwareInterface {
    use LoggerAwareTrait;
    private bool $dirty = false;
    
    /**
     * @param float|null $ttl         Maximum expected lock duration in seconds
     * @param bool       $autoRelease Whether to automatically release the lock or not when the lock instance is destroyed
     */
    public function __construct(Key $key, PersistingStoreInterface $store, ?float $ttl = null, bool $autoRelease = true) {
    }
    public function __sleep() : array {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __wakeup() : void {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    
    /**
     * Automatically releases the underlying lock when the object is destructed.
     */
    public function __destruct() {
        if (!$this->autoRelease || !$this->dirty || !$this->isAcquired()) {
            return;
        }
        $this->release();
    }
    public function acquire(bool $blocking = false) : bool {
        $this->key
            ->resetLifetime();
        try {
            if ($blocking) {
                if (!$this->store instanceof BlockingStoreInterface) {
                    while (true) {
                        try {
                            $this->store
                                ->save($this->key);
                            break;
                        } catch (LockConflictedException) {
                            usleep((100 + random_int(-10, 10)) * 1000);
                        }
                    }
                }
                else {
                    $this->store
                        ->waitAndSave($this->key);
                }
            }
            else {
                $this->store
                    ->save($this->key);
            }
            $this->dirty = true;
            $this->logger?->debug('Successfully acquired the "{resource}" lock.', [
                'resource' => $this->key,
            ]);
            if ($this->ttl) {
                $this->refresh();
            }
            if ($this->key
                ->isExpired()) {
                try {
                    $this->release();
                } catch (\Exception) {
                    // swallow exception to not hide the original issue
                }
                throw new LockExpiredException(\sprintf('Failed to store the "%s" lock.', $this->key));
            }
            return true;
        } catch (LockConflictedException $e) {
            $this->dirty = false;
            $this->logger?->info('Failed to acquire the "{resource}" lock. Someone else already acquired the lock.', [
                'resource' => $this->key,
            ]);
            if ($blocking) {
                throw $e;
            }
            return false;
        } catch (\Exception $e) {
            $this->logger?->notice('Failed to acquire the "{resource}" lock.', [
                'resource' => $this->key,
                'exception' => $e,
            ]);
            throw new LockAcquiringException(\sprintf('Failed to acquire the "%s" lock.', $this->key), 0, $e);
        }
    }
    public function acquireRead(bool $blocking = false) : bool {
        $this->key
            ->resetLifetime();
        try {
            if (!$this->store instanceof SharedLockStoreInterface) {
                $this->logger?->debug('Store does not support ReadLocks, fallback to WriteLock.', [
                    'resource' => $this->key,
                ]);
                return $this->acquire($blocking);
            }
            if ($blocking) {
                if (!$this->store instanceof BlockingSharedLockStoreInterface) {
                    while (true) {
                        try {
                            $this->store
                                ->saveRead($this->key);
                            break;
                        } catch (LockConflictedException) {
                            usleep((100 + random_int(-10, 10)) * 1000);
                        }
                    }
                }
                else {
                    $this->store
                        ->waitAndSaveRead($this->key);
                }
            }
            else {
                $this->store
                    ->saveRead($this->key);
            }
            $this->dirty = true;
            $this->logger?->debug('Successfully acquired the "{resource}" lock for reading.', [
                'resource' => $this->key,
            ]);
            if ($this->ttl) {
                $this->refresh();
            }
            if ($this->key
                ->isExpired()) {
                try {
                    $this->release();
                } catch (\Exception) {
                    // swallow exception to not hide the original issue
                }
                throw new LockExpiredException(\sprintf('Failed to store the "%s" lock.', $this->key));
            }
            return true;
        } catch (LockConflictedException $e) {
            $this->dirty = false;
            $this->logger?->info('Failed to acquire the "{resource}" lock. Someone else already acquired the lock.', [
                'resource' => $this->key,
            ]);
            if ($blocking) {
                throw $e;
            }
            return false;
        } catch (\Exception $e) {
            $this->logger?->notice('Failed to acquire the "{resource}" lock.', [
                'resource' => $this->key,
                'exception' => $e,
            ]);
            throw new LockAcquiringException(\sprintf('Failed to acquire the "%s" lock.', $this->key), 0, $e);
        }
    }
    public function refresh(?float $ttl = null) : void {
        if (!($ttl ??= $this->ttl)) {
            throw new InvalidArgumentException('You have to define an expiration duration.');
        }
        try {
            $this->key
                ->resetLifetime();
            $this->store
                ->putOffExpiration($this->key, $ttl);
            $this->dirty = true;
            if ($this->key
                ->isExpired()) {
                try {
                    $this->release();
                } catch (\Exception) {
                    // swallow exception to not hide the original issue
                }
                throw new LockExpiredException(\sprintf('Failed to put off the expiration of the "%s" lock within the specified time.', $this->key));
            }
            $this->logger?->debug('Expiration defined for "{resource}" lock for "{ttl}" seconds.', [
                'resource' => $this->key,
                'ttl' => $ttl,
            ]);
        } catch (LockConflictedException $e) {
            $this->dirty = false;
            $this->logger?->notice('Failed to define an expiration for the "{resource}" lock, someone else acquired the lock.', [
                'resource' => $this->key,
            ]);
            throw $e;
        } catch (\Exception $e) {
            $this->logger?->notice('Failed to define an expiration for the "{resource}" lock.', [
                'resource' => $this->key,
                'exception' => $e,
            ]);
            throw new LockAcquiringException(\sprintf('Failed to define an expiration for the "%s" lock.', $this->key), 0, $e);
        }
    }
    public function isAcquired() : bool {
        return $this->dirty = $this->store
            ->exists($this->key);
    }
    public function release() : void {
        try {
            try {
                $this->store
                    ->delete($this->key);
                $this->dirty = false;
            } catch (LockReleasingException $e) {
                throw $e;
            } catch (\Exception $e) {
                throw new LockReleasingException(\sprintf('Failed to release the "%s" lock.', $this->key), 0, $e);
            }
            if ($this->store
                ->exists($this->key)) {
                throw new LockReleasingException(\sprintf('Failed to release the "%s" lock, the resource is still locked.', $this->key));
            }
            $this->logger?->debug('Successfully released the "{resource}" lock.', [
                'resource' => $this->key,
            ]);
        } catch (LockReleasingException $e) {
            $this->logger?->notice('Failed to release the "{resource}" lock.', [
                'resource' => $this->key,
            ]);
            throw $e;
        }
    }
    public function isExpired() : bool {
        return $this->key
            ->isExpired();
    }
    public function getRemainingLifetime() : ?float {
        return $this->key
            ->getRemainingLifetime();
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
Lock::$dirty private property
Lock::acquire public function Acquires the lock. If the lock is acquired by someone else, the parameter `blocking` determines whether or not
the call should block until the release of the lock.
Overrides LockInterface::acquire
Lock::acquireRead public function Acquires the lock for reading. If the lock is acquired by someone else in write mode, the parameter `blocking`
determines whether or not the call should block until the release of the lock.
Overrides SharedLockInterface::acquireRead
Lock::getRemainingLifetime public function Returns the remaining lifetime in seconds. Overrides LockInterface::getRemainingLifetime
Lock::isAcquired public function Returns whether or not the lock is acquired. Overrides LockInterface::isAcquired
Lock::isExpired public function Overrides LockInterface::isExpired
Lock::refresh public function Increase the duration of an acquired lock. Overrides LockInterface::refresh
Lock::release public function Release the lock. Overrides LockInterface::release
Lock::__construct public function
Lock::__destruct public function Automatically releases the underlying lock when the object is destructed.
Lock::__sleep public function
Lock::__wakeup public function
LoggerAwareTrait::$logger protected property The logger instance.
LoggerAwareTrait::setLogger public function Sets a logger.
RSS feed
Powered by Drupal