r83135 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r83134‎ | r83135 | r83136 >
Date:04:38, 3 March 2011
Author:tstarling
Status:ok
Tags:
Comment:
Start of ObjectCache reorganisation. Moved the object cache files to includes/objectcache/. Split BagOStuff.php into single-class files.
Modified paths:
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/BagOStuff.php (deleted) (history)
  • /trunk/phase3/includes/ObjectCache.php (deleted) (history)
  • /trunk/phase3/includes/Setup.php (modified) (history)
  • /trunk/phase3/includes/objectcache (added) (history)
  • /trunk/phase3/includes/objectcache/APCBagOStuff.php (added) (history)
  • /trunk/phase3/includes/objectcache/BagOStuff.php (added) (history)
  • /trunk/phase3/includes/objectcache/DBABagOStuff.php (added) (history)
  • /trunk/phase3/includes/objectcache/HashBagOStuff.php (added) (history)
  • /trunk/phase3/includes/objectcache/ObjectCache.php (added) (history)
  • /trunk/phase3/includes/objectcache/SqlBagOStuff.php (added) (history)
  • /trunk/phase3/includes/objectcache/WinCacheBagOStuff.php (added) (history)
  • /trunk/phase3/includes/objectcache/XCacheBagOStuff.php (added) (history)
  • /trunk/phase3/includes/objectcache/eAccelBagOStuff.php (added) (history)

Diff [purge]

