From 44ed771a1cc48a6ad196412f88697132d5f669c7 Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole Date: Thu, 19 Dec 2013 17:54:14 +0000 Subject: [PATCH] Issue #1976172 by chx, andypost: Comment entity acquired and releases the different locks. --- .../comment/CommentStorageController.php | 5 - .../lib/Drupal/comment/Entity/Comment.php | 14 ++- .../comment/Tests/Entity/CommentLockTest.php | 95 +++++++++++++++++++ 3 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 core/modules/comment/tests/Drupal/comment/Tests/Entity/CommentLockTest.php diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php index e23af78c7df..d8c0cfe4b20 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php @@ -19,11 +19,6 @@ use Drupal\Core\Entity\EntityChangedInterface; */ class CommentStorageController extends FieldableDatabaseStorageController implements CommentStorageControllerInterface { - /** - * The thread for which a lock was acquired. - */ - protected $threadLock = ''; - /** * {@inheritdoc} */ diff --git a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php index d2c79bdc338..ddedfb042be 100644 --- a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php +++ b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php @@ -56,6 +56,11 @@ use Drupal\Core\TypedData\DataDefinition; */ class Comment extends ContentEntityBase implements CommentInterface { + /** + * The thread for which a lock was acquired. + */ + protected $threadLock = ''; + /** * The comment ID. * @@ -273,12 +278,13 @@ class Comment extends ContentEntityBase implements CommentInterface { } } // Finally, build the thread field for this new comment. To avoid - // race conditions, get a lock on the thread. If aother process already + // race conditions, get a lock on the thread. If another process already // has the lock, just move to the next integer. do { $thread = $prefix . comment_int_to_alphadecimal(++$n) . '/'; - } while (!lock()->acquire("comment:{$this->entity_id->value}:$thread")); - $this->threadLock = $thread; + $lock_name = "comment:{$this->entity_id->value}:$thread"; + } while (!\Drupal::lock()->acquire($lock_name)); + $this->threadLock = $lock_name; } if (empty($this->created->value)) { $this->created->value = REQUEST_TIME; @@ -316,7 +322,7 @@ class Comment extends ContentEntityBase implements CommentInterface { */ protected function releaseThreadLock() { if ($this->threadLock) { - lock()->release($this->threadLock); + \Drupal::lock()->release($this->threadLock); $this->threadLock = ''; } } diff --git a/core/modules/comment/tests/Drupal/comment/Tests/Entity/CommentLockTest.php b/core/modules/comment/tests/Drupal/comment/Tests/Entity/CommentLockTest.php new file mode 100644 index 00000000000..307a9b54bd7 --- /dev/null +++ b/core/modules/comment/tests/Drupal/comment/Tests/Entity/CommentLockTest.php @@ -0,0 +1,95 @@ + 'Comment locks', + 'description' => 'Test comment acquires and releases the right lock.', + 'group' => 'Comment', + ); + } + + /** + * Test the lock behavior. + */ + public function testLocks() { + $container = new ContainerBuilder(); + $container->set('current_user', $this->getMock('Drupal\Core\Session\AccountInterface')); + $container->register('request', 'Symfony\Component\HttpFoundation\Request'); + $lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface'); + $cid = 2; + $lock_name = "comment:$cid:./"; + $lock->expects($this->at(0)) + ->method('acquire') + ->with($lock_name, 30) + ->will($this->returnValue(TRUE)); + $lock->expects($this->at(1)) + ->method('release') + ->with($lock_name); + $lock->expects($this->exactly(2)) + ->method($this->anything()); + $container->set('lock', $lock); + \Drupal::setContainer($container); + $methods = get_class_methods('Drupal\comment\Entity\Comment'); + unset($methods[array_search('preSave', $methods)]); + unset($methods[array_search('postSave', $methods)]); + $comment = $this->getMockBuilder('Drupal\comment\Entity\Comment') + ->disableOriginalConstructor() + ->setMethods($methods) + ->getMock(); + $comment->expects($this->once()) + ->method('isNew') + ->will($this->returnValue(TRUE)); + foreach (array('status', 'pid', 'created', 'changed', 'entity_id', 'uid', 'thread', 'hostname') as $property) { + $comment->$property = new \stdClass(); + } + $comment->status->value = 1; + $comment->entity_id->value = $cid; + $comment->uid->target_id = 3; + $comment->pid->target_id = 42; + $comment->pid->entity = new \stdClass(); + $comment->pid->entity->thread = (object) array('value' => ''); + $storage_controller = $this->getMock('Drupal\comment\CommentStorageControllerInterface'); + $comment->preSave($storage_controller); + $comment->postSave($storage_controller); + } + + /** + * {@inheritdoc} + */ + protected function tearDown() { + parent::tearDown(); + $container = new ContainerBuilder(); + \Drupal::setContainer($container); + } + +} +} +namespace { +if (!function_exists('comment_int_to_alphadecimal')) { + function comment_int_to_alphadecimal() {} +} +if (!function_exists('module_invoke_all')) { + function module_invoke_all() {} +} +} +