Localisation updates from https://translatewiki.net.
[mediawiki.git] / includes / libs / objectcache / MemcachedPhpBagOStuff.php
blob8d8e07ba5f78eff9695b5fce030911eb228ff9a9
1 <?php
2 /**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
18 * @file
20 namespace Wikimedia\ObjectCache;
22 use MemcachedClient;
24 /**
25 * Store data on memcached servers(s) via a pure-PHP memcached client.
27 * In configuration, the CACHE_MEMCACHED will activate the MemcachedPhpBagOStuff
28 * class. This works out of the box without any PHP extension or other PECL
29 * dependencies. If you can install the php-memcached PECL extension,
30 * it is recommended to use MemcachedPeclBagOStuff instead.
32 * @ingroup Cache
34 class MemcachedPhpBagOStuff extends MemcachedBagOStuff {
35 /** @var MemcachedClient */
36 protected $client;
38 /**
39 * Available parameters are:
40 * - servers: The list of IP:port combinations holding the memcached servers.
41 * - persistent: Whether to use a persistent connection
42 * - compress_threshold: The minimum size an object must be before it is compressed
43 * - timeout: The read timeout in microseconds
44 * - connect_timeout: The connect timeout in seconds
46 * @param array $params
48 public function __construct( $params ) {
49 parent::__construct( $params );
51 // Default class-specific parameters
52 $params += [
53 'compress_threshold' => 1500,
54 'connect_timeout' => 0.5,
55 'timeout' => 500000,
58 $this->client = new MemcachedClient( $params );
59 $this->client->set_servers( $params['servers'] );
60 $this->client->set_debug( true );
63 protected function doGet( $key, $flags = 0, &$casToken = null ) {
64 $getToken = ( $casToken === self::PASS_BY_REF );
65 $casToken = null;
67 $routeKey = $this->validateKeyAndPrependRoute( $key );
69 // T257003: only require "gets" (instead of "get") when a CAS token is needed
70 $res = $getToken // @phan-suppress-next-line PhanTypeMismatchArgument False positive
71 ? $this->client->get( $routeKey, $casToken ) : $this->client->get( $routeKey );
73 if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
74 $this->setLastError( $this->client->_last_cmd_status );
77 return $res;
80 protected function doSet( $key, $value, $exptime = 0, $flags = 0 ) {
81 $routeKey = $this->validateKeyAndPrependRoute( $key );
83 $res = $this->client->set( $routeKey, $value, $this->fixExpiry( $exptime ) );
85 if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
86 $this->setLastError( $this->client->_last_cmd_status );
89 return $res;
92 protected function doDelete( $key, $flags = 0 ) {
93 $routeKey = $this->validateKeyAndPrependRoute( $key );
95 $res = $this->client->delete( $routeKey );
97 if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
98 $this->setLastError( $this->client->_last_cmd_status );
101 return $res;
104 protected function doAdd( $key, $value, $exptime = 0, $flags = 0 ) {
105 $routeKey = $this->validateKeyAndPrependRoute( $key );
107 $res = $this->client->add( $routeKey, $value, $this->fixExpiry( $exptime ) );
109 if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
110 $this->setLastError( $this->client->_last_cmd_status );
113 return $res;
116 protected function doCas( $casToken, $key, $value, $exptime = 0, $flags = 0 ) {
117 $routeKey = $this->validateKeyAndPrependRoute( $key );
119 $res = $this->client->cas( $casToken, $routeKey, $value, $this->fixExpiry( $exptime ) );
121 if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
122 $this->setLastError( $this->client->_last_cmd_status );
125 return $res;
128 protected function doIncrWithInitAsync( $key, $exptime, $step, $init ) {
129 $routeKey = $this->validateKeyAndPrependRoute( $key );
130 $watchPoint = $this->watchErrors();
131 $this->client->add( $routeKey, $init - $step, $this->fixExpiry( $exptime ) );
132 $this->client->incr( $routeKey, $step );
134 return !$this->getLastError( $watchPoint );
137 protected function doIncrWithInitSync( $key, $exptime, $step, $init ) {
138 $routeKey = $this->validateKeyAndPrependRoute( $key );
140 $watchPoint = $this->watchErrors();
141 $newValue = $this->client->incr( $routeKey, $step ) ?? false;
142 if ( $newValue === false && !$this->getLastError( $watchPoint ) ) {
143 // No key set; initialize
144 $success = $this->client->add( $routeKey, $init, $this->fixExpiry( $exptime ) );
145 $newValue = $success ? $init : false;
146 if ( $newValue === false && !$this->getLastError( $watchPoint ) ) {
147 // Raced out initializing; increment
148 $newValue = $this->client->incr( $routeKey, $step ) ?? false;
152 return $newValue;
155 protected function doChangeTTL( $key, $exptime, $flags ) {
156 $routeKey = $this->validateKeyAndPrependRoute( $key );
158 $res = $this->client->touch( $routeKey, $this->fixExpiry( $exptime ) );
160 if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
161 $this->setLastError( $this->client->_last_cmd_status );
164 return $res;
167 protected function doGetMulti( array $keys, $flags = 0 ) {
168 $routeKeys = [];
169 foreach ( $keys as $key ) {
170 $routeKeys[] = $this->validateKeyAndPrependRoute( $key );
173 $resByRouteKey = $this->client->get_multi( $routeKeys );
175 $res = [];
176 foreach ( $resByRouteKey as $routeKey => $value ) {
177 $res[$this->stripRouteFromKey( $routeKey )] = $value;
180 if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
181 $this->setLastError( $this->client->_last_cmd_status );
184 return $res;
187 protected function serialize( $value ) {
188 return is_int( $value ) ? $value : $this->client->serialize( $value );
191 protected function unserialize( $value ) {
192 return $this->isInteger( $value ) ? (int)$value : $this->client->unserialize( $value );
196 /** @deprecated class alias since 1.43 */
197 class_alias( MemcachedPhpBagOStuff::class, 'MemcachedPhpBagOStuff' );