Permalink
Browse files

added lib

  • Loading branch information...
1 parent e24765f commit ceef91ea07e903a155d0cb8199fc89e87c943410 @natepixel committed Sep 26, 2010
View
109 lib/object_cache/cache_types/db.php
@@ -0,0 +1,109 @@
+<?php
+include_once(CARL_UTIL_INC . 'cache/cache_types/default.php');
+include_once(CARL_UTIL_INC . 'db/connectDB.php');
+include_once(CARL_UTIL_INC . 'db/db_query.php');
+
+/**
+ * Cache type that uses a mysql database - the constants OBJECT_CACHE_DB_CONN and OBJECT_CACHE_DB_TABLE must be setup.
+ *
+ * The table must have the following columns:
+ * - "id" primary key
+ * - "content" column (with plenty of storage)
+ * - "date_created" timestamp that updates with modifications.
+ *
+ * Something like the following should get the right table:
+ *
+ * CREATE TABLE `_cache` (`id` VARCHAR( 32 ) NOT NULL,
+ * `content` TEXT NULL,
+ * `date_created` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ * PRIMARY KEY ( `id` ));
+ *
+ * A drawback of this using mysql is that large caches may not work well, particularly if the amount of data mysql will accept
+ * in a single transcation is set at a low value. It is preferably to get memcached up and running or to use file system caching.
+ *
+ * @package carl_util
+ * @subpackage cache
+ * @author Nathan White
+ */
+
+class DbObjectCache extends DefaultObjectCache
+{
+ var $error_msg = ' make sure that the OBJECT_CACHE_DB_CONN and OBJECT_CACHE_DB_TABLE constants are properly setup in object_cache_settings.php.';
+
+ function &fetch()
+ {
+ $ret = false;
+ $cache_id = $this->get_cache_id();
+ $lifespan = $this->get_cache_lifespan();
+
+ $this->_cache_conn(true);
+ $qry = 'SELECT * from ' . OBJECT_CACHE_DB_TABLE . ' WHERE id="'.$cache_id.'"';
+ $result = db_query($qry, 'Select query failed -' . $this->error_msg, false);
+ $this->_cache_conn(false);
+
+ if ($result)
+ {
+ $row = mysql_fetch_assoc($result);
+ $created = get_unix_timestamp($row['date_created']);
+ $ret = ((time() - $created) < $lifespan)
+ ? unserialize($row['content'])
+ : false;
+ }
+ return $ret;
+ }
+
+ function set(&$object)
+ {
+ $cache_id = $this->get_cache_id();
+ $content = mysql_real_escape_string(serialize($object));
+ $qry = 'INSERT INTO ' . OBJECT_CACHE_DB_TABLE . ' (id, content) VALUES ("'.$cache_id.'", "'.$content.'") ON DUPLICATE KEY UPDATE content="'.$content.'";';
+ $this->_cache_conn(true);
+ $result = db_query($qry, 'Insert failed -' . $this->error_msg, false);
+ $this->_cache_conn(false);
+ return ($result);
+ }
+
+ function clear()
+ {
+ $cache_id = $this->get_cache_id();
+ $qry = 'DELETE FROM ' . OBJECT_CACHE_DB_TABLE . ' WHERE id = "'.$cache_id.'" LIMIT 1';
+ $this->_cache_conn(true);
+ $result = db_query($qry, 'Delete failed -' . $this->error_msg, false);
+ $this->_cache_conn(false);
+ return ($result);
+ }
+
+ /**
+ * Make sure that the database and table exist
+ */
+ function validate()
+ {
+ $db_conn_test = (defined('OBJECT_CACHE_DB_CONN') && OBJECT_CACHE_DB_CONN );
+ $db_table_test = (defined('OBJECT_CACHE_DB_TABLE') && OBJECT_CACHE_DB_TABLE );
+ if (!$db_conn_test) trigger_error('You need to populate OBJECT_CACHE_DB_CONN in object_cache_settings.php to use database caching');
+ if (!$db_table_test) trigger_error('You need to populate OBJECT_CACHE_DB_TABLE in object_cache_settings.php to use database caching');
+ return ($db_conn_test && $db_table_test);
+ }
+
+ /**
+ * Private function to handle database connections - only makes a new connection when needed
+ * @access private
+ */
+ function _cache_conn($bool)
+ {
+ static $orig;
+ static $curr;
+ if (empty($orig)) $orig = $curr = get_current_db_connection_name();
+ if ($bool && ($curr != OBJECT_CACHE_DB_CONN))
+ {
+ connectDB(OBJECT_CACHE_DB_CONN);
+ $curr = OBJECT_CACHE_DB_CONN;
+ }
+ elseif (!$bool && ($curr != $orig))
+ {
+ connectDB($orig);
+ $curr = $orig;
+ }
+ }
+}
+?>
View
117 lib/object_cache/cache_types/default.php
@@ -0,0 +1,117 @@
+<?php
+
+/**
+ * Defines the interface for object cache types
+ *
+ * Any object cache type should define these methods
+ *
+ * -fetch
+ * -set
+ * -clear
+ * -validate
+ *
+ * A method setup_custom can be used to refer to additional settings for the type present in the object_cache_settings.php file
+ *
+ * @package carl_util
+ * @subpackage cache
+ * @author Nathan White
+ */
+
+class DefaultObjectCache
+{
+
+ /**
+ * @var int lifespan in cache in seconds;
+ */
+ var $cache_lifespan = OBJECT_CACHE_DEFAULT_LIFESPAN;
+
+ /**
+ * @var string unique identifier for the cache
+ */
+ var $cache_id;
+
+ /**
+ * Fetches an object or array from the cache
+ * @return mixed object/array from cache or false if it was not found
+ */
+ function &fetch()
+ {
+ }
+
+ /**
+ * Saves an object or array to the cache
+ * @param object or array to cache
+ * @return boolean success or failure
+ */
+ function set(&$object)
+ {
+ }
+
+ /**
+ * Removes an object or array from the cache
+ * @return boolean success or failure
+ */
+ function clear()
+ {
+ }
+
+ /**
+ * Run once per page load to setup constants needed by the class
+ */
+ function setup_constants(&$constants)
+ {
+ foreach ($constants as $k=>$v)
+ {
+ if (!defined($k)) define($k, $v);
+ }
+ }
+
+ /**
+ * Run once per page load - custom setup based upon the object_cache_settings settings for a type
+ */
+ function setup_custom(&$settings)
+ {
+ }
+
+ /**
+ * Run once per page load to verify settings and the basic cache type setup
+ */
+ function validate()
+ {
+ return true;
+ }
+
+ /**
+ * @return int cache lifespan in seconds
+ */
+ function get_cache_lifespan()
+ {
+ return $this->cache_lifespan;
+ }
+
+ /**
+ * @return string cache id
+ */
+
+ function get_cache_id()
+ {
+ return $this->cache_id;
+ }
+
+ /**
+ * @return true
+ */
+ function set_cache_id($hash)
+ {
+ $this->cache_id = $hash;
+ }
+
+ /**
+ * @return true
+ */
+ function set_cache_lifespan($seconds)
+ {
+ $this->cache_lifespan = $seconds;
+ }
+}
+?>
View
71 lib/object_cache/cache_types/file.php
@@ -0,0 +1,71 @@
+<?php
+include_once('default.php');
+
+/**
+ * Cache type that uses file system
+ *
+ * @package carl_util
+ * @subpackage cache
+ * @author Nathan White
+ * @todo more error checking - especially during file system transactions
+ */
+
+class FileObjectCache extends DefaultObjectCache
+{
+ function &fetch()
+ {
+ $ret = false;
+ $cache_file = $this->_get_cache_file();
+ $lifespan = $this->get_cache_lifespan();
+ if (file_exists($cache_file))
+ {
+ $last_modified = filemtime($cache_file);
+ $ret = ((time() - $last_modified) < $lifespan)
+ ? unserialize(file_get_contents($cache_file))
+ : false;
+ }
+ return $ret;
+ }
+
+ function set(&$object)
+ {
+ $cache_file = $this->_get_cache_file();
+ $fh = fopen($cache_file,"w");
+ flock($fh, LOCK_EX);
+ fwrite($fh, serialize($object));
+ flock($fh, LOCK_UN);
+ fclose($fh);
+ return true;
+ }
+
+ function clear()
+ {
+ $cache_file = $this->_get_cache_file();
+ if(file_exists($cache_file)) return unlink( $cache_file );
+ }
+
+ // SUPPORT METHODS
+ /**
+ * @return string cache_file
+ */
+ function _get_cache_file()
+ {
+ $cache_id = $this->get_cache_id();
+ $slash_if_needed = (substr(OBJECT_CACHE_DIR, -1, 1) == "/") ? "" : "/";
+ $cache_file = ($cache_id) ? OBJECT_CACHE_DIR .$slash_if_needed.$cache_id.'.obj.cache' : false;
+ return $cache_file;
+ }
+
+ function validate()
+ {
+ $dir_exists = file_exists(OBJECT_CACHE_DIR);
+ $is_readable = is_readable(OBJECT_CACHE_DIR);
+ $is_writable = is_writable(OBJECT_CACHE_DIR);
+ if (!$dir_exists) trigger_error('The OBJECT_CACHE_DIR constant ('.OBJECT_CACHE_DIR.') in object_cache_settings.php references a directory that appears to not exist');
+ elseif (!$is_readable && !$is_writable) trigger_error('The OBJECT_CACHE_DIR constant ('.OBJECT_CACHE_DIR.') in object_cache_settings.php exists, but cannot be read from or written to.');
+ elseif (!$is_readable) trigger_error('The OBJECT_CACHE_DIR constant ('.OBJECT_CACHE_DIR.') in object_cache_settings.php references a directory that exists, but cannot be read from.');
+ elseif (!$is_writable) trigger_error('The OBJECT_CACHE_DIR constant ('.OBJECT_CACHE_DIR.') in object_cache_settings.php references a directory that exists, but cannot be written to.');
+ return ($dir_exists && $is_writable && $is_readable);
+ }
+}
+?>
View
70 lib/object_cache/cache_types/memcached.php
@@ -0,0 +1,70 @@
+<?php
+include_once(CARL_UTIL_INC . 'cache/cache_types/default.php');
+
+/**
+ * Cache type that uses memcached
+ *
+ * @package carl_util
+ * @subpackage cache
+ * @author Nathan White
+ * @todo support multiple servers
+ */
+
+class MemcachedObjectCache extends DefaultObjectCache
+{
+ /**
+ * Fetches a cached object using memcached
+ */
+ function &fetch()
+ {
+ $cache_id = $this->get_cache_id();
+ $lifespan = ($this->get_cache_lifespan()) ? $this->get_cache_lifespan() : 0;
+ $memcached =& $this->_get_memcached_conn();
+ $ret = $memcached->get($cache_id, $lifespan);
+ return $ret;
+ }
+
+ /**
+ * Saves a cache using memcached
+ */
+ function set(&$object)
+ {
+ $cache_id = $this->get_cache_id();
+ $lifespan = ($this->get_cache_lifespan()) ? $this->get_cache_lifespan() : 0;
+ $memcached =& $this->_get_memcached_conn();
+ return $memcached->set($cache_id, $object, MEMCACHE_COMPRESSED, $lifespan);
+ }
+
+ /**
+ * Clear a cache using memcached
+ */
+ function clear()
+ {
+ $cache_id = $this->get_cache_id();
+ $memcached =& $this->_get_memcached_conn();
+ return $memcached->delete($cache_id);
+ }
+
+ // HELPER
+ /**
+ * Returns a reference to the memcached connection
+ * @access private
+ * @return object memcache
+ */
+ function &_get_memcached_conn()
+ {
+ $memcached = new Memcache;
+ $memcached->connect(OBJECT_CACHE_MEMCACHED_SERVER, OBJECT_CACHE_MEMCACHED_PORT);
+ return $memcached;
+ }
+
+ function validate()
+ {
+ $memcached_server_test = (defined('OBJECT_CACHE_MEMCACHED_SERVER') && OBJECT_CACHE_MEMCACHED_SERVER );
+ $memcached_port_test = (defined('OBJECT_CACHE_MEMCACHED_PORT') && OBJECT_CACHE_MEMCACHED_PORT );
+ if (!$memcached_server_test) trigger_error('You need to populate OBJECT_CACHE_MEMCACHED_SERVER in the memcached settings in object_cache_settings.php');
+ if (!$memcached_port_test) trigger_error('You need to populate OBJECT_CACHE_MEMCACHED_PORT in the memcached settings in object_cache_settings.php');
+ return ($memcached_server_test && $memcached_port_test);
+ }
+}
+?>
View
155 lib/object_cache/object_cache.php
@@ -0,0 +1,155 @@
+<?php
+
+/**
+ * This is a utility I wrote for the carl_util library, somewhat altered to remove dependencies.
+ */
+
+/**
+ * Include dependencies
+ */
+require_once('object_cache_settings.php');
+
+/**
+ * Object cache system that fetches and sets serialized objects by id
+ *
+ * Details:
+ * - provides user configurable lifespan for cached objects
+ * - saves and fetches cached objects
+ * - supports creation of additional cache types
+ * - configure default caching type or reference custom caching types in object_cache_settings.php
+ *
+ * Sample usage - $obj will equal false or the cache object with id $unique_id that is not more than one hour old
+ *
+ * <code>
+ * $cache = new ObjectCache();
+ * $cache->init($unique_id, 3600);
+ * $obj =& $cache->fetch();
+ * </code>
+ *
+ * @author Nathan White
+ * @todo implement smart fallbacks so that alternate caching can be used if the specified type fails
+ */
+
+class ObjectCache
+{
+
+ /**
+ * Supported options include file, db, and memcache
+ * @var string defines which cache type to use - defaults to file
+ */
+ var $cache_type = OBJECT_CACHE_DEFAULT_TYPE;
+
+ /**
+ * @var object cache type object
+ */
+ var $_cache = false;
+
+ /**
+ * @param string $id unique identifier for cache object
+ * @param int $lifespan
+ */
+ function ObjectCache($id = '', $lifespan = '', $type = '') // {{{
+ {
+ if ($id) $this->init($id, $lifespan, $type);
+ }
+
+ function init($id = '', $lifespan = '', $type = '')
+ {
+ if (!empty($type)) $this->set_cache_type($type);
+ $cache =& $this->set_cache();
+ if ($id && $cache)
+ {
+ $cache->set_cache_id(md5($id));
+ if ($lifespan) $cache->set_cache_lifespan($lifespan);
+ }
+ elseif (!$id) trigger_error('You must provide an id in order to init the cache');
+ }
+
+ function set_cache_type($type)
+ {
+ $cache =& $this->get_cache();
+ if ($cache === false) $this->cache_type = $type;
+ else
+ {
+ trigger_error('You cannot change the type after the cache has already been initialized - using type ' . $this->get_cache_type());
+ }
+ }
+
+ function get_cache_type()
+ {
+ return $this->cache_type;
+ }
+
+ function &set_cache()
+ {
+ if ($cache_class =& $this->get_cache_class())
+ {
+ $this->_cache = clone($cache_class); // localize a clone of the cache_class
+ }
+ elseif ($cache_class === NULL) trigger_error('The cache type you requested (' . $this->get_cache_type() . ') in not defined in object_cache_settings.php');
+ return $this->_cache;
+ }
+
+ /**
+ * Includes the cache_class file, returns a verified cache class
+ */
+ function &get_cache_class()
+ {
+ static $settings;
+ static $class;
+ $type = $this->get_cache_type();
+ if (!isset($class[$type]))
+ {
+ if (!isset($settings))
+ {
+ $cts = new CacheTypeSettings();
+ $settings =& $cts->get_settings();
+ }
+ $is_defined = (isset($settings[$type]));
+ $file_path = (isset($settings[$type]['path'])) ? ($settings[$type]['path']) : false;
+ if ($is_defined && $file_path)
+ {
+ include_once($file_path);
+ $cache_class_name[$type] = (isset($settings[$type]['classname']))
+ ? $settings[$type]['classname']
+ : ucfirst(basename($file_path, ".php")) .'ObjectCache';
+
+ // create an instance and run setup methods
+ $cache = new $cache_class_name[$type];
+ $cache->setup_constants($settings[$type]['constants']);
+ $cache->setup_custom($settings[$type]);
+ }
+ if (!$is_defined) $class[$type] = NULL;
+ elseif ($file_path && $cache->validate()) $class[$type] =& $cache;
+ else $class[$type] = false;
+ }
+ return $class[$type];
+ }
+
+ function &get_cache()
+ {
+ return $this->_cache;
+ }
+
+ function &fetch()
+ {
+ $cache =& $this->get_cache();
+ $result = ($cache) ? $cache->fetch() : false;
+ return $result;
+ }
+
+ function set($object)
+ {
+ $cache =& $this->get_cache();
+ $result = ($cache) ? $cache->set($object) : false;
+ return $result;
+ }
+
+ function clear()
+ {
+ $cache =& $this->get_cache();
+ $result = ($cache) ? $cache->clear() : false;
+ return $result;
+ }
+}
+?>
View
53 lib/object_cache/object_cache_settings.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Object Cache Type Settings - defines constants and paths for Cache Types
+ *
+ * To define settings for a new type, add an entry to the object_cache_types array
+ * @author Nathan White
+ * @package carl_util
+ * @subpackage cache
+ */
+
+/**
+ * OBJECT_CACHE_DEFAULT_TYPE
+ *
+ * Sets the type of cache you want to use by default
+ *
+ * - file
+ * - db (requires some setup)
+ * - memcached (requires some setup)
+ *
+ */
+define( 'OBJECT_CACHE_DEFAULT_TYPE', 'file' );
+
+/**
+ * OBJECT_CACHE_DEFAULT_LIFESPAN
+ *
+ * How long cached objects should be valid when a lifespan is not explicitly passed (in seconds)
+ */
+define( 'OBJECT_CACHE_DEFAULT_LIFESPAN', 3600 );
+
+class CacheTypeSettings
+{
+ /**
+ * @return array settings
+ */
+ function &get_settings()
+ {
+ static $settings;
+ if (!isset($settings))
+ {
+ $cache_dir = (defined('REASON_CACHE_DIR')) ? REASON_CACHE_DIR : '/tmp';
+ $settings = array ('file' => array('path' => dirname(__FILE__).'/cache_types/file.php',
+ 'constants' => array('OBJECT_CACHE_DIR' => $cache_dir)),
+ 'db' => array('path' => dirname(__FILE__).'/cache_types/db.php',
+ 'constants' => array('OBJECT_CACHE_DB_CONN' => '',
+ 'OBJECT_CACHE_DB_TABLE' => '')),
+ 'memcached' => array('path' => dirname(__FILE__).'/cache_types/memcached.php',
+ 'constants' => array('OBJECT_CACHE_MEMCACHED_SERVER' => '',
+ 'OBJECT_CACHE_MEMCACHED_PORT' => '')));
+ }
+ return $settings;
+ }
+}
+?>

0 comments on commit ceef91e

Please sign in to comment.