diff -uNr includes/bootstrap.inc includes/bootstrap.inc --- includes/bootstrap.inc 2009-01-04 08:15:54.000000000 -0800 +++ includes/bootstrap.inc 2009-01-13 22:55:26.000000000 -0800 @@ -120,36 +120,41 @@ define('DRUPAL_BOOTSTRAP_ACCESS', 3); /** + * Fifth bootstrap phase: initialize locking system. + */ +define('DRUPAL_BOOTSTRAP_LOCK', 4); + +/** * Fifth bootstrap phase: initialize session handling. */ -define('DRUPAL_BOOTSTRAP_SESSION', 4); +define('DRUPAL_BOOTSTRAP_SESSION', 5); /** * Sixth bootstrap phase: initialize the variable system. */ -define('DRUPAL_BOOTSTRAP_VARIABLES', 5); +define('DRUPAL_BOOTSTRAP_VARIABLES', 6); /** * Seventh bootstrap phase: load bootstrap.inc and module.inc, start * the variable system and try to serve a page from the cache. */ -define('DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE', 6); +define('DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE', 7); /** * Eighth bootstrap phase: find out language of the page. */ -define('DRUPAL_BOOTSTRAP_LANGUAGE', 7); +define('DRUPAL_BOOTSTRAP_LANGUAGE', 8); /** * Nineth bootstrap phase: set $_GET['q'] to Drupal path of request. */ -define('DRUPAL_BOOTSTRAP_PATH', 8); +define('DRUPAL_BOOTSTRAP_PATH', 9); /** * Final bootstrap phase: Drupal is fully loaded; validate and fix * input data. */ -define('DRUPAL_BOOTSTRAP_FULL', 9); +define('DRUPAL_BOOTSTRAP_FULL', 10); /** * Role ID for anonymous users; should match what's in the "role" table. @@ -1049,6 +1054,7 @@ * DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE: try to call a non-database cache fetch routine. * DRUPAL_BOOTSTRAP_DATABASE: initialize database layer. * DRUPAL_BOOTSTRAP_ACCESS: identify and reject banned hosts. + * DRUPAL_BOOTSTRAP_LOCK: initialize locking system. * DRUPAL_BOOTSTRAP_SESSION: initialize session handling. * DRUPAL_BOOTSTRAP_VARIABLES: initialize variable handling. * DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE: load bootstrap.inc and module.inc, start @@ -1058,7 +1064,7 @@ * DRUPAL_BOOTSTRAP_FULL: Drupal is fully loaded, validate and fix input data. */ function drupal_bootstrap($phase = NULL) { - static $phases = array(DRUPAL_BOOTSTRAP_CONFIGURATION, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_VARIABLES, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1; + static $phases = array(DRUPAL_BOOTSTRAP_CONFIGURATION, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_LOCK, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_VARIABLES, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1; if (isset($phase)) { while ($phases && $phase > $completed_phase) { @@ -1125,6 +1131,11 @@ } break; + case DRUPAL_BOOTSTRAP_LOCK: + require_once variable_get('lock_inc', './includes/lock.inc'); + lock_init(); + break; + case DRUPAL_BOOTSTRAP_SESSION: require_once DRUPAL_ROOT . '/' . variable_get('session_inc', 'includes/session.inc'); session_set_save_handler('_sess_open', '_sess_close', '_sess_read', '_sess_write', '_sess_destroy_sid', '_sess_gc'); diff -uNr includes/lock.inc includes/lock.inc --- includes/lock.inc 1969-12-31 16:00:00.000000000 -0800 +++ includes/lock.inc 2009-01-13 23:23:36.000000000 -0800 @@ -0,0 +1,101 @@ += $timeout) { + return FALSE; + } + } + return TRUE; + } +} + +/** + * Release a lock previously acquired by lock_acquire(). + * + * @param $name + * The name of the lock. + */ +function lock_release($name) { + global $locks; + if (isset($locks[$name])) { + cache_clear_all($name, 'cache_lock'); + unset($locks[$name]); + } +} + +/** + * Release all previously acquired locks. + */ +function lock_release_all() { + global $locks; + if (!empty($locks)) { + foreach ($locks as $lock_id => $value) { + cache_clear_all($lock_id, 'cache_lock'); + unset($locks[$lock_id]); + } + } +} \ No newline at end of file diff -uNr includes/menu.inc includes/menu.inc --- includes/menu.inc 2009-01-04 12:04:32.000000000 -0800 +++ includes/menu.inc 2009-01-13 22:51:01.000000000 -0800 @@ -1783,15 +1783,20 @@ * is different and leaves stale data in the menu tables. */ function menu_rebuild() { + if (!lock_acquire('menu_rebuild')) { + return FALSE; + } variable_del('menu_rebuild_needed'); menu_cache_clear_all(); $menu = menu_router_build(TRUE); _menu_navigation_links_rebuild($menu); + // Clear the menu cache after we have rebuild the router and navigation links // Clear the page and block caches. _menu_clear_page_cache(); if (defined('MAINTENANCE_MODE')) { variable_set('menu_rebuild_needed', TRUE); } + lock_release('menu_rebuild'); } /** @@ -1799,7 +1804,6 @@ */ function menu_router_build($reset = FALSE) { static $menu; - if (!isset($menu) || $reset) { if (!$reset && ($cache = cache_get('router:', 'cache_menu')) && isset($cache->data)) { $menu = $cache->data; diff -uNr modules/locale/locale.module modules/locale/locale.module --- modules/locale/locale.module 2008-12-16 15:57:32.000000000 -0800 +++ modules/locale/locale.module 2009-01-13 22:57:23.000000000 -0800 @@ -377,11 +377,14 @@ // 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. - $result = db_query("SELECT s.source, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.textgroup = 'default' AND s.version = '%s' AND LENGTH(s.source) < 75", $langcode, VERSION); - while ($data = db_fetch_object($result)) { - $locale_t[$langcode][$data->source] = (empty($data->translation) ? TRUE : $data->translation); + if (lock_acquire('locale_cache_' . $langcode)) { + $result = db_query("SELECT s.source, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.textgroup = 'default' AND s.version = '%s' AND LENGTH(s.source) < 75", $langcode, VERSION); + while ($data = db_fetch_object($result)) { + $locale_t[$langcode][$data->source] = (empty($data->translation) ? TRUE : $data->translation); + } + cache_set('locale:' . $langcode, $locale_t[$langcode]); + lock_release('locale_cache_' . $langcode); } - cache_set('locale:' . $langcode, $locale_t[$langcode]); } } } diff -uNr modules/system/system.install modules/system/system.install --- modules/system/system.install 2009-01-13 23:06:18.000000000 -0800 +++ modules/system/system.install 2009-01-13 23:06:54.000000000 -0800 @@ -598,7 +598,9 @@ $schema['cache_menu']['description'] = 'Cache table for the menu system to store router information as well as generated link trees for various menu/page/user combinations.'; $schema['cache_registry'] = $schema['cache']; $schema['cache_registry']['description'] = 'Cache table for the code registry system to remember what code files need to be loaded on any given page.'; - + $schema['cache_lock'] = $schema['cache']; + $schema['cache_lock']['description'] = t('Cache table for the lock system to allow long operations without race conditions.'); + $schema['files'] = array( 'description' => 'Stores information for uploaded files.', 'fields' => array(