? block_cache_8.patch ? block_cache_9.patch Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.274 diff -u -F^f -r1.274 block.module --- modules/block/block.module 24 Jul 2007 18:17:30 -0000 1.274 +++ modules/block/block.module 9 Aug 2007 16:42:49 -0000 @@ -13,6 +13,19 @@ define('BLOCK_REGION_NONE', -1); /** + * Flags defining cache granularity for cached blocks. + * + * BLOCK_CACHE_CUSTOM lets modules define their own critrions + * using hook_block('cache_id'). + */ +define('BLOCK_NO_CACHE', -1); +define('BLOCK_CACHE_GLOBAL', 0x0001); +define('BLOCK_CACHE_PER_PAGE', 0x0002); +define('BLOCK_CACHE_PER_USER', 0x0004); +define('BLOCK_CACHE_PER_ROLE', 0x0008); +define('BLOCK_CACHE_CUSTOM', 0x0010); + +/** * Implementation of hook_help(). */ function block_help($path, $arg) { @@ -235,6 +248,7 @@ function _block_rehash() { foreach ($module_blocks as $delta => $block) { $block['module'] = $module; $block['delta'] = $delta; + $block['cache'] = isset($block['cache']) ? $block['cache'] : BLOCK_CACHE_PER_ROLE; // If previously written to database, load values. if (!empty($old_blocks[$module][$delta])) { $block['status'] = $old_blocks[$module][$delta]->status; @@ -271,7 +285,7 @@ function _block_rehash() { 'visibility' => NULL, 'throttle' => NULL, ); - db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle, title) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d, '%s')", $block['module'], $block['delta'], $theme_key, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle'], $block['title']); + db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle, title, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d, '%s', %d)", $block['module'], $block['delta'], $theme_key, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle'], $block['title'], $block['cache']); } db_unlock_tables(); @@ -429,7 +443,19 @@ function block_list($region) { // Check the current throttle status and see if block should be displayed // based on server load. if (!($block->throttle && (module_invoke('throttle', 'status') > 0))) { - $array = module_invoke($block->module, 'block', 'view', $block->delta); + // Try fetching the block from cache. Block caching is not compatible with + // node_access modules. We also preserve the submission of forms in blocks, + // by fetching from cache only if the request is 'GET'. + if (!count(module_implements('node_grants')) && $_SERVER['REQUEST_METHOD'] == 'GET' && ($cid = _block_get_cache_id($block)) && ($cache = cache_get($cid, 'cache_block'))) { + $array = $cache->data; + } + else { + $array = module_invoke($block->module, 'block', 'view', $block->delta); + if (isset($cid)) { + cache_set($cid, $array, 'cache_block', variable_get('cache_lifetime', CACHE_TEMPORARY)); + } + } + if (isset($array) && is_array($array)) { foreach ($array as $k => $v) { $block->$k = $v; @@ -453,3 +479,57 @@ function block_list($region) { } return $blocks[$region]; } + +/** + * Determine the block caching granularity. + * + * @param $block + * @return + * The string used as cid for the block + */ +function _block_get_cache_id($block) { + global $theme, $base_root, $user; + + // User 1 being out of the regular 'roles define permissions' schema, + // it brings too many chances of having unwanted output get in the cache + // and later be served to other users. + if (variable_get('block_cache', 0) && $block->cache != BLOCK_NO_CACHE && $user->uid != 1) { + + $base_cid = "$block->module:$block->delta:$theme"; + if (module_exists('locale')) { + global $language; + $base_cid .= ":$language->language"; + } + + $cid_parts = array(); + + // Let the module define specific cache granularity. + if ($block->cache & BLOCK_CACHE_CUSTOM) { + $cid_parts[] = module_invoke($block->module, 'block', 'cache_id', $block->delta); + } + + // 'per role' and 'per user' are mutually exclusive : + // we favor the less expensive 'per role'. + if ($block->cache & BLOCK_CACHE_PER_ROLE) { + $cid_parts[] = 'r_'. implode(',', array_keys($user->roles)); + } + elseif ($block->cache & BLOCK_CACHE_PER_USER) { + $cid_parts[] = "u_$user->uid"; + } + + if ($block->cache & BLOCK_CACHE_PER_PAGE) { + $cid_parts[] = $base_root . request_uri(); + } + + return "$base_cid:". implode(':', $cid_parts); + } +} + +/** + * Implementation of hook_cron(). + * + * Expire outdated block cache entries + */ +function block_cron() { + cache_clear_all(NULL, 'cache_block'); +} Index: modules/block/block.schema =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.schema,v retrieving revision 1.1 diff -u -F^f -r1.1 block.schema --- modules/block/block.schema 25 May 2007 12:46:43 -0000 1.1 +++ modules/block/block.schema 9 Aug 2007 16:42:49 -0000 @@ -15,7 +15,8 @@ function block_schema() { 'throttle' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), 'visibility' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), 'pages' => array('type' => 'text', 'not null' => TRUE), - 'title' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => '') + 'title' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => ''), + 'cache' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), ), 'primary key' => array('bid'), ); @@ -44,6 +45,8 @@ function block_schema() { 'primary key' => array('bid'), ); + $schema['cache_block'] = drupal_get_schema_unprocessed('system', 'cache'); + return $schema; } Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.570 diff -u -F^f -r1.570 comment.module --- modules/comment/comment.module 30 Jul 2007 21:27:34 -0000 1.570 +++ modules/comment/comment.module 9 Aug 2007 16:42:49 -0000 @@ -270,6 +270,7 @@ function comment_perm() { function comment_block($op = 'list', $delta = 0) { if ($op == 'list') { $blocks[0]['info'] = t('Recent comments'); + $blocks[1]['cache_mode'] = BLOCK_CACHE_PER_ROLE; return $blocks; } else if ($op == 'view' && user_access('access comments')) { Index: modules/forum/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v retrieving revision 1.412 diff -u -F^f -r1.412 forum.module --- modules/forum/forum.module 3 Aug 2007 06:07:52 -0000 1.412 +++ modules/forum/forum.module 9 Aug 2007 16:42:50 -0000 @@ -357,7 +357,9 @@ function forum_block($op = 'list', $delt switch ($op) { case 'list': $blocks[0]['info'] = t('Active forum topics'); + $blocks[0]['cache_mode'] = BLOCK_CACHE_PER_PAGE & BLOCK_CACHE_PER_USER; $blocks[1]['info'] = t('New forum topics'); + $blocks[1]['cache_mode'] = BLOCK_CACHE_PER_PAGE & BLOCK_CACHE_PER_USER; return $blocks; case 'configure': Index: modules/menu/menu.module =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v retrieving revision 1.132 diff -u -F^f -r1.132 menu.module --- modules/menu/menu.module 29 Jul 2007 17:28:23 -0000 1.132 +++ modules/menu/menu.module 9 Aug 2007 16:42:50 -0000 @@ -635,6 +635,8 @@ function menu_block($op = 'list', $delta foreach ($custom_menus as $name => $title) { // Default "Navigation" block is handled by user.module. $blocks[$name]['info'] = check_plain($title); + // Menu blocks might be different even for the same path. + $blocks[$name]['cache'] = BLOCK_NO_CACHE; } return $blocks; } Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.866 diff -u -F^f -r1.866 node.module --- modules/node/node.module 9 Aug 2007 11:00:59 -0000 1.866 +++ modules/node/node.module 9 Aug 2007 16:42:50 -0000 @@ -1896,6 +1896,7 @@ function node_admin_search() { function node_block($op = 'list', $delta = 0) { if ($op == 'list') { $blocks[0]['info'] = t('Syndicate'); + $blocks[0]['cache'] = BLOCK_CACHE_GLOBAL; return $blocks; } else if ($op == 'view') { Index: modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.132 diff -u -F^f -r1.132 system.install --- modules/system/system.install 7 Aug 2007 08:32:43 -0000 1.132 +++ modules/system/system.install 9 Aug 2007 16:42:51 -0000 @@ -3476,6 +3476,28 @@ function system_update_6026() { } /** + * Add cache_block table. + */ +function system_update_6027() { + $ret = array(); + db_add_field($ret, 'blocks', 'cache', array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny')); + $schema['cache_block'] = array( + 'fields' => array( + 'cid' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), + 'data' => array('type' => 'blob', 'not null' => FALSE, 'size' => 'big'), + 'expire' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), + 'created' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), + 'headers' => array('type' => 'text', 'not null' => FALSE), + 'serialized' => array('type' => 'int', 'size' => 'small', 'not null' => TRUE, 'default' => 0) + ), + 'indexes' => array('expire' => array('expire')), + 'primary key' => array('cid'), + ); + db_create_table($ret, $schema['cache_block']); + return $ret; +} + +/** * @} End of "defgroup updates-5.x-to-6.x" * The next series of updates should start at 7000. */ Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.513 diff -u -F^f -r1.513 system.module --- modules/system/system.module 2 Aug 2007 20:19:02 -0000 1.513 +++ modules/system/system.module 9 Aug 2007 16:42:51 -0000 @@ -682,7 +682,7 @@ function system_performance_settings() { $form['page_cache'] = array( '#type' => 'fieldset', '#title' => t('Page cache'), - '#description' => t('Enabling the cache will offer a significant performance boost. Drupal can store and send compressed cached pages requested by anonymous users. By caching a web page, Drupal does not have to construct the page each time someone wants to view it.'), + '#description' => t('Enabling the page cache will offer a significant performance boost. Drupal can store and send compressed cached pages requested by anonymous users. By caching a web page, Drupal does not have to construct the page each time someone wants to view it.'), ); $form['page_cache']['cache'] = array( @@ -703,6 +703,21 @@ function system_performance_settings() { '#description' => t('On high-traffic sites it can become necessary to enforce a minimum cache lifetime. The minimum cache lifetime is the minimum amount of time that will go by before the cache is emptied and recreated. A larger minimum cache lifetime offers better performance, but users will not see new content for a longer period of time.') ); + $form['block_cache'] = array( + '#type' => 'fieldset', + '#title' => t('Block cache'), + '#description' => t('Enabling the block cache will enhance performance for pages requested by any user (anonymous or authenticated). It can be enabled or disabled indenpendently of the page cache.'), + ); + + $form['block_cache']['block_cache'] = array( + '#type' => 'radios', + '#title' => t('Block cache'), + '#default_value' => variable_get('block_cache', CACHE_DISABLED), + '#options' => array(CACHE_DISABLED => t('Disabled'), CACHE_NORMAL => t('Enabled (recommended)')), + '#disabled' => count(module_implements('node_grants')), + '#description' => t('Note that block caching is inactive when modules defining content access restrictions are enabled.'), + ); + $form['bandwidth_optimizations'] = array( '#type' => 'fieldset', '#title' => t('Bandwidth optimizations'), Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.827 diff -u -F^f -r1.827 user.module --- modules/user/user.module 9 Aug 2007 10:49:26 -0000 1.827 +++ modules/user/user.module 9 Aug 2007 16:42:52 -0000 @@ -628,10 +628,14 @@ function user_block($op = 'list', $delta if ($op == 'list') { $blocks[0]['info'] = t('User login'); + // Contains a redirect url which changes with each page view. + $blocks[0]['cache'] = BLOCK_CACHE_PER_PAGE; $blocks[1]['info'] = t('Navigation'); + $blocks[1]['cache'] = BLOCK_CACHE_PER_PAGE & BLOCK_CACHE_PER_USER; $blocks[2]['info'] = t('Who\'s new'); + // Too dynamic to cache $blocks[3]['info'] = t('Who\'s online'); - + $blocks[3]['cache'] = BLOCK_NO_CACHE; return $blocks; } else if ($op == 'configure' && $delta == 2) {