Index: trunk/phase3/includes/BagOStuff.php
@@ -1,905 +0,0 @@
2 -<?php
3 -/**
4 - * Classes to cache objects in PHP accelerators, SQL database or DBA files
5 - *
6 - * Copyright © 2003-2004 Brion Vibber <brion@pobox.com>
7 - * http://www.mediawiki.org/
8 - *
9 - * This program is free software; you can redistribute it and/or modify
10 - * it under the terms of the GNU General Public License as published by
11 - * the Free Software Foundation; either version 2 of the License, or
12 - * (at your option) any later version.
13 - *
14 - * This program is distributed in the hope that it will be useful,
15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 - * GNU General Public License for more details.
18 - *
19 - * You should have received a copy of the GNU General Public License along
20 - * with this program; if not, write to the Free Software Foundation, Inc.,
21 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 - * http://www.gnu.org/copyleft/gpl.html
23 - *
24 - * @file
25 - * @ingroup Cache
26 - */
27 -
28 -/**
29 - * @defgroup Cache Cache
30 - */
31 -
32 -/**
33 - * interface is intended to be more or less compatible with
34 - * the PHP memcached client.
35 - *
36 - * backends for local hash array and SQL table included:
37 - * <code>
38 - * $bag = new HashBagOStuff();
39 - * $bag = new SqlBagOStuff(); # connect to db first
40 - * </code>
41 - *
42 - * @ingroup Cache
43 - */
44 -abstract class BagOStuff {
45 - var $debugMode = false;
46 -
47 - public function set_debug( $bool ) {
48 - $this->debugMode = $bool;
49 - }
50 -
51 - /* *** THE GUTS OF THE OPERATION *** */
52 - /* Override these with functional things in subclasses */
53 -
54 - /**
55 - * Get an item with the given key. Returns false if it does not exist.
56 - * @param $key string
57 - */
58 - abstract public function get( $key );
59 -
60 - /**
61 - * Set an item.
62 - * @param $key string
63 - * @param $value mixed
64 - * @param $exptime int Either an interval in seconds or a unix timestamp for expiry
65 - */
66 - abstract public function set( $key, $value, $exptime = 0 );
67 -
68 - /*
69 - * Delete an item.
70 - * @param $key string
71 - * @param $time int Amount of time to delay the operation (mostly memcached-specific)
72 - */
73 - abstract public function delete( $key, $time = 0 );
74 -
75 - public function lock( $key, $timeout = 0 ) {
76 - /* stub */
77 - return true;
78 - }
79 -
80 - public function unlock( $key ) {
81 - /* stub */
82 - return true;
83 - }
84 -
85 - public function keys() {
86 - /* stub */
87 - return array();
88 - }
89 -
90 - /* *** Emulated functions *** */
91 - /* Better performance can likely be got with custom written versions */
92 - public function get_multi( $keys ) {
93 - $out = array();
94 -
95 - foreach ( $keys as $key ) {
96 - $out[$key] = $this->get( $key );
97 - }
98 -
99 - return $out;
100 - }
101 -
102 - public function set_multi( $hash, $exptime = 0 ) {
103 - foreach ( $hash as $key => $value ) {
104 - $this->set( $key, $value, $exptime );
105 - }
106 - }
107 -
108 - public function add( $key, $value, $exptime = 0 ) {
109 - if ( !$this->get( $key ) ) {
110 - $this->set( $key, $value, $exptime );
111 -
112 - return true;
113 - }
114 - }
115 -
116 - public function add_multi( $hash, $exptime = 0 ) {
117 - foreach ( $hash as $key => $value ) {
118 - $this->add( $key, $value, $exptime );
119 - }
120 - }
121 -
122 - public function delete_multi( $keys, $time = 0 ) {
123 - foreach ( $keys as $key ) {
124 - $this->delete( $key, $time );
125 - }
126 - }
127 -
128 - public function replace( $key, $value, $exptime = 0 ) {
129 - if ( $this->get( $key ) !== false ) {
130 - $this->set( $key, $value, $exptime );
131 - }
132 - }
133 -
134 - /**
135 - * @param $key String: Key to increase
136 - * @param $value Integer: Value to add to $key (Default 1)
137 - * @return null if lock is not possible else $key value increased by $value
138 - */
139 - public function incr( $key, $value = 1 ) {
140 - if ( !$this->lock( $key ) ) {
141 - return null;
142 - }
143 -
144 - $value = intval( $value );
145 -
146 - if ( ( $n = $this->get( $key ) ) !== false ) {
147 - $n += $value;
148 - $this->set( $key, $n ); // exptime?
149 - }
150 - $this->unlock( $key );
151 -
152 - return $n;
153 - }
154 -
155 - public function decr( $key, $value = 1 ) {
156 - return $this->incr( $key, - $value );
157 - }
158 -
159 - public function debug( $text ) {
160 - if ( $this->debugMode ) {
161 - wfDebug( "BagOStuff debug: $text\n" );
162 - }
163 - }
164 -
165 - /**
166 - * Convert an optionally relative time to an absolute time
167 - */
168 - protected function convertExpiry( $exptime ) {
169 - if ( ( $exptime != 0 ) && ( $exptime < 86400 * 3650 /* 10 years */ ) ) {
170 - return time() + $exptime;
171 - } else {
172 - return $exptime;
173 - }
174 - }
175 -}
176 -
177 -/**
178 - * Functional versions!
179 - * This is a test of the interface, mainly. It stores things in an associative
180 - * array, which is not going to persist between program runs.
181 - *
182 - * @ingroup Cache
183 - */
184 -class HashBagOStuff extends BagOStuff {
185 - var $bag;
186 -
187 - function __construct() {
188 - $this->bag = array();
189 - }
190 -
191 - protected function expire( $key ) {
192 - $et = $this->bag[$key][1];
193 -
194 - if ( ( $et == 0 ) || ( $et > time() ) ) {
195 - return false;
196 - }
197 -
198 - $this->delete( $key );
199 -
200 - return true;
201 - }
202 -
203 - function get( $key ) {
204 - if ( !isset( $this->bag[$key] ) ) {
205 - return false;
206 - }
207 -
208 - if ( $this->expire( $key ) ) {
209 - return false;
210 - }
211 -
212 - return $this->bag[$key][0];
213 - }
214 -
215 - function set( $key, $value, $exptime = 0 ) {
216 - $this->bag[$key] = array( $value, $this->convertExpiry( $exptime ) );
217 - }
218 -
219 - function delete( $key, $time = 0 ) {
220 - if ( !isset( $this->bag[$key] ) ) {
221 - return false;
222 - }
223 -
224 - unset( $this->bag[$key] );
225 -
226 - return true;
227 - }
228 -
229 - function keys() {
230 - return array_keys( $this->bag );
231 - }
232 -}
233 -
234 -/**
235 - * Class to store objects in the database
236 - *
237 - * @ingroup Cache
238 - */
239 -class SqlBagOStuff extends BagOStuff {
240 - var $lb, $db;
241 - var $lastExpireAll = 0;
242 -
243 - protected function getDB() {
244 - if ( !isset( $this->db ) ) {
245 - /* We must keep a separate connection to MySQL in order to avoid deadlocks
246 - * However, SQLite has an opposite behaviour.
247 - * @todo Investigate behaviour for other databases
248 - */
249 - if ( wfGetDB( DB_MASTER )->getType() == 'sqlite' ) {
250 - $this->db = wfGetDB( DB_MASTER );
251 - } else {
252 - $this->lb = wfGetLBFactory()->newMainLB();
253 - $this->db = $this->lb->getConnection( DB_MASTER );
254 - $this->db->clearFlag( DBO_TRX );
255 - }
256 - }
257 -
258 - return $this->db;
259 - }
260 -
261 - public function get( $key ) {
262 - # expire old entries if any
263 - $this->garbageCollect();
264 - $db = $this->getDB();
265 - $row = $db->selectRow( 'objectcache', array( 'value', 'exptime' ),
266 - array( 'keyname' => $key ), __METHOD__ );
267 -
268 - if ( !$row ) {
269 - $this->debug( 'get: no matching rows' );
270 - return false;
271 - }
272 -
273 - $this->debug( "get: retrieved data; expiry time is " . $row->exptime );
274 -
275 - if ( $this->isExpired( $row->exptime ) ) {
276 - $this->debug( "get: key has expired, deleting" );
277 - try {
278 - $db->begin();
279 - # Put the expiry time in the WHERE condition to avoid deleting a
280 - # newly-inserted value
281 - $db->delete( 'objectcache',
282 - array(
283 - 'keyname' => $key,
284 - 'exptime' => $row->exptime
285 - ), __METHOD__ );
286 - $db->commit();
287 - } catch ( DBQueryError $e ) {
288 - $this->handleWriteError( $e );
289 - }
290 -
291 - return false;
292 - }
293 -
294 - return $this->unserialize( $db->decodeBlob( $row->value ) );
295 - }
296 -
297 - public function set( $key, $value, $exptime = 0 ) {
298 - $db = $this->getDB();
299 - $exptime = intval( $exptime );
300 -
301 - if ( $exptime < 0 ) {
302 - $exptime = 0;
303 - }
304 -
305 - if ( $exptime == 0 ) {
306 - $encExpiry = $this->getMaxDateTime();
307 - } else {
308 - if ( $exptime < 3.16e8 ) { # ~10 years
309 - $exptime += time();
310 - }
311 -
312 - $encExpiry = $db->timestamp( $exptime );
313 - }
314 - try {
315 - $db->begin();
316 - // (bug 24425) use a replace if the db supports it instead of
317 - // delete/insert to avoid clashes with conflicting keynames
318 - $db->replace( 'objectcache', array( 'keyname' ),
319 - array(
320 - 'keyname' => $key,
321 - 'value' => $db->encodeBlob( $this->serialize( $value ) ),
322 - 'exptime' => $encExpiry
323 - ), __METHOD__ );
324 - $db->commit();
325 - } catch ( DBQueryError $e ) {
326 - $this->handleWriteError( $e );
327 -
328 - return false;
329 - }
330 -
331 - return true;
332 - }
333 -
334 - public function delete( $key, $time = 0 ) {
335 - $db = $this->getDB();
336 -
337 - try {
338 - $db->begin();
339 - $db->delete( 'objectcache', array( 'keyname' => $key ), __METHOD__ );
340 - $db->commit();
341 - } catch ( DBQueryError $e ) {
342 - $this->handleWriteError( $e );
343 -
344 - return false;
345 - }
346 -
347 - return true;
348 - }
349 -
350 - public function incr( $key, $step = 1 ) {
351 - $db = $this->getDB();
352 - $step = intval( $step );
353 -
354 - try {
355 - $db->begin();
356 - $row = $db->selectRow( 'objectcache', array( 'value', 'exptime' ),
357 - array( 'keyname' => $key ), __METHOD__, array( 'FOR UPDATE' ) );
358 - if ( $row === false ) {
359 - // Missing
360 - $db->commit();
361 -
362 - return null;
363 - }
364 - $db->delete( 'objectcache', array( 'keyname' => $key ), __METHOD__ );
365 - if ( $this->isExpired( $row->exptime ) ) {
366 - // Expired, do not reinsert
367 - $db->commit();
368 -
369 - return null;
370 - }
371 -
372 - $oldValue = intval( $this->unserialize( $db->decodeBlob( $row->value ) ) );
373 - $newValue = $oldValue + $step;
374 - $db->insert( 'objectcache',
375 - array(
376 - 'keyname' => $key,
377 - 'value' => $db->encodeBlob( $this->serialize( $newValue ) ),
378 - 'exptime' => $row->exptime
379 - ), __METHOD__ );
380 - $db->commit();
381 - } catch ( DBQueryError $e ) {
382 - $this->handleWriteError( $e );
383 -
384 - return null;
385 - }
386 -
387 - return $newValue;
388 - }
389 -
390 - public function keys() {
391 - $db = $this->getDB();
392 - $res = $db->select( 'objectcache', array( 'keyname' ), false, __METHOD__ );
393 - $result = array();
394 -
395 - foreach ( $res as $row ) {
396 - $result[] = $row->keyname;
397 - }
398 -
399 - return $result;
400 - }
401 -
402 - protected function isExpired( $exptime ) {
403 - return $exptime != $this->getMaxDateTime() && wfTimestamp( TS_UNIX, $exptime ) < time();
404 - }
405 -
406 - protected function getMaxDateTime() {
407 - if ( time() > 0x7fffffff ) {
408 - return $this->getDB()->timestamp( 1 << 62 );
409 - } else {
410 - return $this->getDB()->timestamp( 0x7fffffff );
411 - }
412 - }
413 -
414 - protected function garbageCollect() {
415 - /* Ignore 99% of requests */
416 - if ( !mt_rand( 0, 100 ) ) {
417 - $now = time();
418 - /* Avoid repeating the delete within a few seconds */
419 - if ( $now > ( $this->lastExpireAll + 1 ) ) {
420 - $this->lastExpireAll = $now;
421 - $this->expireAll();
422 - }
423 - }
424 - }
425 -
426 - public function expireAll() {
427 - $db = $this->getDB();
428 - $now = $db->timestamp();
429 -
430 - try {
431 - $db->begin();
432 - $db->delete( 'objectcache', array( 'exptime < ' . $db->addQuotes( $now ) ), __METHOD__ );
433 - $db->commit();
434 - } catch ( DBQueryError $e ) {
435 - $this->handleWriteError( $e );
436 - }
437 - }
438 -
439 - public function deleteAll() {
440 - $db = $this->getDB();
441 -
442 - try {
443 - $db->begin();
444 - $db->delete( 'objectcache', '*', __METHOD__ );
445 - $db->commit();
446 - } catch ( DBQueryError $e ) {
447 - $this->handleWriteError( $e );
448 - }
449 - }
450 -
451 - /**
452 - * Serialize an object and, if possible, compress the representation.
453 - * On typical message and page data, this can provide a 3X decrease
454 - * in storage requirements.
455 - *
456 - * @param $data mixed
457 - * @return string
458 - */
459 - protected function serialize( &$data ) {
460 - $serial = serialize( $data );
461 -
462 - if ( function_exists( 'gzdeflate' ) ) {
463 - return gzdeflate( $serial );
464 - } else {
465 - return $serial;
466 - }
467 - }
468 -
469 - /**
470 - * Unserialize and, if necessary, decompress an object.
471 - * @param $serial string
472 - * @return mixed
473 - */
474 - protected function unserialize( $serial ) {
475 - if ( function_exists( 'gzinflate' ) ) {
476 - $decomp = @gzinflate( $serial );
477 -
478 - if ( false !== $decomp ) {
479 - $serial = $decomp;
480 - }
481 - }
482 -
483 - $ret = unserialize( $serial );
484 -
485 - return $ret;
486 - }
487 -
488 - /**
489 - * Handle a DBQueryError which occurred during a write operation.
490 - * Ignore errors which are due to a read-only database, rethrow others.
491 - */
492 - protected function handleWriteError( $exception ) {
493 - $db = $this->getDB();
494 -
495 - if ( !$db->wasReadOnlyError() ) {
496 - throw $exception;
497 - }
498 -
499 - try {
500 - $db->rollback();
501 - } catch ( DBQueryError $e ) {
502 - }
503 -
504 - wfDebug( __METHOD__ . ": ignoring query error\n" );
505 - $db->ignoreErrors( false );
506 - }
507 -}
508 -
509 -/**
510 - * Backwards compatibility alias
511 - */
512 -class MediaWikiBagOStuff extends SqlBagOStuff { }
513 -
514 -/**
515 - * This is a wrapper for APC's shared memory functions
516 - *
517 - * @ingroup Cache
518 - */
519 -class APCBagOStuff extends BagOStuff {
520 - public function get( $key ) {
521 - $val = apc_fetch( $key );
522 -
523 - if ( is_string( $val ) ) {
524 - $val = unserialize( $val );
525 - }
526 -
527 - return $val;
528 - }
529 -
530 - public function set( $key, $value, $exptime = 0 ) {
531 - apc_store( $key, serialize( $value ), $exptime );
532 -
533 - return true;
534 - }
535 -
536 - public function delete( $key, $time = 0 ) {
537 - apc_delete( $key );
538 -
539 - return true;
540 - }
541 -
542 - public function keys() {
543 - $info = apc_cache_info( 'user' );
544 - $list = $info['cache_list'];
545 - $keys = array();
546 -
547 - foreach ( $list as $entry ) {
548 - $keys[] = $entry['info'];
549 - }
550 -
551 - return $keys;
552 - }
553 -}
554 -
555 -/**
556 - * This is a wrapper for eAccelerator's shared memory functions.
557 - *
558 - * This is basically identical to the deceased Turck MMCache version,
559 - * mostly because eAccelerator is based on Turck MMCache.
560 - *
561 - * @ingroup Cache
562 - */
563 -class eAccelBagOStuff extends BagOStuff {
564 - public function get( $key ) {
565 - $val = eaccelerator_get( $key );
566 -
567 - if ( is_string( $val ) ) {
568 - $val = unserialize( $val );
569 - }
570 -
571 - return $val;
572 - }
573 -
574 - public function set( $key, $value, $exptime = 0 ) {
575 - eaccelerator_put( $key, serialize( $value ), $exptime );
576 -
577 - return true;
578 - }
579 -
580 - public function delete( $key, $time = 0 ) {
581 - eaccelerator_rm( $key );
582 -
583 - return true;
584 - }
585 -
586 - public function lock( $key, $waitTimeout = 0 ) {
587 - eaccelerator_lock( $key );
588 -
589 - return true;
590 - }
591 -
592 - public function unlock( $key ) {
593 - eaccelerator_unlock( $key );
594 -
595 - return true;
596 - }
597 -}
598 -
599 -/**
600 - * Wrapper for XCache object caching functions; identical interface
601 - * to the APC wrapper
602 - *
603 - * @ingroup Cache
604 - */
605 -class XCacheBagOStuff extends BagOStuff {
606 - /**
607 - * Get a value from the XCache object cache
608 - *
609 - * @param $key String: cache key
610 - * @return mixed
611 - */
612 - public function get( $key ) {
613 - $val = xcache_get( $key );
614 -
615 - if ( is_string( $val ) ) {
616 - $val = unserialize( $val );
617 - }
618 -
619 - return $val;
620 - }
621 -
622 - /**
623 - * Store a value in the XCache object cache
624 - *
625 - * @param $key String: cache key
626 - * @param $value Mixed: object to store
627 - * @param $expire Int: expiration time
628 - * @return bool
629 - */
630 - public function set( $key, $value, $expire = 0 ) {
631 - xcache_set( $key, serialize( $value ), $expire );
632 -
633 - return true;
634 - }
635 -
636 - /**
637 - * Remove a value from the XCache object cache
638 - *
639 - * @param $key String: cache key
640 - * @param $time Int: not used in this implementation
641 - * @return bool
642 - */
643 - public function delete( $key, $time = 0 ) {
644 - xcache_unset( $key );
645 -
646 - return true;
647 - }
648 -}
649 -
650 -/**
651 - * Cache that uses DBA as a backend.
652 - * Slow due to the need to constantly open and close the file to avoid holding
653 - * writer locks. Intended for development use only, as a memcached workalike
654 - * for systems that don't have it.
655 - *
656 - * @ingroup Cache
657 - */
658 -class DBABagOStuff extends BagOStuff {
659 - var $mHandler, $mFile, $mReader, $mWriter, $mDisabled;
660 -
661 - public function __construct( $dir = false ) {
662 - global $wgDBAhandler;
663 -
664 - if ( $dir === false ) {
665 - global $wgTmpDirectory;
666 - $dir = $wgTmpDirectory;
667 - }
668 -
669 - $this->mFile = "$dir/mw-cache-" . wfWikiID();
670 - $this->mFile .= '.db';
671 - wfDebug( __CLASS__ . ": using cache file {$this->mFile}\n" );
672 - $this->mHandler = $wgDBAhandler;
673 - }
674 -
675 - /**
676 - * Encode value and expiry for storage
677 - */
678 - function encode( $value, $expiry ) {
679 - # Convert to absolute time
680 - $expiry = $this->convertExpiry( $expiry );
681 -
682 - return sprintf( '%010u', intval( $expiry ) ) . ' ' . serialize( $value );
683 - }
684 -
685 - /**
686 - * @return list containing value first and expiry second
687 - */
688 - function decode( $blob ) {
689 - if ( !is_string( $blob ) ) {
690 - return array( null, 0 );
691 - } else {
692 - return array(
693 - unserialize( substr( $blob, 11 ) ),
694 - intval( substr( $blob, 0, 10 ) )
695 - );
696 - }
697 - }
698 -
699 - function getReader() {
700 - if ( file_exists( $this->mFile ) ) {
701 - $handle = dba_open( $this->mFile, 'rl', $this->mHandler );
702 - } else {
703 - $handle = $this->getWriter();
704 - }
705 -
706 - if ( !$handle ) {
707 - wfDebug( "Unable to open DBA cache file {$this->mFile}\n" );
708 - }
709 -
710 - return $handle;
711 - }
712 -
713 - function getWriter() {
714 - $handle = dba_open( $this->mFile, 'cl', $this->mHandler );
715 -
716 - if ( !$handle ) {
717 - wfDebug( "Unable to open DBA cache file {$this->mFile}\n" );
718 - }
719 -
720 - return $handle;
721 - }
722 -
723 - function get( $key ) {
724 - wfProfileIn( __METHOD__ );
725 - wfDebug( __METHOD__ . "($key)\n" );
726 -
727 - $handle = $this->getReader();
728 - if ( !$handle ) {
729 - wfProfileOut( __METHOD__ );
730 - return null;
731 - }
732 -
733 - $val = dba_fetch( $key, $handle );
734 - list( $val, $expiry ) = $this->decode( $val );
735 -
736 - # Must close ASAP because locks are held
737 - dba_close( $handle );
738 -
739 - if ( !is_null( $val ) && $expiry && $expiry < time() ) {
740 - # Key is expired, delete it
741 - $handle = $this->getWriter();
742 - dba_delete( $key, $handle );
743 - dba_close( $handle );
744 - wfDebug( __METHOD__ . ": $key expired\n" );
745 - $val = null;
746 - }
747 -
748 - wfProfileOut( __METHOD__ );
749 - return $val;
750 - }
751 -
752 - function set( $key, $value, $exptime = 0 ) {
753 - wfProfileIn( __METHOD__ );
754 - wfDebug( __METHOD__ . "($key)\n" );
755 -
756 - $blob = $this->encode( $value, $exptime );
757 -
758 - $handle = $this->getWriter();
759 - if ( !$handle ) {
760 - wfProfileOut( __METHOD__ );
761 - return false;
762 - }
763 -
764 - $ret = dba_replace( $key, $blob, $handle );
765 - dba_close( $handle );
766 -
767 - wfProfileOut( __METHOD__ );
768 - return $ret;
769 - }
770 -
771 - function delete( $key, $time = 0 ) {
772 - wfProfileIn( __METHOD__ );
773 - wfDebug( __METHOD__ . "($key)\n" );
774 -
775 - $handle = $this->getWriter();
776 - if ( !$handle ) {
777 - wfProfileOut( __METHOD__ );
778 - return false;
779 - }
780 -
781 - $ret = dba_delete( $key, $handle );
782 - dba_close( $handle );
783 -
784 - wfProfileOut( __METHOD__ );
785 - return $ret;
786 - }
787 -
788 - function add( $key, $value, $exptime = 0 ) {
789 - wfProfileIn( __METHOD__ );
790 -
791 - $blob = $this->encode( $value, $exptime );
792 -
793 - $handle = $this->getWriter();
794 -
795 - if ( !$handle ) {
796 - wfProfileOut( __METHOD__ );
797 - return false;
798 - }
799 -
800 - $ret = dba_insert( $key, $blob, $handle );
801 -
802 - # Insert failed, check to see if it failed due to an expired key
803 - if ( !$ret ) {
804 - list( $value, $expiry ) = $this->decode( dba_fetch( $key, $handle ) );
805 -
806 - if ( $expiry < time() ) {
807 - # Yes expired, delete and try again
808 - dba_delete( $key, $handle );
809 - $ret = dba_insert( $key, $blob, $handle );
810 - # This time if it failed then it will be handled by the caller like any other race
811 - }
812 - }
813 -
814 - dba_close( $handle );
815 -
816 - wfProfileOut( __METHOD__ );
817 - return $ret;
818 - }
819 -
820 - function keys() {
821 - $reader = $this->getReader();
822 - $k1 = dba_firstkey( $reader );
823 -
824 - if ( !$k1 ) {
825 - return array();
826 - }
827 -
828 - $result[] = $k1;
829 -
830 - while ( $key = dba_nextkey( $reader ) ) {
831 - $result[] = $key;
832 - }
833 -
834 - return $result;
835 - }
836 -}
837 -
838 -/**
839 - * Wrapper for WinCache object caching functions; identical interface
840 - * to the APC wrapper
841 - *
842 - * @ingroup Cache
843 - */
844 -class WinCacheBagOStuff extends BagOStuff {
845 -
846 - /**
847 - * Get a value from the WinCache object cache
848 - *
849 - * @param $key String: cache key
850 - * @return mixed
851 - */
852 - public function get( $key ) {
853 - $val = wincache_ucache_get( $key );
854 -
855 - if ( is_string( $val ) ) {
856 - $val = unserialize( $val );
857 - }
858 -
859 - return $val;
860 - }
861 -
862 - /**
863 - * Store a value in the WinCache object cache
864 - *
865 - * @param $key String: cache key
866 - * @param $value Mixed: object to store
867 - * @param $expire Int: expiration time
868 - * @return bool
869 - */
870 - public function set( $key, $value, $expire = 0 ) {
871 - $result = wincache_ucache_set( $key, serialize( $value ), $expire );
872 -
873 - /* wincache_ucache_set returns an empty array on success if $value
874 - was an array, bool otherwise */
875 - return ( is_array( $result ) && $result === array() ) || $result;
876 - }
877 -
878 - /**
879 - * Remove a value from the WinCache object cache
880 - *
881 - * @param $key String: cache key
882 - * @param $time Int: not used in this implementation
883 - * @return bool
884 - */
885 - public function delete( $key, $time = 0 ) {
886 - wincache_ucache_delete( $key );
887 -
888 - return true;
889 - }
890 -
891 - public function keys() {
892 - $info = wincache_ucache_info();
893 - $list = $info['ucache_entries'];
894 - $keys = array();
895 -
896 - if ( is_null( $list ) ) {
897 - return array();
898 - }
899 -
900 - foreach ( $list as $entry ) {
901 - $keys[] = $entry['key_name'];
902 - }
903 -
904 - return $keys;
905 - }
906 -}
Index: trunk/phase3/includes/ObjectCache.php
@@ -1,125 +0,0 @@
2 -<?php
3 -/**
4 - * Functions to get cache objects
5 - *
6 - * @file
7 - * @ingroup Cache
8 - */
9 -
10 -/**
11 - * FakeMemCachedClient imitates the API of memcached-client v. 0.1.2.
12 - * It acts as a memcached server with no RAM, that is, all objects are
13 - * cleared the moment they are set. All set operations succeed and all
14 - * get operations return null.
15 - * @ingroup Cache
16 - */
17 -class FakeMemCachedClient {
18 - function add ($key, $val, $exp = 0) { return true; }
19 - function decr ($key, $amt=1) { return null; }
20 - function delete ($key, $time = 0) { return false; }
21 - function disconnect_all () { }
22 - function enable_compress ($enable) { }
23 - function forget_dead_hosts () { }
24 - function get ($key) { return null; }
25 - function get_multi ($keys) { return array_pad(array(), count($keys), null); }
26 - function incr ($key, $amt=1) { return null; }
27 - function replace ($key, $value, $exp=0) { return false; }
28 - function run_command ($sock, $cmd) { return null; }
29 - function set ($key, $value, $exp=0){ return true; }
30 - function set_compress_threshold ($thresh){ }
31 - function set_debug ($dbg) { }
32 - function set_servers ($list) { }
33 -}
34 -
35 -global $wgCaches;
36 -$wgCaches = array();
37 -
38 -/**
39 - * Get a cache object.
40 - * @param $inputType Integer: cache type, one the the CACHE_* constants.
41 - *
42 - * @return BagOStuff
43 - */
44 -function &wfGetCache( $inputType ) {
45 - global $wgCaches, $wgMemCachedServers, $wgMemCachedDebug, $wgMemCachedPersistent;
46 - $cache = false;
47 -
48 - if ( $inputType == CACHE_ANYTHING ) {
49 - reset( $wgCaches );
50 - $type = key( $wgCaches );
51 - if ( $type === false || $type === CACHE_NONE ) {
52 - $type = CACHE_DB;
53 - }
54 - } else {
55 - $type = $inputType;
56 - }
57 -
58 - if ( $type == CACHE_MEMCACHED ) {
59 - if ( !array_key_exists( CACHE_MEMCACHED, $wgCaches ) ) {
60 - $wgCaches[CACHE_MEMCACHED] = new MemCachedClientforWiki(
61 - array('persistant' => $wgMemCachedPersistent, 'compress_threshold' => 1500 ) );
62 - $wgCaches[CACHE_MEMCACHED]->set_servers( $wgMemCachedServers );
63 - $wgCaches[CACHE_MEMCACHED]->set_debug( $wgMemCachedDebug );
64 - }
65 - $cache =& $wgCaches[CACHE_MEMCACHED];
66 - } elseif ( $type == CACHE_ACCEL ) {
67 - if ( !array_key_exists( CACHE_ACCEL, $wgCaches ) ) {
68 - if ( function_exists( 'eaccelerator_get' ) ) {
69 - $wgCaches[CACHE_ACCEL] = new eAccelBagOStuff;
70 - } elseif ( function_exists( 'apc_fetch') ) {
71 - $wgCaches[CACHE_ACCEL] = new APCBagOStuff;
72 - } elseif( function_exists( 'xcache_get' ) ) {
73 - $wgCaches[CACHE_ACCEL] = new XCacheBagOStuff();
74 - } elseif( function_exists( 'wincache_ucache_get' ) ) {
75 - $wgCaches[CACHE_ACCEL] = new WinCacheBagOStuff();
76 - } else {
77 - $wgCaches[CACHE_ACCEL] = false;
78 - }
79 - }
80 - if ( $wgCaches[CACHE_ACCEL] !== false ) {
81 - $cache =& $wgCaches[CACHE_ACCEL];
82 - }
83 - } elseif ( $type == CACHE_DBA ) {
84 - if ( !array_key_exists( CACHE_DBA, $wgCaches ) ) {
85 - $wgCaches[CACHE_DBA] = new DBABagOStuff;
86 - }
87 - $cache =& $wgCaches[CACHE_DBA];
88 - }
89 -
90 - if ( $type == CACHE_DB || ( $inputType == CACHE_ANYTHING && $cache === false ) ) {
91 - if ( !array_key_exists( CACHE_DB, $wgCaches ) ) {
92 - $wgCaches[CACHE_DB] = new SqlBagOStuff('objectcache');
93 - }
94 - $cache =& $wgCaches[CACHE_DB];
95 - }
96 -
97 - if ( $cache === false ) {
98 - if ( !array_key_exists( CACHE_NONE, $wgCaches ) ) {
99 - $wgCaches[CACHE_NONE] = new FakeMemCachedClient;
100 - }
101 - $cache =& $wgCaches[CACHE_NONE];
102 - }
103 -
104 - return $cache;
105 -}
106 -
107 -/** Get the main cache object */
108 -function &wfGetMainCache() {
109 - global $wgMainCacheType;
110 - $ret =& wfGetCache( $wgMainCacheType );
111 - return $ret;
112 -}
113 -
114 -/** Get the cache object used by the message cache */
115 -function &wfGetMessageCacheStorage() {
116 - global $wgMessageCacheType;
117 - $ret =& wfGetCache( $wgMessageCacheType );
118 - return $ret;
119 -}
120 -
121 -/** Get the cache object used by the parser cache */
122 -function &wfGetParserCacheStorage() {
123 - global $wgParserCacheType;
124 - $ret =& wfGetCache( $wgParserCacheType );
125 - return $ret;
126 -}
Index: trunk/phase3/includes/objectcache/ObjectCache.php
@@ -0,0 +1,125 @@
 2+<?php
 3+/**
 4+ * Functions to get cache objects
 5+ *
 6+ * @file
 7+ * @ingroup Cache
 8+ */
 9+
 10+/**
 11+ * FakeMemCachedClient imitates the API of memcached-client v. 0.1.2.
 12+ * It acts as a memcached server with no RAM, that is, all objects are
 13+ * cleared the moment they are set. All set operations succeed and all
 14+ * get operations return null.
 15+ * @ingroup Cache
 16+ */
 17+class FakeMemCachedClient {
 18+ function add ($key, $val, $exp = 0) { return true; }
 19+ function decr ($key, $amt=1) { return null; }
 20+ function delete ($key, $time = 0) { return false; }
 21+ function disconnect_all () { }
 22+ function enable_compress ($enable) { }
 23+ function forget_dead_hosts () { }
 24+ function get ($key) { return null; }
 25+ function get_multi ($keys) { return array_pad(array(), count($keys), null); }
 26+ function incr ($key, $amt=1) { return null; }
 27+ function replace ($key, $value, $exp=0) { return false; }
 28+ function run_command ($sock, $cmd) { return null; }
 29+ function set ($key, $value, $exp=0){ return true; }
 30+ function set_compress_threshold ($thresh){ }
 31+ function set_debug ($dbg) { }
 32+ function set_servers ($list) { }
 33+}
 34+
 35+global $wgCaches;
 36+$wgCaches = array();
 37+
 38+/**
 39+ * Get a cache object.
 40+ * @param $inputType Integer: cache type, one the the CACHE_* constants.
 41+ *
 42+ * @return BagOStuff
 43+ */
 44+function &wfGetCache( $inputType ) {
 45+ global $wgCaches, $wgMemCachedServers, $wgMemCachedDebug, $wgMemCachedPersistent;
 46+ $cache = false;
 47+
 48+ if ( $inputType == CACHE_ANYTHING ) {
 49+ reset( $wgCaches );
 50+ $type = key( $wgCaches );
 51+ if ( $type === false || $type === CACHE_NONE ) {
 52+ $type = CACHE_DB;
 53+ }
 54+ } else {
 55+ $type = $inputType;
 56+ }
 57+
 58+ if ( $type == CACHE_MEMCACHED ) {
 59+ if ( !array_key_exists( CACHE_MEMCACHED, $wgCaches ) ) {
 60+ $wgCaches[CACHE_MEMCACHED] = new MemCachedClientforWiki(
 61+ array('persistant' => $wgMemCachedPersistent, 'compress_threshold' => 1500 ) );
 62+ $wgCaches[CACHE_MEMCACHED]->set_servers( $wgMemCachedServers );
 63+ $wgCaches[CACHE_MEMCACHED]->set_debug( $wgMemCachedDebug );
 64+ }
 65+ $cache =& $wgCaches[CACHE_MEMCACHED];
 66+ } elseif ( $type == CACHE_ACCEL ) {
 67+ if ( !array_key_exists( CACHE_ACCEL, $wgCaches ) ) {
 68+ if ( function_exists( 'eaccelerator_get' ) ) {
 69+ $wgCaches[CACHE_ACCEL] = new eAccelBagOStuff;
 70+ } elseif ( function_exists( 'apc_fetch') ) {
 71+ $wgCaches[CACHE_ACCEL] = new APCBagOStuff;
 72+ } elseif( function_exists( 'xcache_get' ) ) {
 73+ $wgCaches[CACHE_ACCEL] = new XCacheBagOStuff();
 74+ } elseif( function_exists( 'wincache_ucache_get' ) ) {
 75+ $wgCaches[CACHE_ACCEL] = new WinCacheBagOStuff();
 76+ } else {
 77+ $wgCaches[CACHE_ACCEL] = false;
 78+ }
 79+ }
 80+ if ( $wgCaches[CACHE_ACCEL] !== false ) {
 81+ $cache =& $wgCaches[CACHE_ACCEL];
 82+ }
 83+ } elseif ( $type == CACHE_DBA ) {
 84+ if ( !array_key_exists( CACHE_DBA, $wgCaches ) ) {
 85+ $wgCaches[CACHE_DBA] = new DBABagOStuff;
 86+ }
 87+ $cache =& $wgCaches[CACHE_DBA];
 88+ }
 89+
 90+ if ( $type == CACHE_DB || ( $inputType == CACHE_ANYTHING && $cache === false ) ) {
 91+ if ( !array_key_exists( CACHE_DB, $wgCaches ) ) {
 92+ $wgCaches[CACHE_DB] = new SqlBagOStuff('objectcache');
 93+ }
 94+ $cache =& $wgCaches[CACHE_DB];
 95+ }
 96+
 97+ if ( $cache === false ) {
 98+ if ( !array_key_exists( CACHE_NONE, $wgCaches ) ) {
 99+ $wgCaches[CACHE_NONE] = new FakeMemCachedClient;
 100+ }
 101+ $cache =& $wgCaches[CACHE_NONE];
 102+ }
 103+
 104+ return $cache;
 105+}
 106+
 107+/** Get the main cache object */
 108+function &wfGetMainCache() {
 109+ global $wgMainCacheType;
 110+ $ret =& wfGetCache( $wgMainCacheType );
 111+ return $ret;
 112+}
 113+
 114+/** Get the cache object used by the message cache */
 115+function &wfGetMessageCacheStorage() {
 116+ global $wgMessageCacheType;
 117+ $ret =& wfGetCache( $wgMessageCacheType );
 118+ return $ret;
 119+}
 120+
 121+/** Get the cache object used by the parser cache */
 122+function &wfGetParserCacheStorage() {
 123+ global $wgParserCacheType;
 124+ $ret =& wfGetCache( $wgParserCacheType );
 125+ return $ret;
 126+}
