PluginProbe
WPJAM Basic / trunk
WPJAM Basic vtrunk
wpjam-basic / template / object-cache.php

object-cache.php in WPJAM Basic trunk, at template/object-cache.php

418 lines 11.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if(
3 // (isset($_POST['action']) && $_POST['action'] == 'query-attachments') ||
4 (isset($_GET['debug']) && $_GET['debug'] == 'sql')
5 ){
6 return;
7 }
8
9 if(!defined('WP_CACHE_KEY_SALT')){
10 define('WP_CACHE_KEY_SALT', '');
11 }
12
13 if(class_exists('Memcached')){
14 function wp_cache_add($key, $data, $group='', $expire=0){
15 global $wp_object_cache;
16 return $wp_object_cache->add($key, $data, $group, (int)$expire);
17 }
18
19 function wp_cache_cas($cas_token, $key, $data, $group='', $expire=0){
20 global $wp_object_cache;
21 return $wp_object_cache->cas($cas_token, $key, $data, $group, (int)$expire);
22 }
23
24 function wp_cache_close(){
25 global $wp_object_cache;
26 return $wp_object_cache->close();
27 }
28
29 function wp_cache_decr($key, $offset=1, $group='', $initial_value=0, $expire=0){
30 global $wp_object_cache;
31 return $wp_object_cache->decr($key, $offset, $group, $initial_value, $expire);
32 }
33
34 function wp_cache_delete($key, $group=''){
35 global $wp_object_cache;
36 return $wp_object_cache->delete($key, $group);
37 }
38
39 function wp_cache_flush(){
40 global $wp_object_cache;
41 return $wp_object_cache->flush();
42 }
43
44 function wp_cache_get($key, $group='', $force=false, &$found=null){
45 global $wp_object_cache;
46 return $wp_object_cache->get($key, $group, $force, $found);
47 }
48
49 function wp_cache_get_multiple($keys, $group='', $force=false){
50 global $wp_object_cache;
51 return $wp_object_cache->get_multiple($keys, $group, $force);
52 }
53
54 function wp_cache_set_multiple($data, $group='', $expire=0){
55 global $wp_object_cache;
56 return $wp_object_cache->set_multiple($data, $group, $expire);
57 }
58
59 function wp_cache_delete_multiple($keys, $group=''){
60 global $wp_object_cache;
61 return $wp_object_cache->delete_multiple($keys, $group);
62 }
63
64 function wp_cache_get_with_cas($key, $group='', &$token=null){
65 global $wp_object_cache;
66
67 $result = $wp_object_cache->get_with_cas($key, $group);
68
69 if(is_array($result)){
70 $token = $result['cas'];
71 $result = $result['value'];
72 }
73
74 return $result;
75 }
76
77 function wp_cache_incr($key, $offset=1, $group='', $initial_value=0, $expire=0){
78 global $wp_object_cache;
79 return $wp_object_cache->incr($key, $offset, $group, $initial_value, $expire);
80 }
81
82 if(!isset($_GET['debug']) || $_GET['debug'] != 'sql'){
83 function wp_cache_init(){
84 $GLOBALS['wp_object_cache'] = new WP_Object_Cache();
85 }
86 }
87
88 function wp_cache_replace($key, $data, $group='', $expire=0){
89 global $wp_object_cache;
90 return $wp_object_cache->replace($key, $data, $group, (int)$expire);
91 }
92
93 function wp_cache_set($key, $data, $group='', $expire=0){
94 global $wp_object_cache;
95 return $wp_object_cache->set($key, $data, $group, (int)$expire);
96 }
97
98 function wp_cache_switch_to_blog($blog_id){
99 global $wp_object_cache;
100 return $wp_object_cache->switch_to_blog($blog_id);
101 }
102
103 function wp_cache_add_global_groups($groups){
104 global $wp_object_cache;
105 $wp_object_cache->add_global_groups($groups);
106 }
107
108 function wp_cache_add_non_persistent_groups($groups){
109 global $wp_object_cache;
110 $wp_object_cache->add_non_persistent_groups($groups);
111 }
112
113 function wp_cache_get_stats(){
114 global $wp_object_cache;
115 return $wp_object_cache->get_stats();
116 }
117
118 class WP_Object_Cache{
119 private $cache = [];
120 private $mc = null;
121
122 private $blog_prefix;
123 private $global_prefix;
124
125 protected $global_groups = [];
126 protected $non_persistent_groups = [];
127
128 protected function action($action, $id, $group, $data, $expire=0){
129 if($this->is_non_persistent_group($group)){
130 $internal = $this->internal('get', $id, $group);
131
132 if($action == 'add'){
133 if($internal !== false){
134 return false;
135 }
136 }elseif($action == 'replace'){
137 if($internal === false){
138 return false;
139 }
140 }elseif($action == 'increment' || $action == 'decrement'){
141 $data = $action == 'increment' ? $data : (0-$data);
142 $data = (int)$internal+$data;
143 $data = $data < 0 ? 0 : $data;
144 }
145
146 return $this->internal('add', $id, $group, $data);
147 }else{
148 $key = $this->build_key($id, $group);
149 $expire = (!$expire && strlen($id) > 50) ? DAY_IN_SECONDS : $expire;
150
151 if($action == 'set'){
152 $result = $this->mc->set($key, $data, $expire);
153 }elseif($action == 'add'){
154 $result = $this->mc->add($key, $data, $expire);
155 }elseif($action == 'replace'){
156 $result = $this->mc->replace($key, $data, $expire);
157 }elseif($action == 'increment'){
158 $result = $data = $this->mc->increment($key, $data);
159 }elseif($action == 'decrement'){
160 $result = $data = $this->mc->decrement($key, $data);
161 }
162
163 $code = $this->mc->getResultCode();
164
165 if($code === Memcached::RES_SUCCESS){
166 $this->internal('add', $id, $group, $data);
167 }else{
168 $this->internal('del', $id, $group);
169
170 if($code != Memcached::RES_NOTSTORED){
171 // trigger_error($code.' '.var_export($result, true).' '.var_export($key, true));
172 }
173 }
174
175 return $result;
176 }
177 }
178
179 protected function internal($action, $id, $group, $data=null){
180 $group = $this->parse_group($group);
181
182 if($action == 'get'){
183 $data = $this->cache[$group][$id] ?? false;
184
185 return is_object($data) ? clone $data : $data;
186 }elseif($action == 'add'){
187 $this->cache[$group][$id] = is_object($data) ? clone $data : $data;
188
189 return true;
190 }elseif($action == 'del'){
191 unset($this->cache[$group][$id]);
192 }
193 }
194
195 public function add($id, $data, $group='default', $expire=0){
196 if(wp_suspend_cache_addition()){
197 return false;
198 }
199
200 return $this->action('add', $id, $group, $data, $expire);
201 }
202
203 public function replace($id, $data, $group='default', $expire=0){
204 return $this->action('replace', $id, $group, $data, $expire);
205 }
206
207 public function set($id, $data, $group='default', $expire=0){
208 return $this->action('set', $id, $group, $data, $expire);
209 }
210
211 public function incr($id, $offset=1, $group='default', $initial_value=0, $expire=0){
212 $this->action('add', $id, $group, $initial_value, $expire);
213 return $this->action('increment', $id, $group, $offset);
214 }
215
216 public function decr($id, $offset=1, $group='default', $initial_value=0, $expire=0){
217 $this->action('add', $id, $group, $initial_value, $expire);
218 return $this->action('decrement', $id, $group, $offset);
219 }
220
221 public function cas($cas_token, $id, $data, $group='default', $expire=0){
222 $this->internal('del', $id, $group);
223
224 return $this->mc->cas($cas_token, $this->build_key($id, $group), $data, $expire);
225 }
226
227 public function delete($id, $group='default'){
228 $this->internal('del', $id, $group);
229
230 return $this->is_non_persistent_group($group) ? true : $this->mc->delete($this->build_key($id, $group));
231 }
232
233 public function flush(){
234 $this->cache = [];
235
236 return $this->mc->flush();
237 }
238
239 public function get($id, $group='default', $force=false, &$found=null){
240 $value = $force ? false : $this->internal('get', $id, $group);
241 $found = $value !== false;
242
243 if(!$found && !$this->is_non_persistent_group($group)){
244 $value = $this->mc->get($this->build_key($id, $group));
245 $code = $this->mc->getResultCode();
246 $found = $code !== Memcached::RES_NOTFOUND;
247
248 if($found){
249 if($code !== Memcached::RES_SUCCESS){
250 trigger_error($code.' '.var_export([$id, $group, $value], true));
251 }
252
253 $this->internal('add', $id, $group, $value);
254 }
255 }
256
257 return $value;
258 }
259
260 public function get_with_cas($id, $group='default'){
261 $key = $this->build_key($id, $group);
262
263 if(defined('Memcached::GET_EXTENDED')){
264 $result = $this->mc->get($key, null, Memcached::GET_EXTENDED);
265 }else{
266 $value = $this->mc->get($key, null, $cas);
267 $result = ['value'=>$value, 'cas'=>$cas];
268 }
269
270 return $this->mc->getResultCode() === Memcached::RES_NOTFOUND ? false : $result;
271 }
272
273 public function get_multiple($ids, $group='default', $force=false){
274 $caches = [];
275 $keys = [];
276
277 $non_persistent = $this->is_non_persistent_group($group);
278
279 if($non_persistent || !$force){
280 foreach($ids as $id){
281 $caches[$id] = $this->internal('get', $id, $group);
282 $keys[$id] = $this->build_key($id, $group);
283
284 if(!$non_persistent && $caches[$id] === false){
285 $force = true;
286 }
287 }
288
289 if($non_persistent || !$force){
290 return $caches;
291 }
292 }
293
294 $results = $this->mc->getMulti(array_values($keys)) ?: [];
295
296 foreach($keys as $id => $key){
297 $caches[$id] = $results[$key] ?? false;
298
299 $this->internal('add', $id, $group, $caches[$id]);
300 }
301
302 return $caches;
303 }
304
305 public function set_multiple($data, $group='default', $expire=0){
306 $items = [];
307
308 foreach($data as $id => $value){
309 $this->internal('add', $id, $group, $value);
310
311 $key = $this->build_key($id, $group);
312
313 $items[$key] = $value;
314 }
315
316 if($this->is_non_persistent_group($group)){
317 $result = true;
318 }else{
319 $result = $this->mc->setMulti($items, $expire);
320 $code = $this->mc->getResultCode();
321
322 if($code !== Memcached::RES_SUCCESS){
323 if($code != Memcached::RES_NOTSTORED){
324 // trigger_error($code.' '.var_export($result,true));
325 }
326
327 foreach($data as $id => $value){
328 $this->internal('del', $id, $group);
329 }
330
331 return $result;
332 }
333 }
334
335 return $result;
336 }
337
338 public function delete_multiple($ids, $group='default'){
339 foreach($ids as $id){
340 $this->internal('del', $id, $group);
341
342 $keys[] = $this->build_key($id, $group);
343 }
344
345 return (empty($keys) || $this->is_non_persistent_group($group)) ? true : $this->mc->deleteMulti($keys);
346 }
347
348 public function add_global_groups($groups){
349 $this->global_groups = array_merge($this->global_groups, array_fill_keys((array)$groups, true));
350 }
351
352 public function add_non_persistent_groups($groups){
353 $this->non_persistent_groups = array_merge($this->non_persistent_groups, array_fill_keys((array)$groups, true));
354 }
355
356 public function switch_to_blog($blog_id){
357 if(is_multisite()){
358 $this->blog_prefix = ((int)$blog_id).':';
359 }
360 }
361
362 private function is_non_persistent_group($group){
363 return $group ? isset($this->non_persistent_groups[$group]) : false;
364 }
365
366 private function parse_group($group){
367 $group = $group ?: 'default';
368 $prefix = isset($this->global_groups[$group]) ? $this->global_prefix : $this->blog_prefix;
369
370 return WP_CACHE_KEY_SALT.$prefix.$group;
371 }
372
373 public function build_key($id, $group='default'){
374 return preg_replace('/\s+/', '', $this->parse_group($group).':'.$id);
375 }
376
377 public function get_stats(){
378 return $this->mc->getStats();
379 }
380
381 public function get_mc(){
382 return $this->mc;
383 }
384
385 public function failure_callback($host, $port){}
386
387 public function close(){
388 $this->mc->quit();
389 }
390
391 public function __construct(){
392 $this->mc = new Memcached();
393 // $this->mc->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true); // 用于启用与 libketama 一致性哈希算法�
394 �容的服务器分布策略
395
396 if(!$this->mc->getServerList()){
397 global $memcached_servers;
398
399 if(isset($memcached_servers)){
400 foreach($memcached_servers as $memcached){
401 $this->mc->addServer(...$memcached);
402 }
403 }else{
404 $this->mc->addServer('127.0.0.1', 11211);
405 }
406 }
407
408 if(is_multisite()){
409 $this->blog_prefix = get_current_blog_id().':';
410 $this->global_prefix = '';
411 }else{
412 $this->blog_prefix = $GLOBALS['table_prefix'].':';
413 $this->global_prefix = defined('CUSTOM_USER_TABLE') ? '' : $this->blog_prefix;
414 }
415 }
416 }
417 }
418