summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2009-08-17 20:32:30 +0000
committerDries Buytaert <dries@buytaert.net>2009-08-17 20:32:30 +0000
commit9eb6dd5eaaebef55d0c7ddccd4e6a82d2b410070 (patch)
treec360c0a402895ce98d01425b0408ab0fab560080 /modules
parentb41323642bffd3761f73a8c9dc8260546d7533f1 (diff)
downloadbrdo-9eb6dd5eaaebef55d0c7ddccd4e6a82d2b410070.tar.gz
brdo-9eb6dd5eaaebef55d0c7ddccd4e6a82d2b410070.tar.bz2
- Patch #251792 by pwolanin, Damien Tournoud, slantview, c960657: added a locking framework for long running operations.
Diffstat (limited to 'modules')
-rw-r--r--modules/locale/locale.module3
-rw-r--r--modules/simpletest/simpletest.info1
-rw-r--r--modules/simpletest/tests/lock.test58
-rw-r--r--modules/simpletest/tests/system_test.module40
-rw-r--r--modules/system/system.install28
5 files changed, 129 insertions, 1 deletions
diff --git a/modules/locale/locale.module b/modules/locale/locale.module
index cb37d8cbf..dcb046cdf 100644
--- a/modules/locale/locale.module
+++ b/modules/locale/locale.module
@@ -375,7 +375,7 @@ function locale($string = NULL, $context = NULL, $langcode = NULL, $reset = FALS
if ($cache = cache_get('locale:' . $langcode, 'cache')) {
$locale_t[$langcode] = $cache->data;
}
- else {
+ elseif (lock_acquire('locale_cache_' . $langcode)) {
// Refresh database stored cache of translations for given language.
// We only store short strings used in current version, to improve
// performance and consume less memory.
@@ -384,6 +384,7 @@ function locale($string = NULL, $context = NULL, $langcode = NULL, $reset = FALS
$locale_t[$langcode][$data->context][$data->source] = (empty($data->translation) ? TRUE : $data->translation);
}
cache_set('locale:' . $langcode, $locale_t[$langcode]);
+ lock_release('locale_cache_' . $langcode);
}
}
}
diff --git a/modules/simpletest/simpletest.info b/modules/simpletest/simpletest.info
index dc3974902..9d307eb5b 100644
--- a/modules/simpletest/simpletest.info
+++ b/modules/simpletest/simpletest.info
@@ -24,6 +24,7 @@ files[] = tests/filetransfer.test
files[] = tests/form.test
files[] = tests/graph.test
files[] = tests/image.test
+files[] = tests/lock.test
files[] = tests/menu.test
files[] = tests/module.test
files[] = tests/registry.test
diff --git a/modules/simpletest/tests/lock.test b/modules/simpletest/tests/lock.test
new file mode 100644
index 000000000..d9fc53f75
--- /dev/null
+++ b/modules/simpletest/tests/lock.test
@@ -0,0 +1,58 @@
+<?php
+// $Id$
+
+/**
+ * Tests for the lock system.
+ */
+class LockFunctionalTest extends DrupalWebTestCase {
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Locking framework tests',
+ 'description' => 'Confirm locking works between two separate requests.',
+ 'group' => 'System',
+ );
+ }
+
+ function setUp() {
+ parent::setUp('system_test');
+ }
+
+ /**
+ * Confirm that we can acquire and release locks in two parallel requests.
+ */
+ 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'), t('Lock acquired by this request.'), t('Lock'));
+ $this->assertTrue(lock_acquire('system_test_lock_acquire'), t('Lock extended by this request.'), t('Lock'));
+ lock_release('system_test_lock_acquire');
+
+ // Cause another request to acquire the lock.
+ $this->drupalGet('system-test/lock-acquire');
+ $this->assertText($lock_acquired, t('Lock acquired by the other request.'), t('Lock'));
+ // The other request has finished, thus it should have released its lock.
+ $this->assertTrue(lock_acquire('system_test_lock_acquire'), t('Lock acquired by this request.'), t('Lock'));
+ // This request holds the lock, so the other request cannot acquire it.
+ $this->drupalGet('system-test/lock-acquire');
+ $this->assertText($lock_not_acquired, t('Lock not acquired by the other request.'), t('Lock'));
+ lock_release('system_test_lock_acquire');
+
+ // Try a very short timeout and lock breaking.
+ $this->assertTrue(lock_acquire('system_test_lock_acquire', 0.5), t('Lock acquired by this request.'), t('Lock'));
+ sleep(1);
+ // The other request should break our lock.
+ $this->drupalGet('system-test/lock-acquire');
+ $this->assertText($lock_acquired, t('Lock acquired by the other request, breaking our lock.'), t('Lock'));
+ // We cannot renew it, since the other thread took it.
+ $this->assertFalse(lock_acquire('system_test_lock_acquire'), t('Lock cannot be extended by this request.'), t('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, t('Lock acquired by the other request before exit.'), t('Lock'));
+ $this->assertTrue(lock_acquire('system_test_lock_exit'), t('Lock acquired by this request after the other request exits.'), t('Lock'));
+ }
+}
+
diff --git a/modules/simpletest/tests/system_test.module b/modules/simpletest/tests/system_test.module
index 3f0a1acef..90a8f28a0 100644
--- a/modules/simpletest/tests/system_test.module
+++ b/modules/simpletest/tests/system_test.module
@@ -59,6 +59,20 @@ function system_test_menu() {
'type' => MENU_CALLBACK,
);
+ $items['system-test/lock-acquire'] = array(
+ 'title' => 'Lock acquire',
+ 'page callback' => 'system_test_lock_acquire',
+ 'access callback' => TRUE,
+ 'type' => MENU_CALLBACK,
+ );
+
+ $items['system-test/lock-exit'] = array(
+ 'title' => 'Lock acquire then exit',
+ 'page callback' => 'system_test_lock_exit',
+ 'access callback' => TRUE,
+ 'type' => MENU_CALLBACK,
+ );
+
return $items;
}
@@ -185,3 +199,29 @@ function system_test_system_info_alter(&$info, $file) {
}
}
+/**
+ * Try to acquire a named lock and report the outcome.
+ */
+function system_test_lock_acquire() {
+ if (lock_acquire('system_test_lock_acquire')) {
+ lock_release('system_test_lock_acquire');
+ return 'TRUE: Lock successfully acquired in system_test_lock_acquire()';
+ }
+ else {
+ return 'FALSE: Lock not acquired in system_test_lock_acquire()';
+ }
+}
+
+/**
+ * Try to acquire a specific lock, and then exit.
+ */
+function system_test_lock_exit() {
+ if (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();
+ }
+ else {
+ return 'FALSE: Lock not acquired in system_test_lock_exit()';
+ }
+}
diff --git a/modules/system/system.install b/modules/system/system.install
index 3ff1c5905..83a0f268b 100644
--- a/modules/system/system.install
+++ b/modules/system/system.install
@@ -1265,6 +1265,34 @@ function system_schema() {
'primary key' => array('filename'),
);
+ $schema['semaphore'] = array(
+ 'description' => 'Table for holding semaphores, locks, flags, etc. that cannot be stored as Drupal variables since they must not be cached.',
+ 'fields' => array(
+ 'name' => array(
+ 'description' => 'Primary Key: Unique name.',
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => ''
+ ),
+ 'value' => array(
+ 'description' => 'A value for the semaphore.',
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => ''
+ ),
+ 'expire' => array(
+ 'description' => 'A Unix timestamp with microseconds indicating when the semaphore should expire.',
+ 'type' => 'float',
+ 'size' => 'big',
+ 'not null' => TRUE
+ ),
+ ),
+ 'indexes' => array('value' => array('value')),
+ 'primary key' => array('name'),
+ );
+
$schema['sessions'] = array(
'description' => "Drupal's session handlers read and write into the sessions table. Each record represents a user session, either anonymous or authenticated.",
'fields' => array(