diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index be8c695..9853260 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -2661,70 +2661,3 @@ function drupal_check_memory_limit($required, $memory_limit = NULL) { // the operation. 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. - * - * @deprecated Use \Drupal::lock() instead, or even better have the lock service - * injected into your object. - * - * @return \Drupal\Core\Lock\LockBackendInterface - */ -function lock() { - return \Drupal::lock(); -} - -/** - * @} End of "defgroup lock". - */ diff --git a/core/includes/menu.inc b/core/includes/menu.inc index bbf5c43..812ea8e 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -2448,11 +2448,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; } @@ -2472,7 +2472,7 @@ function menu_router_rebuild() { watchdog_exception('menu', $e); } - lock()->release(__FUNCTION__); + \Drupal::lock()->release(__FUNCTION__); return TRUE; } diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php index cc68937..36b56b8 100644 --- a/core/lib/Drupal.php +++ b/core/lib/Drupal.php @@ -222,6 +222,8 @@ public static function keyValueExpirable($collection) { * Returns the locking layer instance. * * @return \Drupal\Core\Lock\LockBackendInterface + * + * @ingroup lock */ public static function lock() { return static::$container->get('lock'); diff --git a/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php b/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php index f3cd803..2024272 100644 --- a/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php +++ b/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php @@ -12,6 +12,8 @@ /** * Defines the database lock backend. This is the default backend in Drupal. + * + * @ingroup lock */ class DatabaseLockBackend extends LockBackendAbstract { diff --git a/core/lib/Drupal/Core/Lock/LockBackendAbstract.php b/core/lib/Drupal/Core/Lock/LockBackendAbstract.php index f6ca89c..1b9e194 100644 --- a/core/lib/Drupal/Core/Lock/LockBackendAbstract.php +++ b/core/lib/Drupal/Core/Lock/LockBackendAbstract.php @@ -9,6 +9,8 @@ /** * Non backend related common methods implementation for lock backends. + * + * @ingroup lock */ abstract class LockBackendAbstract implements LockBackendInterface { diff --git a/core/lib/Drupal/Core/Lock/LockBackendInterface.php b/core/lib/Drupal/Core/Lock/LockBackendInterface.php index 438f89c..97e255d 100644 --- a/core/lib/Drupal/Core/Lock/LockBackendInterface.php +++ b/core/lib/Drupal/Core/Lock/LockBackendInterface.php @@ -8,7 +8,63 @@ 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() { + * if (\Drupal::lock()->acquire('mymodule_long_operation')) { + * // Do the long operation here. + * // ... + * \Drupal::lock()->release('mymodule_long_operation'); + * } + * } + * @endcode + * + * If a function acquires a lock it should always release it when the + * operation is complete by calling \Drupal::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 \Drupal::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 \Drupal::lock()->wait() if the rest of the current page request + * requires that the operation in question be complete. After + * \Drupal::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. + * + * \Drupal::lock()->acquire() and \Drupal::lock()->wait() will automatically + * break (delete) a lock whose duration has exceeded the timeout specified when + * it was acquired. + */ + +/** * Lock backend interface. + * + * @ingroup lock */ interface LockBackendInterface { diff --git a/core/lib/Drupal/Core/Lock/NullLockBackend.php b/core/lib/Drupal/Core/Lock/NullLockBackend.php index bd59888..7a37cd4 100644 --- a/core/lib/Drupal/Core/Lock/NullLockBackend.php +++ b/core/lib/Drupal/Core/Lock/NullLockBackend.php @@ -12,6 +12,8 @@ * * This implementation won't actually lock anything and will always succeed on * lock attempts. + * + * @ingroup lock */ class NullLockBackend implements LockBackendInterface { diff --git a/core/lib/Drupal/Core/Utility/CacheArray.php b/core/lib/Drupal/Core/Utility/CacheArray.php index 2323756..e2be92e 100644 --- a/core/lib/Drupal/Core/Utility/CacheArray.php +++ b/core/lib/Drupal/Core/Utility/CacheArray.php @@ -201,13 +201,13 @@ protected function set($data, $lock = TRUE) { // 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 = cache($this->bin)->get($this->cid)) { $data = $cached->data + $data; } cache($this->bin)->set($this->cid, $data, Cache::PERMANENT, $this->tags); if ($lock) { - lock()->release($lock_name); + \Drupal::lock()->release($lock_name); } } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Lock/LockFunctionalTest.php b/core/modules/system/lib/Drupal/system/Tests/Lock/LockFunctionalTest.php index bf868db..d72c667 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Lock/LockFunctionalTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Lock/LockFunctionalTest.php @@ -35,34 +35,34 @@ public static function getInfo() { public function testLockAcquire() { $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(\Drupal::lock()->acquire('system_test_lock_acquire'), 'Lock acquired by this request.', 'Lock'); + $this->assertTrue(\Drupal::lock()->acquire('system_test_lock_acquire'), 'Lock extended by this request.', 'Lock'); + \Drupal::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(\Drupal::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'); + \Drupal::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(\Drupal::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(\Drupal::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(\Drupal::lock()->acquire('system_test_lock_exit'), 'Lock acquired by this request after the other request exits.', 'Lock'); } } diff --git a/core/modules/system/tests/modules/system_test/system_test.module b/core/modules/system/tests/modules/system_test/system_test.module index 040d9f3..c7278c9 100644 --- a/core/modules/system/tests/modules/system_test/system_test.module +++ b/core/modules/system/tests/modules/system_test/system_test.module @@ -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();