--- includes/bootstrap.inc.orig 2005-04-03 00:20:10.000000000 -0500 +++ includes/bootstrap.inc 2005-04-03 00:25:23.000000000 -0500 @@ -9,6 +9,12 @@ define('CACHE_PERMANENT', 0); define('CACHE_TEMPORARY', -1); +define('CACHE_DISABLED', 0); +define('CACHE_ENABLED_STRICT', 1); +define('CACHE_ENABLED_LOOSE', 2); + +define('CACHE_LOOSE_DELAY', 300); + define('WATCHDOG_NOTICE', 0); define('WATCHDOG_WARNING', 1); define('WATCHDOG_ERROR', 2); @@ -194,11 +200,42 @@ * * @param $key * The cache ID of the data to retrieve. + * + * @param $recursive + * Flag to prevent loops when cache_get calls itself. */ -function cache_get($key) { - $cache = db_fetch_object(db_query("SELECT data, created, headers FROM {cache} WHERE cid = '%s'", $key)); +function cache_get($key, $recursive = 0) { + global $user, $global_cache; + $sid = session_id(); + + // CACHE_ENABLED_LOOSE garbage collection + $cache_flush = $recursive ? 0 : cache_get('cache_flush', 1); + if ($cache_flush->data && ($cache_flush->data + CACHE_LOOSE_DELAY <= time())) { + // time to flush old cache data + db_query("DELETE FROM {cache} WHERE expire != %d AND expire <= %d", CACHE_PERMANENT, $cache_flush->data); + cache_clear_all('cache_flush'); + } + + $cache = db_fetch_object(db_query("SELECT data, created, headers, expire FROM {cache} WHERE cid = '%s'", $key)); if (isset($cache->data)) { - $cache->data = db_decode_blob($cache->data); + // if data is permanent or using strict caching, always return data + if ($cache->expire == CACHE_PERMANENT || $global_cache == CACHE_ENABLED_STRICT) { + $cache->data = db_decode_blob($cache->data); + } + /* if using loose caching, validate data is current before we return it by + ** making sure the cache entry was created before the timestamp in this + ** session's cache timer. + */ + else { + $required = db_fetch_object(db_query("SELECT cache FROM {sessions} WHERE uid = %d and sid = '%s'", $user->uid, $sid)); + if ($required->cache > $cache->created) { + // this cache data is too old and thus not valid for us, ignore it + return 0; + } + else { + $cache->data = db_decode_blob($cache->data); + } + } return $cache; } return 0; @@ -235,16 +272,44 @@ * Expire data from the cache. * * @param $cid - * If set, the cache ID to delete. Otherwise, all cache entries that can expire - * are deleted. + * If set, the cache ID to delete. Otherwise, all cache entries that can + * expire are deleted. * * @param $wildcard * If set to true, the $cid is treated as a substring to match rather than a * complete ID. */ function cache_clear_all($cid = NULL, $wildcard = false) { + global $user, $global_cache; + $sid = session_id(); + if (empty($cid)) { - db_query("DELETE FROM {cache} WHERE expire != %d AND expire < %d", CACHE_PERMANENT, time()); + if ($global_cache == CACHE_ENABLED_STRICT) { + // strict caching, flush all temporary cache entries + db_query("DELETE FROM {cache} WHERE expire != %d AND expire < %d", CACHE_PERMANENT, time()); + } + else { + $cache_flush = cache_get('cache_flush', 1); + /* loose caching, only flush temporary cache entries that have been + ** invalidated for more than maximum allowable time. + */ + if ($cache_flush->data && ($cache_flush->data + CACHE_LOOSE_DELAY) <= time()) { + /* only flush cache data older than $cache_flush, as newer data may + ** now be valid. + */ + db_query("DELETE FROM {cache} WHERE expire != %d AND expire <= %d", CACHE_PERMANENT, $cache_flush->data); + cache_clear_all('cache_flush'); + } + /* invalidate temporary cache data only for current user/session by + ** updating the appropriate cache timestamp in the sessions table. + */ + db_query("UPDATE {sessions} SET cache = %d WHERE uid = %d AND sid = '%s'", time(), $user->uid, $sid); + $cache_flush = cache_get('cache_flush', 1); + if ($cache_flush->data == 0) { + // set timestamp to know which cache entries we eventually clear + cache_set('cache_flush', time(), CACHE_TEMPORARY); + } + } } else { if ($wildcard) { @@ -416,11 +481,10 @@ * Set HTTP headers in preparation for a page response. */ function drupal_page_header() { - if (variable_get('dev_timer', 0)) { - timer_start(); - } + global $global_cache; + timer_start(); - if (variable_get('cache', 0)) { + if ($global_cache) { if ($cache = page_get_cache()) { bootstrap_invoke_all('init'); // Set default values: --- sites/default/settings.php.orig 2005-04-02 22:42:05.000000000 -0500 +++ sites/default/settings.php 2005-04-03 00:33:53.000000000 -0500 @@ -69,6 +69,28 @@ $base_url = 'http://localhost'; /** + * Cache settings: + * + * Drupal has a caching mechanism which stores dynamically generated web pages + * in a database. By caching a web page, Drupal does not have to create the + * page each time someone wants to view it, instead it takes only one SQL query + * to display it, reducing response time and the server's load. Only pages + * requested by "anonymous" users are cached. In order to reduce server load + * and save bandwidth, Drupal stores and sends cached pages compressed. + * + * Drupal supports strict caching and loose caching. Strict caching immediately + * deletes cached data as soon as it becomes invalid for any user. Loose + * caching delays the deletion of cached data to provide better performance for + * high traffic web sites. + * + * Valid global cache configurations: + * $global_cache = CACHE_DISABLED; + * $global_cache = CACHE_ENABLED_STRICT; + * $global_cache = CACHE_ENABLED_LOOSE; + */ +$global_cache = CACHE_DISABLED; + +/** * PHP settings: * * To see what PHP settings are possible, including whether they can --- modules/system.module.orig 2005-04-02 22:39:52.000000000 -0500 +++ modules/system.module 2005-04-02 23:41:41.000000000 -0500 @@ -37,7 +37,7 @@
     00 * * * * /home/www/drupal/scripts/cron-lynx.sh
Note that it is essential to access cron.php using a browser on the web site's domain; do not run it using command line PHP and avoid using localhost or 127.0.0.1 or some of the environment variables will not be set correctly and features may not work as expected.

Cache

-

Drupal has a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, Drupal does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by \"anonymous\" users are cached. In order to reduce server load and save bandwidth, Drupal stores and sends cached pages compressed.

", array('%base_url' => $base_url, '%cron-link' => "$base_url/cron.php", '%lynx' => 'http://lynx.browser.org', '%wget' => 'http://www.gnu.org/software/wget/wget.html' )); +

Drupal has a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, Drupal does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by \"anonymous\" users are cached. In order to reduce server load and save bandwidth, Drupal stores and sends cached pages compressed. Drupal supports by strict caching and loose caching. Strict caching immediately deletes cached data as soon as it becomes invalid for any user. Loose caching delays the deletion of cached data to provide better performance for high traffic sites.

", array('%base_url' => $base_url, '%cron-link' => "$base_url/cron.php", '%lynx' => 'http://lynx.browser.org', '%wget' => 'http://www.gnu.org/software/wget/wget.html' )); case 'admin/modules#description': return t('Handles general site configuration for administrators.'); } @@ -224,11 +224,6 @@ $output .= form_group(t('Error handling'), $group); - // Caching: - $group = form_radios(t('Cache support'), 'cache', variable_get('cache', 0), array(t('Disabled'), t('Enabled')), t('Enable or disable the caching of rendered pages. When caching is enabled, Drupal will flush the cache when required to make sure updates take effect immediately. Check the cache documentation for information on Drupal\'s cache system.', array('%documentation' => url('admin/help', NULL, NULL, 'cache')))); - - $output .= form_group(t('Cache settings'), $group); - // File system: $directory_path = variable_get('file_directory_path', 'files'); file_check_directory($directory_path, FILE_CREATE_DIRECTORY, 'file_directory_path'); --- database/database.mysql.orig 2005-04-03 00:34:25.000000000 -0500 +++ database/database.mysql 2005-04-02 22:55:03.000000000 -0500 @@ -574,6 +574,7 @@ sid varchar(32) NOT NULL default '', hostname varchar(128) NOT NULL default '', timestamp int(11) NOT NULL default '0', + cache int(11) NOT NULL default '0', session longtext, KEY uid (uid), PRIMARY KEY (sid), --- database/database.pgsql.orig 2005-04-03 00:34:31.000000000 -0500 +++ database/database.pgsql 2005-04-02 22:55:03.000000000 -0500 @@ -587,6 +587,7 @@ sid varchar(32) NOT NULL default '', hostname varchar(128) NOT NULL default '', timestamp integer NOT NULL default '0', + cache integer NOT NULL default '0', session text, PRIMARY KEY (sid) ); --- database/updates.inc.orig 2005-04-03 00:34:39.000000000 -0500 +++ database/updates.inc 2005-04-02 22:55:03.000000000 -0500 @@ -105,6 +105,7 @@ "2005-03-03" => "update_126", "2005-03-18" => "update_127", "2005-03-21" => "update_128" + "2005-03-25: first update since Drupal 4.6.0 release" => "update_129", ); function update_32() { @@ -2350,4 +2351,15 @@ return $ret; } +function update_129() { + $ret = array(); + if ($GLOBALS['db_type'] == 'mysql') { + $ret[] = update_sql("ALTER TABLE sessions ADD cache int(11) NOT NULL default '0' AFTER timestamp"); + } + elseif ($GLOBALS['db_type'] == 'pgsql') { + $ret[] = update_sql("ALTER TABLE sessions ADD cache int(11) NOT NULL default '0' AFTER timestamp"); + } + return $ret; +} + ?>