Property changes on: trunk/phase3/includes/objectcache/ObjectCache.php
___________________________________________________________________
Added: svn:keywords
1127 + Author Date Id Revision
Added: svn:eol-style
2128 + native
Index: trunk/phase3/includes/objectcache/XCacheBagOStuff.php
@@ -0,0 +1,53 @@
 2+<?php
 3+
 4+/**
 5+ * Wrapper for XCache object caching functions; identical interface
 6+ * to the APC wrapper
 7+ *
 8+ * @ingroup Cache
 9+ */
 10+class XCacheBagOStuff extends BagOStuff {
 11+ /**
 12+ * Get a value from the XCache object cache
 13+ *
 14+ * @param $key String: cache key
 15+ * @return mixed
 16+ */
 17+ public function get( $key ) {
 18+ $val = xcache_get( $key );
 19+
 20+ if ( is_string( $val ) ) {
 21+ $val = unserialize( $val );
 22+ }
 23+
 24+ return $val;
 25+ }
 26+
 27+ /**
 28+ * Store a value in the XCache object cache
 29+ *
 30+ * @param $key String: cache key
 31+ * @param $value Mixed: object to store
 32+ * @param $expire Int: expiration time
 33+ * @return bool
 34+ */
 35+ public function set( $key, $value, $expire = 0 ) {
 36+ xcache_set( $key, serialize( $value ), $expire );
 37+
 38+ return true;
 39+ }
 40+
 41+ /**
 42+ * Remove a value from the XCache object cache
 43+ *
 44+ * @param $key String: cache key
 45+ * @param $time Int: not used in this implementation
 46+ * @return bool
 47+ */
 48+ public function delete( $key, $time = 0 ) {
 49+ xcache_unset( $key );
 50+
 51+ return true;
 52+ }
 53+}
 54+
