Implement a hiearchy (primary / secondary) router.

From:  <>


---

 engines/hierarchy.php |  105 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 105 insertions(+), 0 deletions(-)
 create mode 100644 engines/hierarchy.php


diff --git engines/hierarchy.php engines/hierarchy.php
new file mode 100644
index 0000000..351f491
--- /dev/null
+++ engines/hierarchy.php
@@ -0,0 +1,105 @@
+<?php
+// $Id$
+
+/**
+ * @file hierarchy.php
+ *   Hierarchical cache engine.
+ */
+
+class hierarchicalCache extends Cache {
+  var $settings = array();
+  
+  function page_fast_cache() {
+    return $this->fast_cache;
+  }
+  
+  function __construct($bin) {
+    global $conf;
+    if (!isset($conf['cacherouter'][$bin .'_primary'])) {
+      $conf['cacherouter'][$bin .'_primary'] = $conf['cacherouter'][$bin]['primary_engine'];
+    }
+
+    if (!isset($conf['cacherouter'][$bin . '_secondary'])) {
+      $conf['cacherouter'][$bin .'_secondary'] = $conf['cacherouter'][$bin]['secondary_engine'];
+    }
+
+    $this->primaryEngine = $GLOBALS['cache']->__init($bin .'_primary');
+    $this->secondaryEngine = $GLOBALS['cache']->__init($bin .'_secondary');
+
+    $this->tombstone_delay = isset($conf['cacherouter'][$bin]['tombstone_delay']) ? $conf['cacherouter'][$bin]['tombstone_delay'] : 10;
+
+    parent::__construct($bin);
+  }
+  
+  function get($key) {
+    // Attempt to pull from static cache.
+    $cache = parent::get($this->key($key));
+    if (isset($cache)) {
+      return $cache;
+    }
+    
+    // Try to get from secondary cache.
+    $cache = $this->secondaryEngine->get($key);
+    if (!isset($cache)) {
+      // Else, try to get from primary cache.
+      $cache = $this->primaryEngine->get($key);
+      $this->secondaryEngine->set($key, $cache);
+    }
+
+    // Update static cache 
+    parent::set($this->key($key), $cache);
+    
+    return $cache;
+  }
+  
+  function set($key, $value, $expire = CACHE_PERMANENT, $headers = NULL) {
+    $this->secondaryEngine->set($key, $value, $expire, $headers);
+    $this->primaryEngine->set($key, $value, $expire, $headers);
+  }
+  
+  function delete($key) {
+    // Delete from static cache
+    parent::delete($this->key($key));
+
+    // Update the tombstone.
+    $this->updateTombstone();
+
+    // Delete in the engines.
+    $this->primaryEngine->delete($key);
+    $this->secondaryEngine->delete($key);
+  }
+  
+  function flush() {
+    // Flush static cache
+    parent::flush();
+
+    // Delete in the engines.
+    $this->primaryEngine->flush();
+    $this->secondaryEngine->flush();
+
+    // Update the tombstone.
+    $this->updateTombstone();
+  }
+
+  function checkTombstone() {
+    if (!isset($this->tombstone)) {
+      if ($this->secondaryEngine->get('tombstone')) {
+        $this->tombstone = $cache->data;
+      }
+    }
+
+    if (!isset($this->tombstone) || time() - $this->tombstone > $this->tombstone_delay) {
+      if ($cache = $this->primaryEngine->get('tombstone')) {
+        $new_tombstone = $cache->data;
+      }
+
+      if (!isset($new_tombstone) || $new_tombstone != $this->tombstone) {
+        $this->secondaryEngine->flush();
+      }
+    }
+  }
+
+  function updateTombstone() {
+    $this->primaryEngine->set('tombstone', time());
+  }
+}
