Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1068
diff -u -p -r1.1068 common.inc
--- includes/common.inc	22 Dec 2009 14:47:14 -0000	1.1068
+++ includes/common.inc	23 Dec 2009 17:59:32 -0000
@@ -6297,10 +6297,11 @@ function entity_get_info($entity_type = 
           'fieldable' => FALSE,
           'controller class' => 'DrupalDefaultEntityController',
           'static cache' => TRUE,
+          'entity cache' => FALSE,
           'load hook' => $name . '_load',
           'bundles' => array(),
           'object keys' => array(),
-          'cacheable' => TRUE,
+          'field cache' => TRUE,
           'translation' => array(),
         );
         $entity_info[$name]['object keys'] += array(
@@ -6354,8 +6355,8 @@ function entity_extract_ids($entity_type
   // If no bundle key provided, then we assume a single bundle, named after the
   // entity type.
   $bundle = $info['object keys']['bundle'] ? $entity->{$info['object keys']['bundle']} : $entity_type;
-  $cacheable = $info['cacheable'];
-  return array($id, $vid, $bundle, $cacheable);
+  $field_cache = $info['field cache'];
+  return array($id, $vid, $bundle, $field_cache);
 }
 
 /**
@@ -6420,7 +6421,7 @@ function entity_create_stub_entity($enti
  */
 function entity_load($entity_type, $ids = array(), $conditions = array(), $reset = FALSE) {
   if ($reset) {
-    entity_get_controller($entity_type)->resetCache();
+    entity_get_controller($entity_type)->resetCache($ids);
   }
   return entity_get_controller($entity_type)->load($ids, $conditions);
 }
Index: includes/entity.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/entity.inc,v
retrieving revision 1.4
diff -u -p -r1.4 entity.inc
--- includes/entity.inc	8 Dec 2009 06:33:11 -0000	1.4
+++ includes/entity.inc	23 Dec 2009 17:59:32 -0000
@@ -24,7 +24,17 @@ interface DrupalEntityControllerInterfac
   /**
    * Reset the internal, static entity cache.
    */
-  public function resetCache();
+  public function resetStaticCache();
+
+  /**
+   * Clear the persistent cache for an entity.
+   *
+   * @param $ids
+   *   A single entity ID or array of IDs, if present clear the entity cache for
+   *   these specific entities. If no argument is given, the entire bin
+   *   specified in hook_entity_info() will be flushed.
+   */
+  public function resetCache($id = NULL);
 
   /**
    * Load one or more entities.
@@ -48,7 +58,8 @@ interface DrupalEntityControllerInterfac
  */
 class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
 
-  protected $entityCache;
+  protected $entityStaticCache;
+  protected $entityPersistentCache;
   protected $entityType;
   protected $entityInfo;
   protected $hookLoadArguments;
@@ -63,7 +74,7 @@ class DrupalDefaultEntityController impl
   public function __construct($entityType) {
     $this->entityType = $entityType;
     $this->entityInfo = entity_get_info($entityType);
-    $this->entityCache = array();
+    $this->entityStaticCache = array();
     $this->hookLoadArguments = array();
     $this->idKey = $this->entityInfo['object keys']['id'];
 
@@ -77,11 +88,38 @@ class DrupalDefaultEntityController impl
     }
 
     // Check if the entity type supports static caching of loaded entities.
-    $this->cache = !empty($this->entityInfo['static cache']);
+    $this->staticCache = !empty($this->entityInfo['static cache']);
+    // Check if the entity type supports persistent caching if loaded entities.
+    $this->persistentCache = !empty($this->entityInfo['entity cache']);
   }
 
