[AwlCache] Make this mostly static.
[awl.git] / inc / AwlCache.php
blob8ed5c0c9599d8164a57a5721d97b4c1286e56949
1 <?php
3 /**
4 * A simple Memcached wrapper supporting namespacing of stored values.
5 *
6 * @author Andrew McMillan
7 * @license LGPL v2 or later
8 */
10 class AwlCache {
11 private static $m;
12 private static $servers;
13 private static $working;
15 /**
16 * Initialise the cache connection. We use getpid() to give us a persistent connection.
18 function __construct() {
19 global $c;
21 if ( isset(self::$working) ) return;
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]);
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();
40 else {
41 dbg_error_log('Cache', 'Using NoCache dummy interface');
45 /**
46 * So we can find out if we are actually using the cache.
48 function isActive() {
49 return self::$working;
52 /**
53 * Construct a string from the namespace & key
54 * @param unknown_type $namespace
55 * @param unknown_type $key
57 private function nskey( $namespace, $key ) {
58 return str_replace(' ', '%20', $namespace . (isset($key) ? '~~' . $key: '')); // for now.
61 /**
62 * get a value from the specified namespace / key
63 * @param $namespace
64 * @param $key
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;
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
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 );
99 if ( !$success ) return false;
102 else {
103 $keylist = array( $ourkey => 1 );
104 self::$m->set( $nskey, $keylist );
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 );
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
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 );
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 );
135 * Flush the entire cache
137 function flush( ) {
138 if ( !self::$working ) return false;
139 dbg_error_log('Cache', 'Flushing cache');
140 self::$m->flush();
145 function getCacheInstance() {
146 static $ourCacheInstance;
148 if ( !isset($ourCacheInstance) ) $ourCacheInstance = new AWLCache('Memcached');
150 return $ourCacheInstance;