1: <?php
2:
3: 4: 5: 6: 7: 8:
9:
10: class AwlCache {
11: private static $m;
12: private static $servers;
13: private static $working;
14:
15: 16: 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:
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: 47:
48: function isActive() {
49: return self::$working;
50: }
51:
52: 53: 54: 55: 56:
57: private function nskey( $namespace, $key ) {
58: return str_replace(' ', '%20', $namespace . (isset($key) ? '~~' . $key: ''));
59: }
60:
61: 62: 63: 64: 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:
71:
72: return $value;
73: }
74:
75: 76: 77: 78: 79: 80: 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:
107:
108: return self::$m->set( $ourkey, $value, $expiry );
109: }
110:
111: 112: 113: 114: 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: 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: 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: 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: