Overview

Packages

  • awl
    • AuthPlugin
    • AwlDatabase
    • Browser
    • classEditor
    • DataEntry
    • DataUpdate
    • EMail
    • iCalendar
    • MenuSet
    • PgQuery
    • Session
    • Translation
    • User
    • Utilities
    • Validation
    • vCalendar
    • vComponent
    • XMLDocument
    • XMLElement
  • None
  • PHP

Classes

  • AwlCache
  • Multipart
  • SinglePart
  • vObject

Functions

  • getCacheInstance
  • translate
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: 
  3: /**
  4:  * A simple Memcached wrapper supporting namespacing of stored values.
  5:  *
  6:  * @author Andrew McMillan
  7:  * @license LGPL v2 or later
  8:  */
  9: 
 10: class AwlCache {
 11:   private static $m;
 12:   private static $servers;
 13:   private static $working;
 14: 
 15:   /**
 16:    * Initialise the cache connection. We use getpid() to give us a persistent connection.
 17:    */
 18:   function __construct() {
 19:     global $c;
 20: 
 21:     if ( isset(self::$working) ) return;
 22: 
 23:     self::$working = false;
 24:     if ( isset($c->memcache_servers) && class_exists('Memcached') ) {
 25:       dbg_error_log('Cache', 'Using Memcached interface connection');
 26:       self::$servers = $c->memcache_servers;
 27:       self::$m = new Memcached();
 28:       foreach( self::$servers AS $v ) {
 29:         dbg_error_log('Cache', 'Adding server '.$v);
 30:         $server = explode(',',$v);
 31:         if ( isset($server[2]) )
 32:           self::$m->addServer($server[0],$server[1],$server[2]);
 33:         else
 34:           self::$m->addServer($server[0],$server[1]);
 35:       }
 36:       self::$working = true;
 37:       // Hack to allow the regression tests to flush the cache at start
 38:       if ( isset($_SERVER['HTTP_X_DAVICAL_FLUSH_CACHE'])) $this->flush();
 39:     }
 40:     else {
 41:       dbg_error_log('Cache', 'Using NoCache dummy interface');
 42:     }
 43:   }
 44: 
 45:   /**
 46:    * So we can find out if we are actually using the cache.
 47:    */
 48:   function isActive() {
 49:     return self::$working;
 50:   }
 51: 
 52:   /**
 53:    * Construct a string from the namespace & key
 54:    * @param unknown_type $namespace
 55:    * @param unknown_type $key
 56:    */
 57:   private function nskey( $namespace, $key ) {
 58:     return str_replace(' ', '%20', $namespace . (isset($key) ? '~~' . $key: '')); // for now.
 59:   }
 60: 
 61:   /**
 62:    * get a value from the specified namespace / key
 63:    * @param $namespace
 64:    * @param $key
 65:    */
 66:   function get( $namespace, $key ) {
 67:     if ( !self::$working ) return false;
 68:     $ourkey = self::nskey($namespace,$key);
 69:     $value = self::$m->get($ourkey);
 70: //    var_dump($value);
 71: //    if ( $value !== false ) dbg_error_log('Cache', 'Got value for cache key "'.$ourkey.'" - '.strlen(serialize($value)).' bytes');
 72:     return $value;
 73:   }
 74: 
 75:   /**
 76:    * Set a value for the specified namespace/key, perhaps with an expiry (default 10 days)
 77:    * @param $namespace
 78:    * @param $key
 79:    * @param $value
 80:    * @param $expiry
 81:    */
 82:   function set( $namespace, $key, $value, $expiry=864000 ) {
 83:     if ( !self::$working ) return false;
 84:     $ourkey = self::nskey($namespace,$key);
 85:     $nskey = self::nskey($namespace,null);
 86:     $keylist = self::$m->get( $nskey, null, $cas_token );
 87:     if ( isset($keylist) && is_array($keylist) ) {
 88:       if ( !isset($keylist[$ourkey]) ) {
 89:         $keylist[$ourkey] = 1;
 90:         $success = self::$m->cas( $cas_token, $nskey, $keylist );
 91:         $i=0;
 92:         while( !$success && $i++ < 10 && self::$m->getResultCode() == Memcached::RES_DATA_EXISTS ) {
 93:           $keylist = self::$m->get( $nskey, null, $cas_token );
 94:           if ( $keylist === false ) return false;
 95:           if ( isset($keylist[$ourkey]) ) break;
 96:           $keylist[$ourkey] = 1;
 97:           $success = self::$m->cas( $cas_token, $nskey, $keylist );
 98:         }
 99:         if ( !$success ) return false;
100:       }
101:     }
102:     else {
103:       $keylist = array( $ourkey => 1 );
104:       self::$m->set( $nskey, $keylist );
105:     }
106: //    var_dump($value);
107: //    dbg_error_log('Cache', 'Setting value for cache key "'.$ourkey.'" - '.strlen(serialize($value)).' bytes');
108:     return self::$m->set( $ourkey, $value, $expiry );
109:   }
110: 
111:   /**
112:    * Delete a value from a namespace/key, or for everything in a namespace if a 'null' key is supplied.
113:    * @param $namespace
114:    * @param $key
115:    */
116:   function delete( $namespace, $key ) {
117:     if ( !self::$working ) return false;
118:     $nskey = self::nskey($namespace,$key);
119:     dbg_error_log('Cache', 'Deleting from cache key "'.$nskey.'"');
120:     if ( isset($key) ) {
121:       self::$m->delete( $nskey );
122:     }
123:     else {
124:       $keylist = self::$m->get( $nskey, null, $cas_token );
125:       if ( isset($keylist) ) {
126:       self::$m->delete( $nskey );
127:         if ( is_array($keylist) ) {
128:           foreach( $keylist AS $k => $v ) self::$m->delete( $k );
129:         }
130:       }
131:     }
132:   }
133: 
134:   /**
135:    * Flush the entire cache
136:    */
137:   function flush( ) {
138:     if ( !self::$working ) return false;
139:     dbg_error_log('Cache', 'Flushing cache');
140:     self::$m->flush();
141:   }
142: 
143: 
144:   /**
145:    * Acquire a lock on something
146:    */
147:   function acquireLock( $something, $wait_for = 5 ) {
148:     if ( !self::$working ) return $something;
149:     $wait_until = time() + $wait_for;
150:     while( self::$m->add('_lock_'+$something,1,5) === false && time() < $wait_until ) {
151:       usleep(10000);
152:     }
153:     return $something;
154:   }
155: 
156: 
157:   /**
158:    * Release a lock
159:    */
160:   function releaseLock( $something ) {
161:     if ( !self::$working ) return;
162:     self::$m->delete('_lock_'+$something);
163:   }
164: }
165: 
166: 
167: function getCacheInstance() {
168:   static $ourCacheInstance;
169: 
170:   if ( !isset($ourCacheInstance) ) $ourCacheInstance = new AWLCache('Memcached');
171: 
172:   return $ourCacheInstance;
173: }
174: 
AWL API documentation generated by ApiGen 2.8.0