Property changes on: trunk/phase3/includes/objectcache/XCacheBagOStuff.php
___________________________________________________________________
Added: svn:eol-style
155 + native
Index: trunk/phase3/includes/objectcache/eAccelBagOStuff.php
@@ -0,0 +1,46 @@
 2+<?php
 3+
 4+/**
 5+ * This is a wrapper for eAccelerator's shared memory functions.
 6+ *
 7+ * This is basically identical to the deceased Turck MMCache version,
 8+ * mostly because eAccelerator is based on Turck MMCache.
 9+ *
 10+ * @ingroup Cache
 11+ */
 12+class eAccelBagOStuff extends BagOStuff {
 13+ public function get( $key ) {
 14+ $val = eaccelerator_get( $key );
 15+
 16+ if ( is_string( $val ) ) {
 17+ $val = unserialize( $val );
 18+ }
 19+
 20+ return $val;
 21+ }
 22+
 23+ public function set( $key, $value, $exptime = 0 ) {
 24+ eaccelerator_put( $key, serialize( $value ), $exptime );
 25+
 26+ return true;
 27+ }
 28+
 29+ public function delete( $key, $time = 0 ) {
 30+ eaccelerator_rm( $key );
 31+
 32+ return true;
 33+ }
 34+
 35+ public function lock( $key, $waitTimeout = 0 ) {
 36+ eaccelerator_lock( $key );
 37+
 38+ return true;
 39+ }
 40+
 41+ public function unlock( $key ) {
 42+ eaccelerator_unlock( $key );
 43+
 44+ return true;
 45+ }
 46+}
 47+
