cvs diff: Diffing modules/update
Index: modules/update/update.compare.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/update/update.compare.inc,v
retrieving revision 1.8.2.2
diff -u -p -r1.8.2.2 update.compare.inc
--- modules/update/update.compare.inc	28 Aug 2008 08:14:56 -0000	1.8.2.2
+++ modules/update/update.compare.inc	26 Apr 2009 08:51:54 -0000
@@ -30,7 +30,7 @@ function update_get_projects() {
       _update_process_info_list($projects, module_rebuild_cache(), 'module');
       _update_process_info_list($projects, system_theme_data(), 'theme');
       // Set the projects array into the cache table.
-      cache_set('update_project_projects', $projects, 'cache_update', time() + 3600);
+      _update_cache_set('update_project_projects', $projects, time() + 3600);
     }
   }
   return $projects;
@@ -551,17 +551,17 @@ function update_calculate_project_data($
   drupal_alter('update_status', $projects);
 
   // Set the projects array into the cache table.
-  cache_set('update_project_data', $projects, 'cache_update', time() + 3600);
+  _update_cache_set('update_project_data', $projects, time() + 3600);
   return $projects;
 }
 
 /**
- * Retrieve data from {cache_update} or empty the cache when necessary.
+ * Retrieve data from {update_cache} or empty the cache when necessary.
  *
  * Two very expensive arrays computed by this module are the list of all
  * installed modules and themes (and .info data, project associations, etc),
  * and the current status of the site relative to the currently available
- * releases. These two arrays are cached in the {cache_update} table and used
+ * releases. These two arrays are cached in the {update_cache} table and used
  * whenever possible. The cache is cleared whenever the administrator visits
  * the status report, available updates report, or the module or theme
  * administration pages, since we should always recompute the most current
@@ -584,10 +584,10 @@ function update_project_cache($cid) {
   $q = $_GET['q'];
   $paths = array('admin/build/modules', 'admin/build/themes', 'admin/reports', 'admin/reports/updates', 'admin/reports/status', 'admin/reports/updates/check');
   if (in_array($q, $paths)) {
-    cache_clear_all($cid, 'cache_update');
+    _update_cache_clear($cid);
   }
   else {
-    $cache = cache_get($cid, 'cache_update');
+    $cache = _update_cache_get($cid);
     if (!empty($cache->data) && $cache->expire > time()) {
       $projects = $cache->data;
     }
Index: modules/update/update.fetch.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/update/update.fetch.inc,v
retrieving revision 1.7.2.2
diff -u -p -r1.7.2.2 update.fetch.inc
--- modules/update/update.fetch.inc	14 Jan 2009 21:36:16 -0000	1.7.2.2
+++ modules/update/update.fetch.inc	26 Apr 2009 08:51:54 -0000
@@ -52,7 +52,7 @@ function _update_refresh() {
   }
   if (!empty($available) && is_array($available)) {
     $frequency = variable_get('update_check_frequency', 1);
-    cache_set('update_info', $available, 'cache_update', time() + (60 * 60 * 24 * $frequency));
+    _update_cache_set('update_info', $available, time() + (60 * 60 * 24 * $frequency));
     variable_set('update_last_check', time());
     watchdog('update', 'Fetched information about all available new releases and updates.', array(), WATCHDOG_NOTICE, l(t('view'), 'admin/reports/updates'));
   }
Index: modules/update/update.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/update/update.install,v
retrieving revision 1.4.2.2
diff -u -p -r1.4.2.2 update.install
--- modules/update/update.install	6 Jan 2009 15:46:38 -0000	1.4.2.2
+++ modules/update/update.install	26 Apr 2009 08:51:54 -0000
@@ -35,8 +35,45 @@ function update_uninstall() {
  * Implementation of hook_schema().
  */
 function update_schema() {
-  $schema['cache_update'] = drupal_get_schema_unprocessed('system', 'cache');
-  $schema['cache_update']['description'] = 'Cache table for the Update module to store information about available releases, fetched from central server.';
+  $schema['update_cache'] = array(
+    'description' => 'Cache table for the Update module to store information about available releases fetched from central server, and other expensive arrays of computed data.',
+    'fields' => array(
+      'cid' => array(
+        'description' => 'Primary Key: Unique cache ID.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'data' => array(
+        'description' => 'A collection of data to cache.',
+        'type' => 'blob',
+        'not null' => FALSE,
+        'size' => 'big',
+      ),
+      'expire' => array(
+        'description' => 'A Unix timestamp indicating when the cache entry should expire, or 0 for never.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'created' => array(
+        'description' => 'A Unix timestamp indicating when the cache entry was created.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+       ),
+      'serialized' => array(
+        'description' => 'A flag to indicate whether content is serialized (1) or not (0).',
+        'type' => 'int',
+        'size' => 'small',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'indexes' => array('expire' => array('expire')),
+    'primary key' => array('cid'),
+ );
   return $schema;
 }
 
@@ -62,3 +99,50 @@ function update_update_6000() {
   _update_remove_update_status_variables();
   return array();
 }
+
+/**
+ * Rename the {cache_update} table to {update_cache}.
+ *
+ * We do not have to (nor even want to) migrate any data, we should just
+ * rebuild the cache (check for available updates again) once this is done.
+ */
+function update_update_6001() {
+  $ret = array();
+  $schema['update_cache'] = 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,
+       ),
+      'serialized' => array(
+        'type' => 'int',
+        'size' => 'small',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'indexes' => array('expire' => array('expire')),
+    'primary key' => array('cid'),
+  );
+  db_create_table($ret, 'update_cache', $schema['update_cache']);
+  $ret[] = update_sql("DROP TABLE {cache_update}");
+  return $ret;
+}
+
Index: modules/update/update.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/update/update.module,v
retrieving revision 1.17.2.1
diff -u -p -r1.17.2.1 update.module
--- modules/update/update.module	23 Sep 2008 10:19:02 -0000	1.17.2.1
+++ modules/update/update.module	26 Apr 2009 08:51:55 -0000
@@ -286,9 +286,9 @@ function _update_requirement_check($proj
 function update_cron() {
   $frequency = variable_get('update_check_frequency', 1);
   $interval = 60 * 60 * 24 * $frequency;
-  // Cron should check for updates if there is no update data cached or if the configured
-  // update interval has elapsed.
-  if (!cache_get('update_info', 'cache_update') || ((time() - variable_get('update_last_check', 0)) > $interval)) {
+  // Cron should check for updates if there is no update data cached or if the
+  // configured update interval has elapsed.
+  if (!_update_cache_get('update_info') || ((time() - variable_get('update_last_check', 0)) > $interval)) {
     update_refresh();
     _update_cron_notify();
   }
@@ -353,7 +353,7 @@ function update_get_available($refresh =
       break;
     }
   }
-  if (!$needs_refresh && ($cache = cache_get('update_info', 'cache_update'))
+  if (!$needs_refresh && ($cache = _update_cache_get('update_info'))
        && $cache->expire > time()) {
     $available = $cache->data;
   }
@@ -374,14 +374,14 @@ function update_get_available($refresh =
  * something, in which case, we want to check for available update data again.
  */
 function update_flush_caches() {
-  return array('cache_update');
+  return array('update_cache');
 }
 
 /**
  * Invalidates any cached data relating to update status.
  */
 function update_invalidate_cache() {
-  cache_clear_all('*', 'cache_update', TRUE);
+  db_query("DELETE FROM {update_cache}");
 }
 
 /**
@@ -514,3 +514,84 @@ function _update_project_status_sort($a,
   $b_status = $b['status'] > 0 ? $b['status'] : (-10 * $b['status']);
   return $a_status - $b_status;
 }
+
+/**
+ * Set data in the private update module cache table.
+ *
+ * We specifically do NOT use the core cache API for saving the fetched data
+ * about available updates. It is vitally important that this cache is only
+ * cleared when we're populating it after successfully fetching new available
+ * update data. When we relied on the core cache API, there were all sorts of
+ * potential problems that would result in attempting to fetch available
+ * update data all the time, including if a site sets a so-called "minimum
+ * cache lifetime" (which is both a minimum and a maximum), or if a site uses
+ * memcache and does not properly configure a completely separate memcache
+ * bucket for this table.
+ *
+ * @param $cid
+ *   The cache ID to save the data with.
+ * @param $data
+ *   Array of parsed data representing available updates for the project.
+ * @param $expire
+ *   One of the following values:
+ *   - CACHE_PERMANENT: Indicates that the item should never be removed unless
+ *     explicitly told to using _update_cache_clear() with a cache ID.
+ *   - A Unix timestamp: Indicates that the item should be kept at least until
+ *     the given time, after which it will be invalidated.
+ *
+ * @see _update_cache_get()
+ * @see _update_cache_clear()
+ */
+function _update_cache_set($cid, $data, $expire) {
+  $serialized = 0;
+  if (is_object($data) || is_array($data)) {
+    $data = serialize($data);
+    $serialized = 1;
+  }
+  $created = time();
+  db_query("UPDATE {update_cache} SET data = %b, created = %d, expire = %d, serialized = %d WHERE cid = '%s'", $data, $created, $expire, $serialized, $cid);
+  if (!db_affected_rows()) {
+    @db_query("INSERT INTO {update_cache} (cid, data, created, expire, serialized) VALUES ('%s', %b, %d, %d, %d)", $cid, $data, $created, $expire, $serialized);
+  }
+}
+
+/** 
+ * Retrieve data from the private update module cache table.
+ *
+ * We specifically do NOT use the core cache API for this. Among other things,
+ * it is up to the caller to worry about expired data and clearing the cache.
+ * Cached data is never automatically cleared.
+ *
+ * @see _update_cache_set()
+ * @see _update_cache_clear()
+ *
+ * @param $cid
+ *   The cache ID to retrieve.
+ * @return
+ *   The data for the given cache ID, or NULL if the ID was not found.
+ */
+function _update_cache_get($cid) {
+  $cache = db_fetch_object(db_query("SELECT data, created, expire, serialized FROM {update_cache} WHERE cid = '%s'", $cid));
+  if (isset($cache->data)) {
+    $cache->data = db_decode_blob($cache->data);
+    if ($cache->serialized) {
+      $cache->data = unserialize($cache->data);
+    }
+  }
+  return $cache;
+}
+
+/**
+ * Explicitly clear the private update module cache for a given cache ID.
+ *
+ * We specifically do NOT use the core cache API for this.
+ * @see _update_cache_set()
+ * @see _update_cache_get()
+ *
+ * @param $cid
+ *   The cache ID of the record to clear from the private update module cache.
+ */
+function _update_cache_clear($cid) {
+  db_query("DELETE FROM {update_cache} WHERE cid = '%s'", $cid);
+}
+
