diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 9b4667e..a6d4e82 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -939,6 +939,32 @@ function drupal_get_filename($type, $name, $filename = NULL) { } /** + * Extends DrupalCacheArray to allow for cumulative caching of variables. + */ +class VariableCache extends DrupalCacheArray { + protected function resolveCacheMiss($offset) { + $result = db_query('SELECT value FROM {variable} WHERE name = :name', array(':name' => $offset))->fetchField(); + $value = $result ? unserialize($result) : NULL; + $this->storage[$offset] = $value; + $this->persist($offset); + return $value; + } + + /** + * Replace the storage variable with a separate array. + * + * @return + * The value of the storage variable before it was replaced. + */ + public function replaceStorage($array) { + $return = $this->storage; + $this->storage = $array; + $this->keysToPersist = array(); + return $return; + } +} + +/** * Load the persistent variable table. * * The variable table is composed of values that have been saved in the table @@ -946,27 +972,11 @@ function drupal_get_filename($type, $name, $filename = NULL) { * file. */ function variable_initialize($conf = array()) { - // NOTE: caching the variables improves performance by 20% when serving - // cached pages. - if ($cached = cache('bootstrap')->get('variables')) { - $variables = $cached->data; - } - else { - // Cache miss. Avoid a stampede. - $name = 'variable_init'; - if (!lock_acquire($name, 1)) { - // Another request is building the variable cache. - // Wait, then re-run this function. - lock_wait($name); - return variable_initialize($conf); - } - else { - // Proceed with variable rebuild. - $variables = array_map('unserialize', db_query('SELECT name, value FROM {variable}')->fetchAllKeyed()); - cache('bootstrap')->set('variables', $variables); - lock_release($name); - } - } + $cache = &drupal_static('variables'); + $cache = new VariableCache('variables', 'cache_bootstrap'); + // Copy the cached variables, free memory in the cache array by setting it + // to empty. + $variables = $cache->replaceStorage(array()); foreach ($conf as $name => $value) { $variables[$name] = $value; @@ -995,8 +1005,15 @@ function variable_initialize($conf = array()) { */ function variable_get($name, $default = NULL) { global $conf; - - return isset($conf[$name]) ? $conf[$name] : $default; + if (isset($conf[$name])) { + return $conf[$name]; + } + $cache = &drupal_static('variables'); + if (isset($cache) && isset($cache[$name])) { + $conf[$name] = $cache[$name]; + return $conf[$name]; + } + return $default; } /** @@ -1019,10 +1036,22 @@ function variable_set($name, $value) { global $conf; db_merge('variable')->key(array('name' => $name))->fields(array('value' => serialize($value)))->execute(); - - cache('bootstrap')->delete('variables'); - $conf[$name] = $value; + + $cache = &drupal_static('variables'); + if (is_object($cache)) { + // Write through to the variable cache. + $replace = array(); + if ($cached = cache('bootstrap')->get('variables')) { + $cached->data[$name] = $value; + cache('bootstrap')->set('variables', $cached->data); + $replace = $cached->data; + } + $cache->replaceStorage($replace); + } + else { + cache('bootstrap')->delete('variables'); + } } /** @@ -1044,9 +1073,19 @@ function variable_del($name) { db_delete('variable') ->condition('name', $name) ->execute(); - cache('bootstrap')->delete('variables'); - unset($conf[$name]); + + $cache = &drupal_static('variables'); + if (is_object($cache)) { + unset($cache[$name]); + if ($cached = cache('bootstrap')->get('variables')) { + unset($cache->data[$name]); + cache('bootstrap')->set('variables', $cached->data); + } + } + else { + cache('bootstrap')->delete('variables'); + } } /** diff --git a/core/modules/simpletest/tests/batch.test b/core/modules/simpletest/tests/batch.test index 1e9b31b..505332d 100644 --- a/core/modules/simpletest/tests/batch.test +++ b/core/modules/simpletest/tests/batch.test @@ -83,6 +83,7 @@ class BatchProcessingTestCase extends DrupalWebTestCase { $this->assertBatchMessages($this->_resultMessages('batch_1'), t('Batch for step 1 performed successfully.')); $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), t('Execution order was correct.')); $this->assertText('step 2', t('Form is displayed in step 2.')); + drupal_static_reset('variables'); // Second step triggers batch 2. $this->drupalPost(NULL, array(), 'Submit');