Property changes on: trunk/phase3/includes/objectcache/eAccelBagOStuff.php
___________________________________________________________________
Added: svn:eol-style
148 + native
Index: trunk/phase3/includes/objectcache/BagOStuff.php
@@ -0,0 +1,176 @@
 2+<?php
 3+/**
 4+ * Classes to cache objects in PHP accelerators, SQL database or DBA files
 5+ *
 6+ * Copyright © 2003-2004 Brion Vibber <brion@pobox.com>
 7+ * http://www.mediawiki.org/
 8+ *
 9+ * This program is free software; you can redistribute it and/or modify
 10+ * it under the terms of the GNU General Public License as published by
 11+ * the Free Software Foundation; either version 2 of the License, or
 12+ * (at your option) any later version.
 13+ *
 14+ * This program is distributed in the hope that it will be useful,
 15+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 17+ * GNU General Public License for more details.
 18+ *
 19+ * You should have received a copy of the GNU General Public License along
 20+ * with this program; if not, write to the Free Software Foundation, Inc.,
 21+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 22+ * http://www.gnu.org/copyleft/gpl.html
 23+ *
 24+ * @file
 25+ * @ingroup Cache
 26+ */
 27+
 28+/**
 29+ * @defgroup Cache Cache
 30+ */
 31+
 32+/**
 33+ * interface is intended to be more or less compatible with
 34+ * the PHP memcached client.
 35+ *
 36+ * backends for local hash array and SQL table included:
 37+ * <code>
 38+ * $bag = new HashBagOStuff();
 39+ * $bag = new SqlBagOStuff(); # connect to db first
 40+ * </code>
 41+ *
 42+ * @ingroup Cache
 43+ */
 44+abstract class BagOStuff {
 45+ var $debugMode = false;
 46+
 47+ public function set_debug( $bool ) {
 48+ $this->debugMode = $bool;
 49+ }
 50+
 51+ /* *** THE GUTS OF THE OPERATION *** */
 52+ /* Override these with functional things in subclasses */
 53+
 54+ /**
 55+ * Get an item with the given key. Returns false if it does not exist.
 56+ * @param $key string
 57+ */
 58+ abstract public function get( $key );
 59+
 60+ /**
 61+ * Set an item.
 62+ * @param $key string
 63+ * @param $value mixed
 64+ * @param $exptime int Either an interval in seconds or a unix timestamp for expiry
 65+ */
 66+ abstract public function set( $key, $value, $exptime = 0 );
 67+
 68+ /*
 69+ * Delete an item.
 70+ * @param $key string
 71+ * @param $time int Amount of time to delay the operation (mostly memcached-specific)
 72+ */
 73+ abstract public function delete( $key, $time = 0 );
 74+
 75+ public function lock( $key, $timeout = 0 ) {
 76+ /* stub */
 77+ return true;
 78+ }
 79+
 80+ public function unlock( $key ) {
 81+ /* stub */
 82+ return true;
 83+ }
 84+
 85+ public function keys() {
 86+ /* stub */
 87+ return array();
 88+ }
 89+
 90+ /* *** Emulated functions *** */
 91+ /* Better performance can likely be got with custom written versions */
 92+ public function get_multi( $keys ) {
 93+ $out = array();
 94+
 95+ foreach ( $keys as $key ) {
 96+ $out[$key] = $this->get( $key );
 97+ }
 98+
 99+ return $out;
 100+ }
 101+
 102+ public function set_multi( $hash, $exptime = 0 ) {
 103+ foreach ( $hash as $key => $value ) {
 104+ $this->set( $key, $value, $exptime );
 105+ }
 106+ }
 107+
 108+ public function add( $key, $value, $exptime = 0 ) {
 109+ if ( !$this->get( $key ) ) {
 110+ $this->set( $key, $value, $exptime );
 111+
 112+ return true;
 113+ }
 114+ }
 115+
 116+ public function add_multi( $hash, $exptime = 0 ) {
 117+ foreach ( $hash as $key => $value ) {
 118+ $this->add( $key, $value, $exptime );
 119+ }
 120+ }
 121+
 122+ public function delete_multi( $keys, $time = 0 ) {
 123+ foreach ( $keys as $key ) {
 124+ $this->delete( $key, $time );
 125+ }
 126+ }
 127+
 128+ public function replace( $key, $value, $exptime = 0 ) {
 129+ if ( $this->get( $key ) !== false ) {
 130+ $this->set( $key, $value, $exptime );
 131+ }
 132+ }
 133+
 134+ /**
 135+ * @param $key String: Key to increase
 136+ * @param $value Integer: Value to add to $key (Default 1)
 137+ * @return null if lock is not possible else $key value increased by $value
 138+ */
 139+ public function incr( $key, $value = 1 ) {
 140+ if ( !$this->lock( $key ) ) {
 141+ return null;
 142+ }
 143+
 144+ $value = intval( $value );
 145+
 146+ if ( ( $n = $this->get( $key ) ) !== false ) {
 147+ $n += $value;
 148+ $this->set( $key, $n ); // exptime?
 149+ }
 150+ $this->unlock( $key );
 151+
 152+ return $n;
 153+ }
 154+
 155+ public function decr( $key, $value = 1 ) {
 156+ return $this->incr( $key, - $value );
 157+ }
 158+
 159+ public function debug( $text ) {
 160+ if ( $this->debugMode ) {
 161+ wfDebug( "BagOStuff debug: $text\n" );
 162+ }
 163+ }
 164+
 165+ /**
 166+ * Convert an optionally relative time to an absolute time
 167+ */
 168+ protected function convertExpiry( $exptime ) {
 169+ if ( ( $exptime != 0 ) && ( $exptime < 86400 * 3650 /* 10 years */ ) ) {
 170+ return time() + $exptime;
 171+ } else {
 172+ return $exptime;
 173+ }
 174+ }
 175+}
 176+
 177+
