Campustream 1.0
A social network MQP for WPI
core/lib/activecache.php
Go to the documentation of this file.
00001 <?php
00002 
00003 class ActiveCache {
00004         
00005         private $run_sql    = false;
00006         private $find_all   = false;
00007         private $result_set = null;
00008         private $object     = null;
00009         private static $mem_cache       = array();
00010         
00011         public static function find( $class, $cache_key, $expire=0 ) {
00012                 
00013                 $memcache = MemcacheManager::connection();
00014                 
00015                 $table_name = ActiveRecord::model_to_table_name( $class );
00016                 $cache_key  = substr($table_name, 0, -1) . '/' . $cache_key;
00017                 
00018                 Logger::debug( "looking up cache key $cache_key");
00019                 
00020                 if (!empty(self::$mem_cache[$cache_key])) {
00021                         Logger::debug( "using local cache key $cache_key" );
00022                         return new ActiveCache( $class, $cache_key, $expire, self::$mem_cache[$cache_key]);
00023                 } elseif ( ( $result = $memcache->get( $cache_key ) ) !== false ) {
00024                         return new ActiveCache( $class, $cache_key, $expire, $result );
00025                 } else {
00026                         return new ActiveCache( $class, $cache_key, $expire );
00027                 }
00028                 
00029         }
00030         
00031         public static function find_all( $class, $cache_key, $expire=0 ) {
00032                 
00033                 $memcache = MemcacheManager::connection();
00034                 
00035                 $table_name = ActiveRecord::model_to_table_name( $class );
00036                 $cache_key  = $table_name . '/' . $cache_key;
00037                 
00038                 Logger::debug( "looking up cache key $cache_key");
00039                 
00040                 
00041                 if (!empty(self::$mem_cache[$cache_key])) {
00042                         Logger::debug( "using local cache key $cache_key" );
00043                         return new ActiveCache( $class, $cache_key, $expire, self::$mem_cache[$cache_key]);
00044                 } elseif ( ( $result = $memcache->get( $cache_key ) ) !== false ) {
00045                         return new ActiveCache( $class, $cache_key, $expire, $result, true );
00046                         Logger::debug( "found cache key $cache_key");
00047                 } else {
00048                         return new ActiveCache( $class, $cache_key, $expire, null, true );
00049                 }
00050                 
00051         }
00052         
00053         public static function invalidate_keys_for( ActiveRecord $object ) {
00054                 $memcache = MemcacheManager::connection();
00055                                 
00056                 foreach ( $object->cache_keys as $cache_key => $replace ) {
00057                         if ( $replace !== null ) $cache_key = str_replace( '#', $object->{$replace}, $cache_key );
00058                         $memcache->delete( $cache_key );
00059                         Logger::debug( "deleting $cache_key" );
00060                 }
00061         }
00062         
00063         public function __construct( $class, $cache_key, $expire=0, $result=null, $find_all=false ) {
00064                 $this->class = $class;
00065                 $this->cache_key = $cache_key;
00066                 
00067                 if ( $expire == 0 ) {
00068                         $this->expire = 0;
00069                 } else {
00070                         $this->expire = $expire + time();
00071                 }
00072                 // used to keep track if being called w/ find_all or find
00073                 $this->find_all = $find_all;
00074                 if ( $result === null ) {
00075                         $this->run_sql = true;
00076                         return; 
00077                 }
00078                 
00079                 $this->result_set = $result;
00080                 
00081         }
00082         
00083         public function sql( $clause ) {
00084                 // only run the sql if nothing was found in the cache
00085                 if ( $this->run_sql === true ) {
00086                         
00087                         $memcache = MemcacheManager::connection();
00088                         
00089                         if ( $this->find_all === false ) {
00090                                 $this->result_set = ActiveRecord::find( $this->class, $clause );
00091                                 if ( $this->result_set->is_loaded() === false ) return $this->result_set; // we don't want to cache an empty object 
00092                         } else {
00093                                 $this->result_set = ActiveRecord::find_all( $this->class, $clause );
00094                         }
00095                         
00096                         Logger::debug( "setting cache key $this->cache_key");
00097                         $memcache->set( $this->cache_key, $this->result_set, $this->expire);
00098                         
00099                 }
00100                 
00101                 self::$mem_cache[$this->cache_key] = $this->result_set;
00102                 
00103                 // subscribe to save() and delete() events, which will call
00104                 // ActiveCache->notify and invalidate cache keys automatically.
00105                 
00106                 if ( is_array( $this->result_set ) ) {
00107                         foreach( $this->result_set as $result ) {
00108                                 $result->cache_keys[ $this->cache_key ] = null;
00109                                 $result->subscribe( $this );
00110                         }
00111                 } else {
00112                         $this->result_set->cache_keys[ $this->cache_key ] = null;
00113                         $this->result_set->subscribe( $this );
00114                 }
00115                 
00116                 $result_set = $this->result_set;
00117                 $this->result_set = null;
00118                 
00119                 
00120                 return $result_set;
00121         
00122         }
00123         
00124         public function notify( ActiveRecord $object ) {
00125                 ActiveCache::invalidate_keys_for( $object );
00126         }
00127 }