-  public function resetCache() {
-    $this->entityCache = array();
+  public function resetStaticCache() {
+    $this->staticCache = array();
+  }
+
+  public function resetCache($ids = NULL) {
+    // Only attempt to clear the persistent cache if this entity type uses it.
+    if ($this->persistentCache) {
+      // For consistency with cache_clear_all(), we allow either a single ID
+      // or an array of IDS.
+      if (isset($ids)) {
+        $ids = is_numeric($ids) ? array($ids) : $ids;
+        foreach ($ids as $id) {
+          $cids[] = $this->entityType . ':' . $id;
+          $wildcard = FALSE;
+        }
+      }
+      // If no IDs are given, do a full cache bin flush.
+      else {
+        $cids = '*';
+        $wildcard = TRUE;
+      }
+      $bin = $this->entityInfo['entity cache bin'];
+
+      cache_clear_all($cids, $bin, $wildcard);
+    }
+    // Clear the static cache whenever this is called.
+    $this->resetStaticCache();
   }
 
   public function load($ids = array(), $conditions = array()) {
@@ -108,17 +146,35 @@ class DrupalDefaultEntityController impl
     $passed_ids = !empty($this->ids) ? array_flip($this->ids) : FALSE;
     // Try to load entities from the static cache, if the entity type supports
     // static caching.
-    if ($this->cache) {
-      $entities += $this->cacheGet($this->ids, $this->conditions);
+    if ($this->staticCache) {
+      $entities += $this->staticCacheGet($this->ids, $this->conditions);
       // If any entities were loaded, remove them from the ids still to load.
       if ($passed_ids) {
         $this->ids = array_keys(array_diff_key($passed_ids, $entities));
       }
     }
 
+    // Attempt to load any remaining entities from the persistent cache.
+    $cached_entities = array();
+
+    $cid_prefix = $this->entityType . ':';
+    if ($this->persistentCache && $this->ids && !$this->conditions && !$this->revisionId) {
+      foreach ($this->ids as $id) {
+        $cids[] = $cid_prefix . $id;
+      }
+      if ($cached = cache_get_multiple($cids, $this->entityInfo['entity cache bin'])) {
+        foreach ($cached as $item) {
+          $id = str_replace($cid_prefix, '', $item->cid);
+          $cached_entities[$id] = $item->data;
+        }
+        $this->ids = array_diff($this->ids, array_keys($cached_entities));
+      }
+    }
+
     // Load any remaining entities from the database. This is the case if $ids
     // is set to FALSE (so we load all entities), if there are any ids left to
     // load, if loading a revision, or if $conditions was passed without $ids.
+    $queried_entities = array();
     if ($this->ids === FALSE || $this->ids || $this->revisionId || ($this->conditions && !$passed_ids)) {
       // Build the query.
       $this->buildQuery();
@@ -132,15 +188,32 @@ class DrupalDefaultEntityController impl
     // entity type specific load callback, for example hook_node_load().
     if (!empty($queried_entities)) {
       $this->attachLoad($queried_entities);
-      $entities += $queried_entities;
+      // If these entities can be persistently cached, do so now.
+      if ($this->persistentCache && !$this->revisionId) {
+        foreach ($queried_entities as $item) {
+          cache_set($cid_prefix . $item->{$this->idKey}, $item, $this->entityInfo['entity cache bin']);
+        }
+      }
     }
 
-    if ($this->cache) {
-      // Add entities to the cache if we are not loading a revision.
-      if (!empty($queried_entities) && !$this->revisionId) {
-        $this->cacheSet($queried_entities);
+    // Now that attachLoad() has been run, merge in entities loaded from cache
+    // and those from the database into a single variable.
+    $new_entities = $queried_entities + $cached_entities;
+
+    // Allow modules to act on entities without the result being persistently
+    // cached.
+    if (!empty($new_entities)) {
+      $this->attachAfterLoad($new_entities);
+      if ($this->staticCache) {
+        // Add entities to the cache if we are not loading a revision.
+        if (!empty($new_entities) && !$this->revisionId) {
+          $this->staticCacheSet($new_entities);
+        }
       }
     }
+    // Merge all entities to be returned from this call into the same array
+    // now that all hooks have run.
+    $entities += $new_entities;
 
     // Ensure that the returned array is ordered the same as the original
     // $ids array if this was passed in and remove any invalid ids.
@@ -257,6 +330,27 @@ class DrupalDefaultEntityController impl
   }
 
   /**
+   * Attach data to entities after loading.
+   *
+   * Invokes hook_TYPE_load_uncached() to allow modules to interact with
+   * entity objects without the result being persistently cached.
+   *
+   * If your hook_TYPE_load() expects special parameters apart from the
+   * queried entities, you can set $this->hookLoadArguments prior to
+   * calling the method. See NodeController::attachLoad() for an example.
+   */
+  protected function attachAfterLoad(&$entities) {
+    // Call hook_TYPE_load(). The first argument for hook_TYPE_load() are
+    // always the queried entities, followed by additional arguments set in
+    // $this->hookLoadArguments.
+    $args = array_merge(array($entities), $this->hookLoadArguments);
+    foreach (module_implements($this->entityInfo['load hook'] . '_uncached') as $module) {
+      call_user_func_array($module . '_' . $this->entityInfo['load hook'] . '_uncached', $args);
+    }
+  }
+
+
+  /**
    * Get entities from the static cache.
    *
    * @param $ids
@@ -264,17 +358,17 @@ class DrupalDefaultEntityController impl
    * @param $conditions
    *   If set, return entities that match all of these conditions.
    */
-  protected function cacheGet($ids, $conditions = array()) {
+  protected function staticCacheGet($ids, $conditions = array()) {
     $entities = array();
     // Load any available entities from the internal cache.
-    if (!empty($this->entityCache) && !$this->revisionId) {
+    if (!empty($this->entityStaticCache) && !$this->revisionId) {
       if ($ids) {
-        $entities += array_intersect_key($this->entityCache, array_flip($ids));
+        $entities += array_intersect_key($this->entityStaticCache, array_flip($ids));
       }
       // If loading entities only by conditions, fetch all available entities
       // from the cache. Entities which don't match are removed later.
       elseif ($conditions) {
-        $entities = $this->entityCache;
+        $entities = $this->entityStaticCache;
       }
     }
 
@@ -294,7 +388,7 @@ class DrupalDefaultEntityController impl
   /**
    * Store entities in the static entity cache.
    */
-  protected function cacheSet($entities) {
-    $this->entityCache += $entities;
+  protected function staticCacheSet($entities) {
+    $this->entityStaticCache += $entities;
   }
 }
Index: includes/file.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/file.inc,v
retrieving revision 1.199
diff -u -p -r1.199 file.inc
--- includes/file.inc	5 Nov 2009 03:37:08 -0000	1.199
+++ includes/file.inc	23 Dec 2009 17:59:33 -0000
@@ -490,6 +490,7 @@ function file_save(stdClass $file) {
     drupal_write_record('file', $file, 'fid');
     // Inform modules that the file has been updated.
     module_invoke_all('file_update', $file);
+    entity_get_controller('file')->resetCache($file->fid);
   }
 
   return $file;
@@ -937,6 +938,7 @@ function file_delete(stdClass $file, $fo
 
   // Let other modules clean up any references to the deleted file.
   module_invoke_all('file_delete', $file);
+  entity_get_controller('file')->resetCache($file->fid);
 
   // Make sure the file is deleted before removing its row from the
   // database, so UIs can still find the file in the database.
Index: modules/book/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.module,v
retrieving revision 1.531
diff -u -p -r1.531 book.module
--- modules/book/book.module	21 Dec 2009 13:47:31 -0000	1.531
+++ modules/book/book.module	23 Dec 2009 17:59:33 -0000
@@ -744,9 +744,9 @@ function book_menu_name($bid) {
 }
 
 /**
- * Implements hook_node_load().
+ * Implements hook_node_load_uncached().
  */
-function book_node_load($nodes, $types) {
+function book_node_load_uncached($nodes, $types) {
   $result = db_query("SELECT * FROM {book} b INNER JOIN {menu_links} ml ON b.mlid = ml.mlid WHERE b.nid IN (:nids)", array(':nids' =>  array_keys($nodes)), array('fetch' => PDO::FETCH_ASSOC));
   foreach ($result as $record) {
     $nodes[$record['nid']]->book = $record;
Index: modules/comment/comment.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.install,v
retrieving revision 1.55
diff -u -p -r1.55 comment.install
--- modules/comment/comment.install	8 Dec 2009 06:52:38 -0000	1.55
+++ modules/comment/comment.install	23 Dec 2009 17:59:33 -0000
@@ -215,6 +215,15 @@ function comment_update_7011() {
 }
 
 /**
+ * Add the {cache_comment} table.
+ */
+function comment_update_7012() {
+  $schema['cache_comment'] = drupal_get_schema_unprocessed('system', 'cache');
+  $schema['cache_comment']['description'] = 'Cache table used for taxonomy terms and vocabularies.';
+  db_create_table('cache_comment', $schema['cache_comment']);
+}
+
+/**
  * @} End of "defgroup updates-6.x-to-7.x"
  * The next series of updates should start at 8000.
  */
@@ -395,5 +404,8 @@ function comment_schema() {
     ),
   );
 
+  $schema['cache_comment'] = drupal_get_schema_unprocessed('system', 'cache');
+  $schema['cache_comment']['description'] = 'Cache table used for comments.';
+
   return $schema;
 }
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.820
diff -u -p -r1.820 comment.module
--- modules/comment/comment.module	22 Dec 2009 20:38:23 -0000	1.820
+++ modules/comment/comment.module	23 Dec 2009 17:59:34 -0000
@@ -108,6 +108,9 @@ function comment_entity_info() {
       ),
       'bundles' => array(),
       'static cache' => FALSE,
+      'field cache' => FALSE,
+      'entity cache' => TRUE,
+      'entity cache bin' => 'cache_comment',
     ),
   );
 
@@ -1311,6 +1314,7 @@ function comment_save($comment) {
       module_invoke_all('comment_update', $comment);
       // Add an entry to the watchdog log.
       watchdog('content', 'Comment: updated %subject.', array('%subject' => $comment->subject), WATCHDOG_NOTICE, l(t('view'), 'comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid)));
+      entity_get_controller('comment')->resetCache($comment->cid);
     }
     else {
       // Add the comment to database. This next section builds the thread field.
@@ -1443,6 +1447,7 @@ function comment_delete_multiple($cids) 
       $child_cids = db_query('SELECT cid FROM {comment} WHERE pid = :cid', array(':cid' => $comment->cid))->fetchCol();
       comment_delete_multiple($child_cids);
       _comment_update_node_statistics($comment->nid);
+      entity_get_controller('comment')->resetCache($comment->cid);
     }
   }
 }
@@ -2255,6 +2260,8 @@ function _comment_update_node_statistics
       ->condition('nid', $nid)
       ->execute();
   }
+  // Clear the cache for this node.
+  entity_get_controller('node')->resetCache($nid);
 }
 
 /**
Index: modules/field/field.attach.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.attach.inc,v
retrieving revision 1.66
diff -u -p -r1.66 field.attach.inc
--- modules/field/field.attach.inc	21 Dec 2009 13:47:32 -0000	1.66
+++ modules/field/field.attach.inc	23 Dec 2009 17:59:34 -0000
@@ -540,7 +540,7 @@ function field_attach_load($obj_type, $o
   $info = entity_get_info($obj_type);
   // Only the most current revision of non-deleted fields for
   // cacheable fieldable types can be cached.
-  $cache_read = $load_current && $info['cacheable'] && empty($options['deleted']);
+  $cache_read = $load_current && $info['field cache'] && empty($options['deleted']);
   // In addition, do not write to the cache when loading a single field.
   $cache_write = $cache_read && !isset($options['field_id']);
 
@@ -821,7 +821,7 @@ function field_attach_insert($obj_type, 
   _field_invoke_default('insert', $obj_type, $object);
   _field_invoke('insert', $obj_type, $object);
 
-  list($id, $vid, $bundle, $cacheable) = entity_extract_ids($obj_type, $object);
+  list($id, $vid, $bundle, $field_cache) = entity_extract_ids($obj_type, $object);
 
   // Let any module insert field data before the storage engine, accumulating
   // saved fields along the way.
@@ -854,7 +854,7 @@ function field_attach_insert($obj_type, 
   // Let other modules act on inserting the object.
   module_invoke_all('field_attach_insert', $obj_type, $object);
 
-  if ($cacheable) {
+  if ($field_cache) {
     cache_clear_all("field:$obj_type:$id", 'cache_field');
   }
 }
@@ -870,7 +870,7 @@ function field_attach_insert($obj_type, 
 function field_attach_update($obj_type, $object) {
   _field_invoke('update', $obj_type, $object);
 
-  list($id, $vid, $bundle, $cacheable) = entity_extract_ids($obj_type, $object);
+  list($id, $vid, $bundle, $field_cache) = entity_extract_ids($obj_type, $object);
 
   // Let any module update field data before the storage engine, accumulating
   // saved fields along the way.
@@ -907,7 +907,7 @@ function field_attach_update($obj_type, 
   // Let other modules act on updating the object.
   module_invoke_all('field_attach_update', $obj_type, $object);
 
-  if ($cacheable) {
+  if ($field_cache) {
     cache_clear_all("field:$obj_type:$id", 'cache_field');
   }
 }
Index: modules/field/tests/field_test.entity.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field_test.entity.inc,v
retrieving revision 1.1
diff -u -p -r1.1 field_test.entity.inc
--- modules/field/tests/field_test.entity.inc	20 Nov 2009 23:29:28 -0000	1.1
+++ modules/field/tests/field_test.entity.inc	23 Dec 2009 17:59:34 -0000
@@ -19,7 +19,7 @@ function field_test_entity_info() {
         'revision' => 'ftvid',
         'bundle' => 'fttype',
       ),
-      'cacheable' => FALSE,
+      'field cache' => FALSE,
       'bundles' => $bundles,
       'fieldable' => TRUE,
     ),
@@ -32,7 +32,7 @@ function field_test_entity_info() {
         'bundle' => 'fttype',
       ),
       'fieldable' => TRUE,
-      'cacheable' => TRUE,
+      'field cache' => TRUE,
       'bundles' => $bundles,
     ),
   );
Index: modules/locale/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v
retrieving revision 1.275
diff -u -p -r1.275 locale.module
--- modules/locale/locale.module	7 Dec 2009 05:02:37 -0000	1.275
+++ modules/locale/locale.module	23 Dec 2009 17:59:35 -0000
@@ -380,7 +380,7 @@ function locale_form_path_admin_form_alt
  * Implements hook_form_FORM_ID_alter().
  */
 function locale_form_node_type_form_alter(&$form, &$form_state) {
-  if (isset($form['identity']['type'])) {
+  if (isset($form['type'])) {
     $form['workflow']['language_content_type'] = array(
       '#type' => 'radios',
       '#title' => t('Multilingual support'),
Index: modules/node/node.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.install,v
retrieving revision 1.37
diff -u -p -r1.37 node.install
--- modules/node/node.install	4 Dec 2009 16:49:46 -0000	1.37
+++ modules/node/node.install	23 Dec 2009 17:59:35 -0000
@@ -353,6 +353,9 @@ function node_schema() {
     'primary key' => array('type'),
   );
 
+  $schema['cache_node'] = drupal_get_schema_unprocessed('system', 'cache');
+  $schema['cache_node']['description'] = 'Cache table used for nodes.';
+
   return $schema;
 }
 
@@ -576,6 +579,16 @@ function node_update_7009() {
 }
 
 /**
+ * Add the {cache_node} table.
+ */
+function node_update_7010() {
+  // Add the cache_path table.
+  $schema['cache_node'] = drupal_get_schema_unprocessed('system', 'cache');
+  $schema['cache_node']['description'] = 'Cache table used for nodes.';
+  db_create_table('cache_node', $schema['cache_node']);
+}
+
+/**
  * @} End of "defgroup updates-6.x-to-7.x"
  * The next series of updates should start at 8000.
  */
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1188
diff -u -p -r1.1188 node.module
--- modules/node/node.module	22 Dec 2009 20:38:23 -0000	1.1188
+++ modules/node/node.module	23 Dec 2009 17:59:37 -0000
@@ -192,6 +192,9 @@ function node_entity_info() {
       'controller class' => 'NodeController',
       'base table' => 'node',
       'revision table' => 'node_revision',
+      'entity cache bin' => 'cache_node',
+      'entity cache' => TRUE,
+      'field cache' => FALSE,
       'fieldable' => TRUE,
       'object keys' => array(
         'id' => 'nid',
@@ -1053,6 +1056,11 @@ function node_save($node) {
     // Update the node access table for this node.
     node_access_acquire_grants($node);
 
+    // Clear the entity cache.
+    if (!$node->is_new) {
+      entity_get_controller('node')->resetCache($node->nid);
+    }
+
     // Clear internal properties.
     unset($node->is_new);
 
@@ -1132,8 +1140,7 @@ function node_delete_multiple($nids) {
     }
 
     // Clear the page and block and node_load_multiple caches.
-    cache_clear_all();
-    entity_get_controller('node')->resetCache();
+    entity_get_controller('node')->resetCache($nids);
   }
 }
 
@@ -3290,4 +3297,15 @@ class NodeController extends DrupalDefau
     $this->hookLoadArguments[] = array_keys($typed_nodes);
     parent::attachLoad($nodes);
   }
+
+  protected function attachAfterLoad(&$nodes) {
+    // Create an array of content types and pass this to the
+    // object type specific callback.
+    $types = array();
+    foreach ($nodes as $object) {
+      $types[$object->type] = $object->type;
+    }
+    $this->hookLoadArguments[] = $types;
+    parent::attachAfterLoad($nodes);
+  }
 }
Index: modules/poll/poll.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v
retrieving revision 1.329
diff -u -p -r1.329 poll.module
--- modules/poll/poll.module	14 Dec 2009 20:38:15 -0000	1.329
+++ modules/poll/poll.module	23 Dec 2009 17:59:37 -0000
@@ -433,7 +433,6 @@ function poll_node_prepare_translation($
  * Implements hook_load().
  */
 function poll_load($nodes) {
-  global $user;
   foreach ($nodes as $node) {
     $poll = db_query("SELECT runtime, active FROM {poll} WHERE nid = :nid", array(':nid' => $node->nid))->fetchObject();
 
@@ -445,23 +444,6 @@ function poll_load($nodes) {
       ->orderBy('weight')
       ->execute()->fetchAllAssoc('chid', PDO::FETCH_ASSOC);
 
-    // Determine whether or not this user is allowed to vote.
-    $poll->allowvotes = FALSE;
-    if (user_access('vote on polls') && $poll->active) {
-      if ($user->uid) {
-        $result = db_query('SELECT chid FROM {poll_vote} WHERE nid = :nid AND uid = :uid', array(':nid' => $node->nid, ':uid' => $user->uid))->fetchObject();
-      }
-      else {
-        $result = db_query("SELECT chid FROM {poll_vote} WHERE nid = :nid AND hostname = :hostname", array(':nid' => $node->nid, ':hostname' => ip_address()))->fetchObject();
-      }
-      if ($result) {
-        $poll->vote = $result->chid;
-      }
-      else {
-        $poll->vote = -1;
-        $poll->allowvotes = TRUE;
-      }
-    }
     foreach ($poll as $key => $value) {
       $nodes[$node->nid]->$key = $value;
     }
@@ -469,6 +451,39 @@ function poll_load($nodes) {
 }
 
 /**
+ * Implements hook_node_load_uncached().
+ *
+ * Loads user-specific information into the node object for the duration
+ * of the page request only.
+ */
+function poll_node_load_uncached($nodes, $types) {
+  global $user;
+
+  foreach ($nodes as $node) {
+    if ($node->type == 'poll') {
+      // Determine whether or not this user is allowed to vote.
+      $node->allowvotes = FALSE;
+      if (user_access('vote on polls') && $node->active) {
+        if ($user->uid) {
+          $result = db_query('SELECT chid FROM {poll_vote} WHERE nid = :nid AND uid = :uid', array(':nid' => $node->nid, ':uid' => $user->uid))->fetchObject();
+        }
+        else {
+          $result = db_query("SELECT chid FROM {poll_vote} WHERE nid = :nid AND hostname = :hostname", array(':nid' => $node->nid, ':hostname' => ip_address()))->fetchObject();
+        }
+        if ($result) {
+          $node->vote = $result->chid;
+        }
+        else {
+          $node->vote = -1;
+          $node->allowvotes = TRUE;
+        }
+      }
+    }
+  }
+}
+
+
+/**
  * Implements hook_insert().
  */
 function poll_insert($node) {
@@ -699,6 +714,7 @@ function poll_vote($form, &$form_state) 
     ->condition('chid', $choice)
     ->execute();
 
+  entity_get_controller('node')->resetCache($node->nid);
   cache_clear_all();
   drupal_set_message(t('Your vote was recorded.'));
 
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.430
diff -u -p -r1.430 system.install
--- modules/system/system.install	14 Dec 2009 10:36:26 -0000	1.430
+++ modules/system/system.install	23 Dec 2009 17:59:37 -0000
@@ -604,6 +604,8 @@ function system_schema() {
   $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_path'] = $schema['cache'];
   $schema['cache_path']['description'] = 'Cache table for path alias lookup.';
+  $schema['cache_file'] = $schema['cache'];
+  $schema['cache_file']['description'] = 'Cache table for file objects.';
 
   $schema['date_format_type'] = array(
     'description' => 'Stores configured date format types.',
@@ -2716,6 +2718,16 @@ function system_update_7048() {
 }
 
 /**
+ * Add the {cache_file} table.
+ */
+function system_update_7049() {
+  // Add the cache_path table.
+  $schema['cache_file'] = drupal_get_schema_unprocessed('system', 'cache');
+  $schema['cache_file']['description'] = 'Cache table used for files.';
+  db_create_table('cache_file', $schema['cache_file']);
+}
+
+/**
  * @} End of "defgroup updates-6.x-to-7.x"
  * The next series of updates should start at 8000.
  */
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.862
diff -u -p -r1.862 system.module
--- modules/system/system.module	15 Dec 2009 08:45:32 -0000	1.862
+++ modules/system/system.module	23 Dec 2009 17:59:38 -0000
@@ -282,6 +282,9 @@ function system_entity_info() {
         'id' => 'fid',
       ),
       'static cache' => FALSE,
+      'field cache' => FALSE,
+      'entity cache' => TRUE,
+      'entity cache bin' => 'cache_file',
     ),
   );
 }
Index: modules/taxonomy/taxonomy.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.install,v
retrieving revision 1.30
diff -u -p -r1.30 taxonomy.install
--- modules/taxonomy/taxonomy.install	9 Dec 2009 15:52:25 -0000	1.30
+++ modules/taxonomy/taxonomy.install	23 Dec 2009 17:59:38 -0000
@@ -211,6 +211,9 @@ function taxonomy_schema() {
     ),
   );
 
+  $schema['cache_taxonomy'] = drupal_get_schema_unprocessed('system', 'cache');
+  $schema['cache_taxonomy']['description'] = 'Cache table used for taxonomy terms and vocabularies.';
+
   return $schema;
 }
 
@@ -429,3 +432,11 @@ function taxonomy_update_7006() {
   ));
 }
 
+/**
+ * Add the {cache_taxonomy} table.
+ */
+function taxonomy_update_7007() {
+  $schema['cache_taxonomy'] = drupal_get_schema_unprocessed('system', 'cache');
+  $schema['cache_taxonomy']['description'] = 'Cache table used for taxonomy terms and vocabularies.';
+  db_create_table('cache_taxonomy', $schema['cache_taxonomy']);
+}
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.552
diff -u -p -r1.552 taxonomy.module
--- modules/taxonomy/taxonomy.module	21 Dec 2009 13:47:32 -0000	1.552
+++ modules/taxonomy/taxonomy.module	23 Dec 2009 17:59:39 -0000
@@ -90,6 +90,9 @@ function taxonomy_entity_info() {
       'controller class' => 'TaxonomyTermController',
       'base table' => 'taxonomy_term_data',
       'fieldable' => TRUE,
+      'entity cache' => TRUE,
+      'entity cache bin' => 'cache_taxonomy',
+      'field cache' => FALSE,
       'object keys' => array(
         'id' => 'tid',
         'bundle' => 'vocabulary_machine_name',
@@ -115,6 +118,8 @@ function taxonomy_entity_info() {
     'label' => t('Taxonomy vocabulary'),
     'controller class' => 'TaxonomyVocabularyController',
     'base table' => 'taxonomy_vocabulary',
+    'entity cache' => TRUE,
+    'entity cache bin' => 'cache_taxonomy',
     'object keys' => array(
       'id' => 'vid',
     ),
@@ -341,6 +346,7 @@ function taxonomy_vocabulary_save($vocab
   if (!empty($vocabulary->vid) && !empty($vocabulary->name)) {
     $status = drupal_write_record('taxonomy_vocabulary', $vocabulary, 'vid');
     module_invoke_all('taxonomy_vocabulary_update', $vocabulary);
+    entity_get_controller('taxonomy_vocabulary')->resetCache($vocabulary->vid);
   }
   elseif (empty($vocabulary->vid)) {
     $status = drupal_write_record('taxonomy_vocabulary', $vocabulary);
@@ -350,7 +356,6 @@ function taxonomy_vocabulary_save($vocab
   }
 
   cache_clear_all();
-  entity_get_controller('taxonomy_vocabulary')->resetCache();
 
   return $status;
 }
@@ -473,10 +478,11 @@ function taxonomy_term_save($term) {
     $status = drupal_write_record('taxonomy_term_data', $term, 'tid');
     field_attach_update('taxonomy_term', $term);
     module_invoke_all('taxonomy_term_update', $term);
+    entity_get_controller('taxonomy_term')->resetCache($term->tid);
+    taxonomy_terms_static_reset();
   }
   else {
     $status = drupal_write_record('taxonomy_term_data', $term);
-    _taxonomy_clean_field_cache($term);
     field_attach_insert('taxonomy_term', $term);
     module_invoke_all('taxonomy_term_insert', $term);
   }
@@ -514,7 +520,6 @@ function taxonomy_term_save($term) {
   $query->execute();
 
   cache_clear_all();
-  taxonomy_terms_static_reset();
 
   return $status;
 }
@@ -553,15 +558,15 @@ function taxonomy_term_delete($tid) {
         ->execute();
 
       field_attach_delete('taxonomy_term', $term);
-      _taxonomy_clean_field_cache($term);
       module_invoke_all('taxonomy_term_delete', $term);
     }
 
     $tids = $orphans;
   }
 
-  cache_clear_all();
+  entity_get_controller('taxonomy_term')->resetCache($term->tid);
   taxonomy_terms_static_reset();
+  cache_clear_all();
 
   return SAVED_DELETED;
 }
@@ -572,7 +577,6 @@ function taxonomy_term_delete($tid) {
 function taxonomy_terms_static_reset() {
   drupal_static_reset('taxonomy_term_count_nodes');
   drupal_static_reset('taxonomy_get_tree');
-  entity_get_controller('taxonomy_term')->resetCache();
 }
 
 /**
@@ -1174,48 +1178,6 @@ function taxonomy_field_formatter_prepar
 }
 
 /**
- * Helper function that clears field cache when terms are updated or deleted
- */
-function _taxonomy_clean_field_cache($term) {
-  $cids = array();
-
-  // Determine object types that are not cacheable.
-  $obj_types = array();
-  foreach (entity_get_info() as $obj_type => $info) {
-    if (isset($info['cacheable']) && !$info['cacheable']) {
-      $obj_types[] = $obj_type;
-    }
-  }
-
-  // Load info for all taxonomy term fields.
-  $fields = field_read_fields(array('type' => 'taxonomy_term'));
-  foreach ($fields as $field_name => $field) {
-
-    // Assemble an array of vocabulary IDs that are used in this field.
-    foreach ($field['settings']['allowed_values'] as $tree) {
-      $vids[$tree['vid']] = $tree['vid'];
-    }
-
-    // Check this term's vocabulary against those used for the field's options.
-    if (in_array($term->vid, $vids)) {
-      $conditions = array(array('tid', $term->tid));
-      if ($obj_types) {
-        $conditions[] = array('type', $obj_types, 'NOT IN');
-      }
-      $results = field_attach_query($field['id'], $conditions, array('limit' => FIELD_QUERY_NO_LIMIT));
-      foreach ($results as $obj_type => $objects) {
-        foreach (array_keys($objects) as $id) {
-          $cids[] = "field:$obj_type:$id";
-        }
-      }
-    }
-  }
-  if ($cids) {
-    cache_clear_all($cids, 'cache_field');
-  }
-}
-
-/**
  * Title callback for term pages.
  *
  * @param $term
Index: modules/taxonomy/taxonomy.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.test,v
retrieving revision 1.64
diff -u -p -r1.64 taxonomy.test
--- modules/taxonomy/taxonomy.test	10 Dec 2009 15:39:43 -0000	1.64
+++ modules/taxonomy/taxonomy.test	23 Dec 2009 17:59:39 -0000
@@ -683,6 +683,7 @@ class TaxonomyHooksTestCase extends Taxo
       'antonym' => 'Short',
     );
     $this->drupalPost('taxonomy/term/' . $term->tid . '/edit', $edit, t('Save'));
+    entity_get_controller('taxonomy_term')->resetCache($term->tid);
     taxonomy_terms_static_reset();
     $term = taxonomy_term_load($term->tid);
     $this->assertEqual($edit['antonym'], $term->antonym, t('Antonym was successfully edited'));
Index: modules/translation/translation.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/translation/translation.module,v
retrieving revision 1.68
diff -u -p -r1.68 translation.module
--- modules/translation/translation.module	6 Dec 2009 17:56:05 -0000	1.68
+++ modules/translation/translation.module	23 Dec 2009 17:59:39 -0000
@@ -225,14 +225,14 @@ function translation_node_insert($node) 
     if (!empty($node->translation_source)) {
       if ($node->translation_source->tnid) {
         // Add node to existing translation set.
-        $tnid = $node->translation_source->tnid;
+        $node->tnid = $node->translation_source->tnid;
       }
       else {
         // Create new translation set, using nid from the source node.
-        $tnid = $node->translation_source->nid;
+        $node->tnid = $node->translation_source->nid;
         db_update('node')
           ->fields(array(
-            'tnid' => $tnid,
+            'tnid' => $node->tnid,
             'translate' => 0,
           ))
           ->condition('nid', $node->translation_source->nid)
@@ -240,11 +240,12 @@ function translation_node_insert($node) 
       }
       db_update('node')
         ->fields(array(
-          'tnid' => $tnid,
+          'tnid' => $node->tnid,
           'translate' => 0,
         ))
         ->condition('nid', $node->nid)
         ->execute();
+      translation_clear_node_cache($node);
     }
   }
 }
@@ -273,6 +274,7 @@ function translation_node_update($node) 
           ->execute();
       }
     }
+    translation_clear_node_cache($node);
   }
 }
 
@@ -334,6 +336,7 @@ function translation_remove_from_set($no
           ->execute();
       }
     }
+    translation_clear_node_cache($node);
   }
 }
 
@@ -420,3 +423,24 @@ function translation_language_switch_lin
     }
   }
 }
+
+/**
+ * Clear the node_load() cache for all nodes in the translation set.
+ *
+ * This ensures we have the proper translation set information in every node.
+ *
+ * @param $tnid
+ *   The translation source nid of the translation set, the identifier
+ *   of the node used to derive all translations in the set.
+ */
+function translation_clear_node_cache($node) {
+  drupal_static_reset('translation_node_get_translations');
+  $nids = array();
+  if ($translations = translation_node_get_translations($node->tnid)) {
+    foreach ($translations as $translation) {
+      $nids[] = $translation->nid;
+    }
+    entity_get_controller('node')->resetCache($nids);
+  }
+}
+