Property changes on: trunk/phase3/includes/objectcache/BagOStuff.php
___________________________________________________________________
Added: svn:keywords
1178 + Author Date Id Revision
Added: svn:eol-style
2179 + native
Index: trunk/phase3/includes/objectcache/SqlBagOStuff.php
@@ -0,0 +1,282 @@
 2+<?php
 3+
 4+/**
 5+ * Class to store objects in the database
 6+ *
 7+ * @ingroup Cache
 8+ */
 9+class SqlBagOStuff extends BagOStuff {
 10+ var $lb, $db;
 11+ var $lastExpireAll = 0;
 12+
 13+ protected function getDB() {
 14+ if ( !isset( $this->db ) ) {
 15+ /* We must keep a separate connection to MySQL in order to avoid deadlocks
 16+ * However, SQLite has an opposite behaviour.
 17+ * @todo Investigate behaviour for other databases
 18+ */
 19+ if ( wfGetDB( DB_MASTER )->getType() == 'sqlite' ) {
 20+ $this->db = wfGetDB( DB_MASTER );
 21+ } else {
 22+ $this->lb = wfGetLBFactory()->newMainLB();
 23+ $this->db = $this->lb->getConnection( DB_MASTER );
 24+ $this->db->clearFlag( DBO_TRX );
 25+ }
 26+ }
 27+
 28+ return $this->db;
 29+ }
 30+
 31+ public function get( $key ) {
 32+ # expire old entries if any
 33+ $this->garbageCollect();
 34+ $db = $this->getDB();
 35+ $row = $db->selectRow( 'objectcache', array( 'value', 'exptime' ),
 36+ array( 'keyname' => $key ), __METHOD__ );
 37+
 38+ if ( !$row ) {
 39+ $this->debug( 'get: no matching rows' );
 40+ return false;
 41+ }
 42+
 43+ $this->debug( "get: retrieved data; expiry time is " . $row->exptime );
 44+
 45+ if ( $this->isExpired( $row->exptime ) ) {
 46+ $this->debug( "get: key has expired, deleting" );
 47+ try {
 48+ $db->begin();
 49+ # Put the expiry time in the WHERE condition to avoid deleting a
 50+ # newly-inserted value
 51+ $db->delete( 'objectcache',
 52+ array(
 53+ 'keyname' => $key,
 54+ 'exptime' => $row->exptime
 55+ ), __METHOD__ );
 56+ $db->commit();
 57+ } catch ( DBQueryError $e ) {
 58+ $this->handleWriteError( $e );
 59+ }
 60+
 61+ return false;
 62+ }
 63+
 64+ return $this->unserialize( $db->decodeBlob( $row->value ) );
 65+ }
 66+
 67+ public function set( $key, $value, $exptime = 0 ) {
 68+ $db = $this->getDB();
 69+ $exptime = intval( $exptime );
 70+
 71+ if ( $exptime < 0 ) {
 72+ $exptime = 0;
 73+ }
 74+
 75+ if ( $exptime == 0 ) {
 76+ $encExpiry = $this->getMaxDateTime();
 77+ } else {
 78+ if ( $exptime < 3.16e8 ) { # ~10 years
 79+ $exptime += time();
 80+ }
 81+
 82+ $encExpiry = $db->timestamp( $exptime );
 83+ }
 84+ try {
 85+ $db->begin();
 86+ // (bug 24425) use a replace if the db supports it instead of
 87+ // delete/insert to avoid clashes with conflicting keynames
 88+ $db->replace( 'objectcache', array( 'keyname' ),
 89+ array(
 90+ 'keyname' => $key,
 91+ 'value' => $db->encodeBlob( $this->serialize( $value ) ),
 92+ 'exptime' => $encExpiry
 93+ ), __METHOD__ );
 94+ $db->commit();
 95+ } catch ( DBQueryError $e ) {
 96+ $this->handleWriteError( $e );
 97+
 98+ return false;
 99+ }
 100+
 101+ return true;
 102+ }
 103+
 104+ public function delete( $key, $time = 0 ) {
 105+ $db = $this->getDB();
 106+
 107+ try {
 108+ $db->begin();
 109+ $db->delete( 'objectcache', array( 'keyname' => $key ), __METHOD__ );
 110+ $db->commit();
 111+ } catch ( DBQueryError $e ) {
 112+ $this->handleWriteError( $e );
 113+
 114+ return false;
 115+ }
 116+
 117+ return true;
 118+ }
 119+
 120+ public function incr( $key, $step = 1 ) {
 121+ $db = $this->getDB();
 122+ $step = intval( $step );
 123+
 124+ try {
 125+ $db->begin();
 126+ $row = $db->selectRow( 'objectcache', array( 'value', 'exptime' ),
 127+ array( 'keyname' => $key ), __METHOD__, array( 'FOR UPDATE' ) );
 128+ if ( $row === false ) {
 129+ // Missing
 130+ $db->commit();
 131+
 132+ return null;
 133+ }
 134+ $db->delete( 'objectcache', array( 'keyname' => $key ), __METHOD__ );
 135+ if ( $this->isExpired( $row->exptime ) ) {
 136+ // Expired, do not reinsert
 137+ $db->commit();
 138+
 139+ return null;
 140+ }
 141+
 142+ $oldValue = intval( $this->unserialize( $db->decodeBlob( $row->value ) ) );
 143+ $newValue = $oldValue + $step;
 144+ $db->insert( 'objectcache',
 145+ array(
 146+ 'keyname' => $key,
 147+ 'value' => $db->encodeBlob( $this->serialize( $newValue ) ),
 148+ 'exptime' => $row->exptime
 149+ ), __METHOD__ );
 150+ $db->commit();
 151+ } catch ( DBQueryError $e ) {
 152+ $this->handleWriteError( $e );
 153+
 154+ return null;
 155+ }
 156+
 157+ return $newValue;
 158+ }
 159+
 160+ public function keys() {
 161+ $db = $this->getDB();
 162+ $res = $db->select( 'objectcache', array( 'keyname' ), false, __METHOD__ );
 163+ $result = array();
 164+
 165+ foreach ( $res as $row ) {
 166+ $result[] = $row->keyname;
 167+ }
 168+
 169+ return $result;
 170+ }
 171+
 172+ protected function isExpired( $exptime ) {
 173+ return $exptime != $this->getMaxDateTime() && wfTimestamp( TS_UNIX, $exptime ) < time();
 174+ }
 175+
 176+ protected function getMaxDateTime() {
 177+ if ( time() > 0x7fffffff ) {
 178+ return $this->getDB()->timestamp( 1 << 62 );
 179+ } else {
 180+ return $this->getDB()->timestamp( 0x7fffffff );
 181+ }
 182+ }
 183+
 184+ protected function garbageCollect() {
 185+ /* Ignore 99% of requests */
 186+ if ( !mt_rand( 0, 100 ) ) {
 187+ $now = time();
 188+ /* Avoid repeating the delete within a few seconds */
 189+ if ( $now > ( $this->lastExpireAll + 1 ) ) {
 190+ $this->lastExpireAll = $now;
 191+ $this->expireAll();
 192+ }
 193+ }
 194+ }
 195+
 196+ public function expireAll() {
 197+ $db = $this->getDB();
 198+ $now = $db->timestamp();
 199+
 200+ try {
 201+ $db->begin();
 202+ $db->delete( 'objectcache', array( 'exptime < ' . $db->addQuotes( $now ) ), __METHOD__ );
 203+ $db->commit();
 204+ } catch ( DBQueryError $e ) {
 205+ $this->handleWriteError( $e );
 206+ }
 207+ }
 208+
 209+ public function deleteAll() {
 210+ $db = $this->getDB();
 211+
 212+ try {
 213+ $db->begin();
 214+ $db->delete( 'objectcache', '*', __METHOD__ );
 215+ $db->commit();
 216+ } catch ( DBQueryError $e ) {
 217+ $this->handleWriteError( $e );
 218+ }
 219+ }
 220+
 221+ /**
 222+ * Serialize an object and, if possible, compress the representation.
 223+ * On typical message and page data, this can provide a 3X decrease
 224+ * in storage requirements.
 225+ *
 226+ * @param $data mixed
 227+ * @return string
 228+ */
 229+ protected function serialize( &$data ) {
 230+ $serial = serialize( $data );
 231+
 232+ if ( function_exists( 'gzdeflate' ) ) {
 233+ return gzdeflate( $serial );
 234+ } else {
 235+ return $serial;
 236+ }
 237+ }
 238+
 239+ /**
 240+ * Unserialize and, if necessary, decompress an object.
 241+ * @param $serial string
 242+ * @return mixed
 243+ */
 244+ protected function unserialize( $serial ) {
 245+ if ( function_exists( 'gzinflate' ) ) {
 246+ $decomp = @gzinflate( $serial );
 247+
 248+ if ( false !== $decomp ) {
 249+ $serial = $decomp;
 250+ }
 251+ }
 252+
 253+ $ret = unserialize( $serial );
 254+
 255+ return $ret;
 256+ }
 257+
 258+ /**
 259+ * Handle a DBQueryError which occurred during a write operation.
 260+ * Ignore errors which are due to a read-only database, rethrow others.
 261+ */
 262+ protected function handleWriteError( $exception ) {
 263+ $db = $this->getDB();
 264+
 265+ if ( !$db->wasReadOnlyError() ) {
 266+ throw $exception;
 267+ }
 268+
 269+ try {
 270+ $db->rollback();
 271+ } catch ( DBQueryError $e ) {
 272+ }
 273+
 274+ wfDebug( __METHOD__ . ": ignoring query error\n" );
 275+ $db->ignoreErrors( false );
 276+ }
 277+}
 278+
 279+/**
 280+ * Backwards compatibility alias
 281+ */
 282+class MediaWikiBagOStuff extends SqlBagOStuff { }
 283+
