diff --git a/includes/cache.inc b/includes/cache.inc index 09f4d75..600c9c8 100644 --- a/includes/cache.inc +++ b/includes/cache.inc @@ -5,32 +5,73 @@ * Functions and interfaces for cache handling. */ +class DrupalCache { + static protected $cacheObjects = array(); + + /** + * Gets the cache object for a cache bin. + * + * By default, this returns an instance of the DrupalDatabaseCache class. + * Classes implementing DrupalCacheInterface can register themselves both as a + * default implementation and for specific bins. + * + * @param string $bin + * The cache bin for which the cache object should be returned. + * + * @return DrupalCacheInterface + * The cache object associated with the specified bin. + * + * @see DrupalCacheInterface + */ + static public function getObject($bin) { + // We do not use drupal_static() here because we do not want to change the + // storage of a cache bin mid-request. + if (!isset(self::$cacheObjects[$bin])) { + $class = variable_get('cache_class_' . $bin); + if (!isset($class)) { + $class = variable_get('cache_default_class', 'DrupalDatabaseCache'); + } + self::$cacheObjects[$bin] = new $class($bin); + } + return self::$cacheObjects[$bin]; + } + + /** + * Called on transaction rollback. + * + * @param int $depth + * The transaction depth rolled back to. + */ + static public function rollback($depth = NULL) { + foreach (self::$cacheObjects as $cache_object) { + if ($cache_object instanceOf DrupalTransactionalCacheInterface) { + $cache_object->rollback($depth); + } + } + } + + /** + * Called on transaction commit. + * + * @param int $depth + * The transaction depth committed to. + */ + static public function commit($depth = NULL) { + foreach (self::$cacheObjects as $cache_object) { + if ($cache_object instanceOf DrupalTransactionalCacheInterface) { + $cache_object->commit($depth); + } + } + } +} + /** - * Gets the cache object for a cache bin. - * - * By default, this returns an instance of the DrupalDatabaseCache class. - * Classes implementing DrupalCacheInterface can register themselves both as a - * default implementation and for specific bins. + * Wrapper for DrupalCache::getObject(). * - * @param $bin - * The cache bin for which the cache object should be returned. - * @return DrupalCacheInterface - * The cache object associated with the specified bin. - * - * @see DrupalCacheInterface + * @see DrupalCache::getObject() */ function _cache_get_object($bin) { - // We do not use drupal_static() here because we do not want to change the - // storage of a cache bin mid-request. - static $cache_objects; - if (!isset($cache_objects[$bin])) { - $class = variable_get('cache_class_' . $bin); - if (!isset($class)) { - $class = variable_get('cache_default_class', 'DrupalDatabaseCache'); - } - $cache_objects[$bin] = new $class($bin); - } - return $cache_objects[$bin]; + return DrupalCache::getObject($bin); } /** @@ -299,6 +340,37 @@ interface DrupalCacheInterface { } /** + * Defines an interface for transaction aware cache implementations. + * + * All cache implementations that does not use the default database as a cache + * storage should implement this interface. + * + * The implementation is responsible for buffering write cache operations until + * either the buffer is cleared or flushed. The cache implementations is also + * responsible for handling nested transaction properly. + * + * @see _cache_get_object() + * @see DrupalDatabaseCache + */ +interface DrupalTransactionalCacheInterface { + /** + * Called on transaction rollback. + * + * @param int $depth + * The transaction depth rolled back to. + */ + function rollback($depth); + + /** + * Called on transaction commit. + * + * @param int $depth + * The transaction depth committed to. + */ + function commit($depth); +} + +/** * Defines a default cache implementation. * * This is Drupal's default cache implementation. It uses the database to store diff --git a/includes/database/database.inc b/includes/database/database.inc index f78098b..1e561de 100644 --- a/includes/database/database.inc +++ b/includes/database/database.inc @@ -1906,6 +1906,7 @@ class DatabaseTransaction { // If we rolled back then the transaction would have already been popped. if (!$this->rolledBack) { $this->connection->popTransaction($this->name); + DrupalCache::commit($this->connection->transactionDepth()); } } @@ -1931,6 +1932,7 @@ class DatabaseTransaction { public function rollback() { $this->rolledBack = TRUE; $this->connection->rollback($this->name); + DrupalCache::rollback($this->connection->transactionDepth()); } }