summaryrefslogtreecommitdiff
path: root/includes/objectcache/MultiWriteBagOStuff.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/objectcache/MultiWriteBagOStuff.php')
-rw-r--r--includes/objectcache/MultiWriteBagOStuff.php113
1 files changed, 113 insertions, 0 deletions
diff --git a/includes/objectcache/MultiWriteBagOStuff.php b/includes/objectcache/MultiWriteBagOStuff.php
new file mode 100644
index 00000000..2b88b427
--- /dev/null
+++ b/includes/objectcache/MultiWriteBagOStuff.php
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * A cache class that replicates all writes to multiple child caches. Reads
+ * are implemented by reading from the caches in the order they are given in
+ * the configuration until a cache gives a positive result.
+ */
+class MultiWriteBagOStuff extends BagOStuff {
+ var $caches;
+
+ /**
+ * Constructor. Parameters are:
+ *
+ * - caches: This should have a numbered array of cache parameter
+ * structures, in the style required by $wgObjectCaches. See
+ * the documentation of $wgObjectCaches for more detail.
+ *
+ * @param $params array
+ */
+ public function __construct( $params ) {
+ if ( !isset( $params['caches'] ) ) {
+ throw new MWException( __METHOD__.': the caches parameter is required' );
+ }
+
+ $this->caches = array();
+ foreach ( $params['caches'] as $cacheInfo ) {
+ $this->caches[] = ObjectCache::newFromParams( $cacheInfo );
+ }
+ }
+
+ public function setDebug( $debug ) {
+ $this->doWrite( 'setDebug', $debug );
+ }
+
+ public function get( $key ) {
+ foreach ( $this->caches as $cache ) {
+ $value = $cache->get( $key );
+ if ( $value !== false ) {
+ return $value;
+ }
+ }
+ return false;
+ }
+
+ public function set( $key, $value, $exptime = 0 ) {
+ return $this->doWrite( 'set', $key, $value, $exptime );
+ }
+
+ public function delete( $key, $time = 0 ) {
+ return $this->doWrite( 'delete', $key, $time );
+ }
+
+ public function add( $key, $value, $exptime = 0 ) {
+ return $this->doWrite( 'add', $key, $value, $exptime );
+ }
+
+ public function replace( $key, $value, $exptime = 0 ) {
+ return $this->doWrite( 'replace', $key, $value, $exptime );
+ }
+
+ public function incr( $key, $value = 1 ) {
+ return $this->doWrite( 'incr', $key, $value );
+ }
+
+ public function decr( $key, $value = 1 ) {
+ return $this->doWrite( 'decr', $key, $value );
+ }
+
+ public function lock( $key, $timeout = 0 ) {
+ // Lock only the first cache, to avoid deadlocks
+ if ( isset( $this->caches[0] ) ) {
+ return $this->caches[0]->lock( $key, $timeout );
+ } else {
+ return true;
+ }
+ }
+
+ public function unlock( $key ) {
+ if ( isset( $this->caches[0] ) ) {
+ return $this->caches[0]->unlock( $key );
+ } else {
+ return true;
+ }
+ }
+
+ protected function doWrite( $method /*, ... */ ) {
+ $ret = true;
+ $args = func_get_args();
+ array_shift( $args );
+
+ foreach ( $this->caches as $cache ) {
+ if ( !call_user_func_array( array( $cache, $method ), $args ) ) {
+ $ret = false;
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Delete objects expiring before a certain date.
+ *
+ * Succeed if any of the child caches succeed.
+ */
+ public function deleteObjectsExpiringBefore( $date ) {
+ $ret = false;
+ foreach ( $this->caches as $cache ) {
+ if ( $cache->deleteObjectsExpiringBefore( $date ) ) {
+ $ret = true;
+ }
+ }
+ return $ret;
+ }
+}