Property changes on: trunk/phase3/includes/objectcache/SqlBagOStuff.php
___________________________________________________________________
Added: svn:eol-style
1284 + native
Index: trunk/phase3/includes/objectcache/WinCacheBagOStuff.php
@@ -0,0 +1,71 @@
 2+<?php
 3+
 4+/**
 5+ * Wrapper for WinCache object caching functions; identical interface
 6+ * to the APC wrapper
 7+ *
 8+ * @ingroup Cache
 9+ */
 10+class WinCacheBagOStuff extends BagOStuff {
 11+
 12+ /**
 13+ * Get a value from the WinCache object cache
 14+ *
 15+ * @param $key String: cache key
 16+ * @return mixed
 17+ */
 18+ public function get( $key ) {
 19+ $val = wincache_ucache_get( $key );
 20+
 21+ if ( is_string( $val ) ) {
 22+ $val = unserialize( $val );
 23+ }
 24+
 25+ return $val;
 26+ }
 27+
 28+ /**
 29+ * Store a value in the WinCache object cache
 30+ *
 31+ * @param $key String: cache key
 32+ * @param $value Mixed: object to store
 33+ * @param $expire Int: expiration time
 34+ * @return bool
 35+ */
 36+ public function set( $key, $value, $expire = 0 ) {
 37+ $result = wincache_ucache_set( $key, serialize( $value ), $expire );
 38+
 39+ /* wincache_ucache_set returns an empty array on success if $value
 40+ was an array, bool otherwise */
 41+ return ( is_array( $result ) && $result === array() ) || $result;
 42+ }
 43+
 44+ /**
 45+ * Remove a value from the WinCache object cache
 46+ *
 47+ * @param $key String: cache key
 48+ * @param $time Int: not used in this implementation
 49+ * @return bool
 50+ */
 51+ public function delete( $key, $time = 0 ) {
 52+ wincache_ucache_delete( $key );
 53+
 54+ return true;
 55+ }
 56+
 57+ public function keys() {
 58+ $info = wincache_ucache_info();
 59+ $list = $info['ucache_entries'];
 60+ $keys = array();
 61+
 62+ if ( is_null( $list ) ) {
 63+ return array();
 64+ }
 65+
 66+ foreach ( $list as $entry ) {
 67+ $keys[] = $entry['key_name'];
 68+ }
 69+
 70+ return $keys;
 71+ }
 72+}
Property changes on: trunk/phase3/includes/objectcache/WinCacheBagOStuff.php
___________________________________________________________________
Added: svn:eol-style
173 + native
Index: trunk/phase3/includes/objectcache/APCBagOStuff.php
@@ -0,0 +1,43 @@
 2+<?php
 3+
 4+/**
 5+ * This is a wrapper for APC's shared memory functions
 6+ *
 7+ * @ingroup Cache
 8+ */
 9+class APCBagOStuff extends BagOStuff {
 10+ public function get( $key ) {
 11+ $val = apc_fetch( $key );
 12+
 13+ if ( is_string( $val ) ) {
 14+ $val = unserialize( $val );
 15+ }
 16+
 17+ return $val;
 18+ }
 19+
 20+ public function set( $key, $value, $exptime = 0 ) {
 21+ apc_store( $key, serialize( $value ), $exptime );
 22+
 23+ return true;
 24+ }
 25+
 26+ public function delete( $key, $time = 0 ) {
 27+ apc_delete( $key );
 28+
 29+ return true;
 30+ }
 31+
 32+ public function keys() {
 33+ $info = apc_cache_info( 'user' );
 34+ $list = $info['cache_list'];
 35+ $keys = array();
 36+
 37+ foreach ( $list as $entry ) {
 38+ $keys[] = $entry['info'];
 39+ }
 40+
 41+ return $keys;
 42+ }
 43+}
 44+
Property changes on: trunk/phase3/includes/objectcache/APCBagOStuff.php
___________________________________________________________________
Added: svn:eol-style
145 + native
Index: trunk/phase3/includes/objectcache/HashBagOStuff.php
@@ -0,0 +1,58 @@
 2+<?php
 3+
 4+/**
 5+ * This is a test of the interface, mainly. It stores things in an associative
 6+ * array, which is not going to persist between program runs.
 7+ *
 8+ * @ingroup Cache
 9+ */
 10+class HashBagOStuff extends BagOStuff {
 11+ var $bag;
 12+
 13+ function __construct() {
 14+ $this->bag = array();
 15+ }
 16+
 17+ protected function expire( $key ) {
 18+ $et = $this->bag[$key][1];
 19+
 20+ if ( ( $et == 0 ) || ( $et > time() ) ) {
 21+ return false;
 22+ }
 23+
 24+ $this->delete( $key );
 25+
 26+ return true;
 27+ }
 28+
 29+ function get( $key ) {
 30+ if ( !isset( $this->bag[$key] ) ) {
 31+ return false;
 32+ }
 33+
 34+ if ( $this->expire( $key ) ) {
 35+ return false;
 36+ }
 37+
 38+ return $this->bag[$key][0];
 39+ }
 40+
 41+ function set( $key, $value, $exptime = 0 ) {
 42+ $this->bag[$key] = array( $value, $this->convertExpiry( $exptime ) );
 43+ }
 44+
 45+ function delete( $key, $time = 0 ) {
 46+ if ( !isset( $this->bag[$key] ) ) {
 47+ return false;
 48+ }
 49+
 50+ unset( $this->bag[$key] );
 51+
 52+ return true;
 53+ }
 54+
 55+ function keys() {
 56+ return array_keys( $this->bag );
 57+ }
 58+}
 59+
Property changes on: trunk/phase3/includes/objectcache/HashBagOStuff.php
___________________________________________________________________
Added: svn:eol-style
160 + native
Index: trunk/phase3/includes/objectcache/DBABagOStuff.php
@@ -0,0 +1,190 @@
 2+<?php
 3+
 4+/**
 5+ * Cache that uses DBA as a backend.
 6+ * Slow due to the need to constantly open and close the file to avoid holding
 7+ * writer locks. Intended for development use only, as a memcached workalike
 8+ * for systems that don't have it.
 9+ *
 10+ * @ingroup Cache
 11+ */
 12+class DBABagOStuff extends BagOStuff {
 13+ var $mHandler, $mFile, $mReader, $mWriter, $mDisabled;
 14+
 15+ public function __construct( $dir = false ) {
 16+ global $wgDBAhandler;
 17+
 18+ if ( $dir === false ) {
 19+ global $wgTmpDirectory;
 20+ $dir = $wgTmpDirectory;
 21+ }
 22+
 23+ $this->mFile = "$dir/mw-cache-" . wfWikiID();
 24+ $this->mFile .= '.db';
 25+ wfDebug( __CLASS__ . ": using cache file {$this->mFile}\n" );
 26+ $this->mHandler = $wgDBAhandler;
 27+ }
 28+
 29+ /**
 30+ * Encode value and expiry for storage
 31+ */
 32+ function encode( $value, $expiry ) {
 33+ # Convert to absolute time
 34+ $expiry = $this->convertExpiry( $expiry );
 35+
 36+ return sprintf( '%010u', intval( $expiry ) ) . ' ' . serialize( $value );
 37+ }
 38+
 39+ /**
 40+ * @return list containing value first and expiry second
 41+ */
 42+ function decode( $blob ) {
 43+ if ( !is_string( $blob ) ) {
 44+ return array( null, 0 );
 45+ } else {
 46+ return array(
 47+ unserialize( substr( $blob, 11 ) ),
 48+ intval( substr( $blob, 0, 10 ) )
 49+ );
 50+ }
 51+ }
 52+
 53+ function getReader() {
 54+ if ( file_exists( $this->mFile ) ) {
 55+ $handle = dba_open( $this->mFile, 'rl', $this->mHandler );
 56+ } else {
 57+ $handle = $this->getWriter();
 58+ }
 59+
 60+ if ( !$handle ) {
 61+ wfDebug( "Unable to open DBA cache file {$this->mFile}\n" );
 62+ }
 63+
 64+ return $handle;
 65+ }
 66+
 67+ function getWriter() {
 68+ $handle = dba_open( $this->mFile, 'cl', $this->mHandler );
 69+
 70+ if ( !$handle ) {
 71+ wfDebug( "Unable to open DBA cache file {$this->mFile}\n" );
 72+ }
 73+
 74+ return $handle;
 75+ }
 76+
 77+ function get( $key ) {
 78+ wfProfileIn( __METHOD__ );
 79+ wfDebug( __METHOD__ . "($key)\n" );
 80+
 81+ $handle = $this->getReader();
 82+ if ( !$handle ) {
 83+ wfProfileOut( __METHOD__ );
 84+ return null;
 85+ }
 86+
 87+ $val = dba_fetch( $key, $handle );
 88+ list( $val, $expiry ) = $this->decode( $val );
 89+
 90+ # Must close ASAP because locks are held
 91+ dba_close( $handle );
 92+
 93+ if ( !is_null( $val ) && $expiry && $expiry < time() ) {
 94+ # Key is expired, delete it
 95+ $handle = $this->getWriter();
 96+ dba_delete( $key, $handle );
 97+ dba_close( $handle );
 98+ wfDebug( __METHOD__ . ": $key expired\n" );
 99+ $val = null;
 100+ }
 101+
 102+ wfProfileOut( __METHOD__ );
 103+ return $val;
 104+ }
 105+
 106+ function set( $key, $value, $exptime = 0 ) {
 107+ wfProfileIn( __METHOD__ );
 108+ wfDebug( __METHOD__ . "($key)\n" );
 109+
 110+ $blob = $this->encode( $value, $exptime );
 111+
 112+ $handle = $this->getWriter();
 113+ if ( !$handle ) {
 114+ wfProfileOut( __METHOD__ );
 115+ return false;
 116+ }
 117+
 118+ $ret = dba_replace( $key, $blob, $handle );
 119+ dba_close( $handle );
 120+
 121+ wfProfileOut( __METHOD__ );
 122+ return $ret;
 123+ }
 124+
 125+ function delete( $key, $time = 0 ) {
 126+ wfProfileIn( __METHOD__ );
 127+ wfDebug( __METHOD__ . "($key)\n" );
 128+
 129+ $handle = $this->getWriter();
 130+ if ( !$handle ) {
 131+ wfProfileOut( __METHOD__ );
 132+ return false;
 133+ }
 134+
 135+ $ret = dba_delete( $key, $handle );
 136+ dba_close( $handle );
 137+
 138+ wfProfileOut( __METHOD__ );
 139+ return $ret;
 140+ }
 141+
 142+ function add( $key, $value, $exptime = 0 ) {
 143+ wfProfileIn( __METHOD__ );
 144+
 145+ $blob = $this->encode( $value, $exptime );
 146+
 147+ $handle = $this->getWriter();
 148+
 149+ if ( !$handle ) {
 150+ wfProfileOut( __METHOD__ );
 151+ return false;
 152+ }
 153+
 154+ $ret = dba_insert( $key, $blob, $handle );
 155+
 156+ # Insert failed, check to see if it failed due to an expired key
 157+ if ( !$ret ) {
 158+ list( $value, $expiry ) = $this->decode( dba_fetch( $key, $handle ) );
 159+
 160+ if ( $expiry < time() ) {
 161+ # Yes expired, delete and try again
 162+ dba_delete( $key, $handle );
 163+ $ret = dba_insert( $key, $blob, $handle );
 164+ # This time if it failed then it will be handled by the caller like any other race
 165+ }
 166+ }
 167+
 168+ dba_close( $handle );
 169+
 170+ wfProfileOut( __METHOD__ );
 171+ return $ret;
 172+ }
 173+
 174+ function keys() {
 175+ $reader = $this->getReader();
 176+ $k1 = dba_firstkey( $reader );
 177+
 178+ if ( !$k1 ) {
 179+ return array();
 180+ }
 181+
 182+ $result[] = $k1;
 183+
 184+ while ( $key = dba_nextkey( $reader ) ) {
 185+ $result[] = $key;
 186+ }
 187+
 188+ return $result;
 189+ }
 190+}
 191+
