Issue #2044367 by InternetDevels, Berdir, wildflower_0002, ianthomas_uk, ParisLiakos, Xano | cosmicdreams: Replace calls to lock() with \Drupal::lock().
parent
aa49131293
commit
08a9a7993d
|
@ -2577,57 +2577,6 @@ function drupal_check_memory_limit($required, $memory_limit = NULL) {
|
|||
return ((!$memory_limit) || ($memory_limit == -1) || (parse_size($memory_limit) >= parse_size($required)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @defgroup lock Locking mechanisms
|
||||
* @{
|
||||
* Functions to coordinate long-running operations across requests.
|
||||
*
|
||||
* In most environments, multiple Drupal page requests (a.k.a. threads or
|
||||
* processes) will execute in parallel. This leads to potential conflicts or
|
||||
* race conditions when two requests execute the same code at the same time. A
|
||||
* common example of this is a rebuild like menu_router_rebuild() where we
|
||||
* invoke many hook implementations to get and process data from all active
|
||||
* modules, and then delete the current data in the database to insert the new
|
||||
* afterwards.
|
||||
*
|
||||
* This is a cooperative, advisory lock system. Any long-running operation
|
||||
* that could potentially be attempted in parallel by multiple requests should
|
||||
* try to acquire a lock before proceeding. By obtaining a lock, one request
|
||||
* notifies any other requests that a specific operation is in progress which
|
||||
* must not be executed in parallel.
|
||||
*
|
||||
* To use this API, pick a unique name for the lock. A sensible choice is the
|
||||
* name of the function performing the operation. A very simple example use of
|
||||
* this API:
|
||||
* @code
|
||||
* function mymodule_long_operation() {
|
||||
* if (lock()->acquire('mymodule_long_operation')) {
|
||||
* // Do the long operation here.
|
||||
* // ...
|
||||
* lock()->release('mymodule_long_operation');
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* If a function acquires a lock it should always release it when the
|
||||
* operation is complete by calling lock()->release(), as in the example.
|
||||
*
|
||||
* A function that has acquired a lock may attempt to renew a lock (extend the
|
||||
* duration of the lock) by calling lock()->acquire() again during the operation.
|
||||
* Failure to renew a lock is indicative that another request has acquired
|
||||
* the lock, and that the current operation may need to be aborted.
|
||||
*
|
||||
* If a function fails to acquire a lock it may either immediately return, or
|
||||
* it may call lock()->wait() if the rest of the current page request requires
|
||||
* that the operation in question be complete. After lock()->wait() returns,
|
||||
* the function may again attempt to acquire the lock, or may simply allow the
|
||||
* page request to proceed on the assumption that a parallel request completed
|
||||
* the operation.
|
||||
*
|
||||
* lock()->acquire() and lock()->wait() will automatically break (delete) a lock
|
||||
* whose duration has exceeded the timeout specified when it was acquired.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get locking layer instance.
|
||||
*
|
||||
|
@ -2639,7 +2588,3 @@ function drupal_check_memory_limit($required, $memory_limit = NULL) {
|
|||
function lock() {
|
||||
return \Drupal::lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "defgroup lock".
|
||||
*/
|
||||
|
|
|
@ -2140,11 +2140,11 @@ function menu_reset_static_cache() {
|
|||
* in parallel and the current thread just waited for completion.
|
||||
*/
|
||||
function menu_router_rebuild() {
|
||||
if (!lock()->acquire(__FUNCTION__)) {
|
||||
if (!\Drupal::lock()->acquire(__FUNCTION__)) {
|
||||
// Wait for another request that is already doing this work.
|
||||
// We choose to block here since otherwise the router item may not
|
||||
// be available during routing resulting in a 404.
|
||||
lock()->wait(__FUNCTION__);
|
||||
\Drupal::lock()->wait(__FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -2164,7 +2164,7 @@ function menu_router_rebuild() {
|
|||
watchdog_exception('menu', $e);
|
||||
}
|
||||
|
||||
lock()->release(__FUNCTION__);
|
||||
\Drupal::lock()->release(__FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -245,6 +245,8 @@ class Drupal {
|
|||
* Returns the locking layer instance.
|
||||
*
|
||||
* @return \Drupal\Core\Lock\LockBackendInterface
|
||||
*
|
||||
* @ingroup lock
|
||||
*/
|
||||
public static function lock() {
|
||||
return static::$container->get('lock');
|
||||
|
|
|
@ -12,6 +12,8 @@ use Drupal\Core\Database\IntegrityConstraintViolationException;
|
|||
|
||||
/**
|
||||
* Defines the database lock backend. This is the default backend in Drupal.
|
||||
*
|
||||
* @ingroup lock
|
||||
*/
|
||||
class DatabaseLockBackend extends LockBackendAbstract {
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ namespace Drupal\Core\Lock;
|
|||
|
||||
/**
|
||||
* Non backend related common methods implementation for lock backends.
|
||||
*
|
||||
* @ingroup lock
|
||||
*/
|
||||
abstract class LockBackendAbstract implements LockBackendInterface {
|
||||
|
||||
|
|
|
@ -7,8 +7,64 @@
|
|||
|
||||
namespace Drupal\Core\Lock;
|
||||
|
||||
/**
|
||||
* @defgroup lock Locking mechanisms
|
||||
* @{
|
||||
* Functions to coordinate long-running operations across requests.
|
||||
*
|
||||
* In most environments, multiple Drupal page requests (a.k.a. threads or
|
||||
* processes) will execute in parallel. This leads to potential conflicts or
|
||||
* race conditions when two requests execute the same code at the same time. A
|
||||
* common example of this is a rebuild like menu_router_rebuild() where we
|
||||
* invoke many hook implementations to get and process data from all active
|
||||
* modules, and then delete the current data in the database to insert the new
|
||||
* afterwards.
|
||||
*
|
||||
* This is a cooperative, advisory lock system. Any long-running operation
|
||||
* that could potentially be attempted in parallel by multiple requests should
|
||||
* try to acquire a lock before proceeding. By obtaining a lock, one request
|
||||
* notifies any other requests that a specific operation is in progress which
|
||||
* must not be executed in parallel.
|
||||
*
|
||||
* To use this API, pick a unique name for the lock. A sensible choice is the
|
||||
* name of the function performing the operation. A very simple example use of
|
||||
* this API:
|
||||
* @code
|
||||
* function mymodule_long_operation() {
|
||||
* $lock = \Drupal::lock();
|
||||
* if ($lock->acquire('mymodule_long_operation')) {
|
||||
* // Do the long operation here.
|
||||
* // ...
|
||||
* $lock->release('mymodule_long_operation');
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* If a function acquires a lock it should always release it when the operation
|
||||
* is complete by calling $lock->release(), as in the example.
|
||||
*
|
||||
* A function that has acquired a lock may attempt to renew a lock (extend the
|
||||
* duration of the lock) by calling $lock->acquire() again during the operation.
|
||||
* Failure to renew a lock is indicative that another request has acquired the
|
||||
* lock, and that the current operation may need to be aborted.
|
||||
*
|
||||
* If a function fails to acquire a lock it may either immediately return, or
|
||||
* it may call $lock->wait() if the rest of the current page request requires
|
||||
* that the operation in question be complete. After $lock->wait() returns, the
|
||||
* function may again attempt to acquire the lock, or may simply allow the page
|
||||
* request to proceed on the assumption that a parallel request completed the
|
||||
* operation.
|
||||
*
|
||||
* $lock->acquire() and $lock->wait() will automatically break (delete) a lock
|
||||
* whose duration has exceeded the timeout specified when it was acquired.
|
||||
*
|
||||
* @} End of "defgroup lock".
|
||||
*/
|
||||
|
||||
/**
|
||||
* Lock backend interface.
|
||||
*
|
||||
* @ingroup lock
|
||||
*/
|
||||
interface LockBackendInterface {
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ namespace Drupal\Core\Lock;
|
|||
*
|
||||
* This implementation won't actually lock anything and will always succeed on
|
||||
* lock attempts.
|
||||
*
|
||||
* @ingroup lock
|
||||
*/
|
||||
class NullLockBackend implements LockBackendInterface {
|
||||
|
||||
|
|
|
@ -202,13 +202,13 @@ abstract class CacheArray implements \ArrayAccess {
|
|||
// Lock cache writes to help avoid stampedes.
|
||||
// To implement locking for cache misses, override __construct().
|
||||
$lock_name = $this->cid . ':' . $this->bin;
|
||||
if (!$lock || lock()->acquire($lock_name)) {
|
||||
if (!$lock || \Drupal::lock()->acquire($lock_name)) {
|
||||
if ($cached = \Drupal::cache($this->bin)->get($this->cid)) {
|
||||
$data = $cached->data + $data;
|
||||
}
|
||||
\Drupal::cache($this->bin)->set($this->cid, $data, Cache::PERMANENT, $this->tags);
|
||||
if ($lock) {
|
||||
lock()->release($lock_name);
|
||||
\Drupal::lock()->release($lock_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,36 +33,37 @@ class LockFunctionalTest extends WebTestBase {
|
|||
* Confirms that we can acquire and release locks in two parallel requests.
|
||||
*/
|
||||
public function testLockAcquire() {
|
||||
$lock = $this->container->get('lock');
|
||||
$lock_acquired = 'TRUE: Lock successfully acquired in system_test_lock_acquire()';
|
||||
$lock_not_acquired = 'FALSE: Lock not acquired in system_test_lock_acquire()';
|
||||
$this->assertTrue(lock()->acquire('system_test_lock_acquire'), 'Lock acquired by this request.', 'Lock');
|
||||
$this->assertTrue(lock()->acquire('system_test_lock_acquire'), 'Lock extended by this request.', 'Lock');
|
||||
lock()->release('system_test_lock_acquire');
|
||||
$this->assertTrue($lock->acquire('system_test_lock_acquire'), 'Lock acquired by this request.', 'Lock');
|
||||
$this->assertTrue($lock->acquire('system_test_lock_acquire'), 'Lock extended by this request.', 'Lock');
|
||||
$lock->release('system_test_lock_acquire');
|
||||
|
||||
// Cause another request to acquire the lock.
|
||||
$this->drupalGet('system-test/lock-acquire');
|
||||
$this->assertText($lock_acquired, 'Lock acquired by the other request.', 'Lock');
|
||||
// The other request has finished, thus it should have released its lock.
|
||||
$this->assertTrue(lock()->acquire('system_test_lock_acquire'), 'Lock acquired by this request.', 'Lock');
|
||||
$this->assertTrue($lock->acquire('system_test_lock_acquire'), 'Lock acquired by this request.', 'Lock');
|
||||
// This request holds the lock, so the other request cannot acquire it.
|
||||
$this->drupalGet('system-test/lock-acquire');
|
||||
$this->assertText($lock_not_acquired, 'Lock not acquired by the other request.', 'Lock');
|
||||
lock()->release('system_test_lock_acquire');
|
||||
$lock->release('system_test_lock_acquire');
|
||||
|
||||
// Try a very short timeout and lock breaking.
|
||||
$this->assertTrue(lock()->acquire('system_test_lock_acquire', 0.5), 'Lock acquired by this request.', 'Lock');
|
||||
$this->assertTrue($lock->acquire('system_test_lock_acquire', 0.5), 'Lock acquired by this request.', 'Lock');
|
||||
sleep(1);
|
||||
// The other request should break our lock.
|
||||
$this->drupalGet('system-test/lock-acquire');
|
||||
$this->assertText($lock_acquired, 'Lock acquired by the other request, breaking our lock.', 'Lock');
|
||||
// We cannot renew it, since the other thread took it.
|
||||
$this->assertFalse(lock()->acquire('system_test_lock_acquire'), 'Lock cannot be extended by this request.', 'Lock');
|
||||
$this->assertFalse($lock->acquire('system_test_lock_acquire'), 'Lock cannot be extended by this request.', 'Lock');
|
||||
|
||||
// Check the shut-down function.
|
||||
$lock_acquired_exit = 'TRUE: Lock successfully acquired in system_test_lock_exit()';
|
||||
$lock_not_acquired_exit = 'FALSE: Lock not acquired in system_test_lock_exit()';
|
||||
$this->drupalGet('system-test/lock-exit');
|
||||
$this->assertText($lock_acquired_exit, 'Lock acquired by the other request before exit.', 'Lock');
|
||||
$this->assertTrue(lock()->acquire('system_test_lock_exit'), 'Lock acquired by this request after the other request exits.', 'Lock');
|
||||
$this->assertTrue($lock->acquire('system_test_lock_exit'), 'Lock acquired by this request after the other request exits.', 'Lock');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,8 +77,8 @@ function system_test_system_info_alter(&$info, $file, $type) {
|
|||
* @deprecated \Drupal\system_test\Controller\SystemTestController::lockAcquire()
|
||||
*/
|
||||
function system_test_lock_acquire() {
|
||||
if (lock()->acquire('system_test_lock_acquire')) {
|
||||
lock()->release('system_test_lock_acquire');
|
||||
if (\Drupal::lock()->acquire('system_test_lock_acquire')) {
|
||||
\Drupal::lock()->release('system_test_lock_acquire');
|
||||
return 'TRUE: Lock successfully acquired in system_test_lock_acquire()';
|
||||
}
|
||||
else {
|
||||
|
@ -92,7 +92,7 @@ function system_test_lock_acquire() {
|
|||
* @deprecated \Drupal\system_test\Controller\SystemTestController::lockExit()
|
||||
*/
|
||||
function system_test_lock_exit() {
|
||||
if (lock()->acquire('system_test_lock_exit', 900)) {
|
||||
if (\Drupal::lock()->acquire('system_test_lock_exit', 900)) {
|
||||
echo 'TRUE: Lock successfully acquired in system_test_lock_exit()';
|
||||
// The shut-down function should release the lock.
|
||||
exit();
|
||||
|
|
Loading…
Reference in New Issue