Property changes on: trunk/phase3/includes/objectcache/DBABagOStuff.php
___________________________________________________________________
Added: svn:eol-style
1192 + native
Index: trunk/phase3/includes/Setup.php
@@ -283,7 +283,7 @@
284284 require_once( "$IP/includes/Hooks.php" );
285285 require_once( "$IP/includes/Namespace.php" );
286286 require_once( "$IP/includes/ProxyTools.php" );
287 -require_once( "$IP/includes/ObjectCache.php" );
 287+require_once( "$IP/includes/objectcache/ObjectCache.php" );
288288 require_once( "$IP/includes/ImageFunctions.php" );
289289 wfProfileOut( $fname . '-includes' );
290290 wfProfileIn( $fname . '-misc1' );
Index: trunk/phase3/includes/AutoLoader.php
@@ -17,14 +17,12 @@
1818 'AjaxDispatcher' => 'includes/AjaxDispatcher.php',
1919 'AjaxResponse' => 'includes/AjaxResponse.php',
2020 'AlphabeticPager' => 'includes/Pager.php',
21 - 'APCBagOStuff' => 'includes/BagOStuff.php',
2221 'Article' => 'includes/Article.php',
2322 'AtomFeed' => 'includes/Feed.php',
2423 'AuthPlugin' => 'includes/AuthPlugin.php',
2524 'AuthPluginUser' => 'includes/AuthPlugin.php',
2625 'Autopromote' => 'includes/Autopromote.php',
2726 'BacklinkCache' => 'includes/BacklinkCache.php',
28 - 'BagOStuff' => 'includes/BagOStuff.php',
2927 'Block' => 'includes/Block.php',
3028 'CacheDependency' => 'includes/CacheDependency.php',
3129 'CacheTime' => 'includes/parser/ParserOutput.php',
@@ -55,7 +53,6 @@
5654 'Credits' => 'includes/Credits.php',
5755 'CSSJanus' => 'includes/libs/CSSJanus.php',
5856 'CSSMin' => 'includes/libs/CSSMin.php',
59 - 'DBABagOStuff' => 'includes/BagOStuff.php',
6057 'DependencyWrapper' => 'includes/CacheDependency.php',
6158 'DiffHistoryBlob' => 'includes/HistoryBlob.php',
6259 'DjVuImage' => 'includes/DjVuImage.php',
@@ -72,7 +69,6 @@
7370 'DumpNotalkFilter' => 'includes/Export.php',
7471 'DumpOutput' => 'includes/Export.php',
7572 'DumpPipeOutput' => 'includes/Export.php',
76 - 'eAccelBagOStuff' => 'includes/BagOStuff.php',
7773 'EditPage' => 'includes/EditPage.php',
7874 'EmailNotification' => 'includes/UserMailer.php',
7975 'EnhancedChangesList' => 'includes/ChangesList.php',
@@ -86,7 +82,6 @@
8783 'ExternalUser' => 'includes/ExternalUser.php',
8884 'FatalError' => 'includes/Exception.php',
8985 'FakeTitle' => 'includes/FakeTitle.php',
90 - 'FakeMemCachedClient' => 'includes/ObjectCache.php',
9186 'Fallback' => 'includes/Fallback.php',
9287 'FauxRequest' => 'includes/WebRequest.php',
9388 'FauxResponse' => 'includes/WebResponse.php',
@@ -100,7 +95,6 @@
10196 'FormOptions' => 'includes/FormOptions.php',
10297 'GenderCache' => 'includes/GenderCache.php',
10398 'GlobalDependency' => 'includes/CacheDependency.php',
104 - 'HashBagOStuff' => 'includes/BagOStuff.php',
10599 'HashtableReplacer' => 'includes/StringUtils.php',
106100 'HistoryBlobCurStub' => 'includes/HistoryBlob.php',
107101 'HistoryBlob' => 'includes/HistoryBlob.php',
@@ -162,7 +156,6 @@
163157 'MagicWord' => 'includes/MagicWord.php',
164158 'MailAddress' => 'includes/UserMailer.php',
165159 'MathRenderer' => 'includes/Math.php',
166 - 'MediaWikiBagOStuff' => 'includes/BagOStuff.php',
167160 'MediaWiki_I18N' => 'includes/SkinTemplate.php',
168161 'MediaWiki' => 'includes/Wiki.php',
169162 'MemCachedClientforWiki' => 'includes/memcached-client.php',
@@ -232,7 +225,6 @@
233226 'SpecialMytalk' => 'includes/SpecialPage.php',
234227 'SpecialPage' => 'includes/SpecialPage.php',
235228 'SpecialRedirectToSpecial' => 'includes/SpecialPage.php',
236 - 'SqlBagOStuff' => 'includes/BagOStuff.php',
237229 'SquidUpdate' => 'includes/SquidUpdate.php',
238230 'SquidPurgeClient' => 'includes/SquidPurgeClient.php',
239231 'SquidPurgeClientPool' => 'includes/SquidPurgeClient.php',
@@ -267,8 +259,6 @@
268260 'WikiMap' => 'includes/WikiMap.php',
269261 'WikiReference' => 'includes/WikiMap.php',
270262 'WikiXmlError' => 'includes/WikiError.php',
271 - 'WinCacheBagOStuff' => 'includes/BagOStuff.php',
272 - 'XCacheBagOStuff' => 'includes/BagOStuff.php',
273263 'XmlDumpWriter' => 'includes/Export.php',
274264 'Xml' => 'includes/Xml.php',
275265 'XmlJsCode' => 'includes/Xml.php',
@@ -512,6 +502,18 @@
513503 # includes/normal
514504 'UtfNormal' => 'includes/normal/UtfNormal.php',
515505
 506+ # includes/objectcache
 507+ 'APCBagOStuff' => 'includes/objectcache/APCBagOStuff.php',
 508+ 'BagOStuff' => 'includes/objectcache/BagOStuff.php',
 509+ 'DBABagOStuff' => 'includes/objectcache/DBABagOStuff.php',
 510+ 'FakeMemCachedClient' => 'includes/objectcache/ObjectCache.php',
 511+ 'HashBagOStuff' => 'includes/objectcache/HashBagOStuff.php',
 512+ 'MediaWikiBagOStuff' => 'includes/objectcache/SqlBagOStuff.php',
 513+ 'SqlBagOStuff' => 'includes/objectcache/SqlBagOStuff.php',
 514+ 'WinCacheBagOStuff' => 'includes/objectcache/WinCacheBagOStuff.php',
 515+ 'XCacheBagOStuff' => 'includes/objectcache/XCacheBagOStuff.php',
 516+ 'eAccelBagOStuff' => 'includes/objectcache/eAccelBagOStuff.php',
 517+
516518 # includes/parser
517519 'CoreLinkFunctions' => 'includes/parser/CoreLinkFunctions.php',
518520 'CoreParserFunctions' => 'includes/parser/CoreParserFunctions.php',

Sign-offs

UserFlagDate
Hasharinspected10:15, 3 March 2011

Follow-up revisions

RevisionCommit summaryAuthorDate
r84727Merged in the ObjectCache refactor and the Ehcache client. MFT r83135, r83136...tstarling03:28, 25 March 2011

Status & tagging log