MediaWiki  master
MemcachedPhpBagOStuff.php
Go to the documentation of this file.
1 <?php
31  protected $client;
32 
43  public function __construct( $params ) {
44  parent::__construct( $params );
45 
46  // Default class-specific parameters
47  $params += [
48  'compress_threshold' => 1500,
49  'connect_timeout' => 0.5,
50  'timeout' => 500000,
51  ];
52 
53  $this->client = new MemcachedClient( $params );
54  $this->client->set_servers( $params['servers'] );
55  $this->client->set_debug( true );
56  }
57 
58  protected function doGet( $key, $flags = 0, &$casToken = null ) {
59  $getToken = ( $casToken === self::PASS_BY_REF );
60  $casToken = null;
61 
62  $routeKey = $this->validateKeyAndPrependRoute( $key );
63 
64  // T257003: only require "gets" (instead of "get") when a CAS token is needed
65  $res = $getToken
66  // @phan-suppress-next-line PhanTypeMismatchArgument False positive
67  ? $this->client->get( $routeKey, $casToken )
68  : $this->client->get( $routeKey );
69 
70  if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
71  $this->setLastError( $this->client->_last_cmd_status );
72  }
73 
74  return $res;
75  }
76 
77  protected function doSet( $key, $value, $exptime = 0, $flags = 0 ) {
78  $routeKey = $this->validateKeyAndPrependRoute( $key );
79 
80  $res = $this->client->set( $routeKey, $value, $this->fixExpiry( $exptime ) );
81 
82  if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
83  $this->setLastError( $this->client->_last_cmd_status );
84  }
85 
86  return $res;
87  }
88 
89  protected function doDelete( $key, $flags = 0 ) {
90  $routeKey = $this->validateKeyAndPrependRoute( $key );
91 
92  $res = $this->client->delete( $routeKey );
93 
94  if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
95  $this->setLastError( $this->client->_last_cmd_status );
96  }
97 
98  return $res;
99  }
100 
101  protected function doAdd( $key, $value, $exptime = 0, $flags = 0 ) {
102  $routeKey = $this->validateKeyAndPrependRoute( $key );
103 
104  $res = $this->client->add( $routeKey, $value, $this->fixExpiry( $exptime ) );
105 
106  if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
107  $this->setLastError( $this->client->_last_cmd_status );
108  }
109 
110  return $res;
111  }
112 
113  protected function doCas( $casToken, $key, $value, $exptime = 0, $flags = 0 ) {
114  $routeKey = $this->validateKeyAndPrependRoute( $key );
115 
116  $res = $this->client->cas( $casToken, $routeKey, $value, $this->fixExpiry( $exptime ) );
117 
118  if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
119  $this->setLastError( $this->client->_last_cmd_status );
120  }
121 
122  return $res;
123  }
124 
125  public function incr( $key, $value = 1, $flags = 0 ) {
126  $routeKey = $this->validateKeyAndPrependRoute( $key );
127  $n = $this->client->incr( $routeKey, $value );
128 
129  $res = ( $n !== false && $n !== null ) ? $n : false;
130 
131  if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
132  $this->setLastError( $this->client->_last_cmd_status );
133  }
134 
135  return $res;
136  }
137 
138  public function decr( $key, $value = 1, $flags = 0 ) {
139  $routeKey = $this->validateKeyAndPrependRoute( $key );
140  $n = $this->client->decr( $routeKey, $value );
141 
142  $res = ( $n !== false && $n !== null ) ? $n : false;
143 
144  if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
145  $this->setLastError( $this->client->_last_cmd_status );
146  }
147 
148  return $res;
149  }
150 
151  protected function doIncrWithInitAsync( $key, $exptime, $step, $init ) {
152  $routeKey = $this->validateKeyAndPrependRoute( $key );
153  $watchPoint = $this->watchErrors();
154  $this->client->add( $routeKey, $init - $step, $this->fixExpiry( $exptime ) );
155  $this->client->incr( $routeKey, $step );
156  return !$this->getLastError( $watchPoint );
157  }
158 
159  protected function doIncrWithInitSync( $key, $exptime, $step, $init ) {
160  $routeKey = $this->validateKeyAndPrependRoute( $key );
161 
162  $watchPoint = $this->watchErrors();
163  $newValue = $this->client->incr( $routeKey, $step ) ?? false;
164  if ( $newValue === false && !$this->getLastError( $watchPoint ) ) {
165  // No key set; initialize
166  $success = $this->client->add( $routeKey, $init, $this->fixExpiry( $exptime ) );
167  $newValue = $success ? $init : false;
168  if ( $newValue === false && !$this->getLastError( $watchPoint ) ) {
169  // Raced out initializing; increment
170  $newValue = $this->client->incr( $routeKey, $step ) ?? false;
171  }
172  }
173 
174  return $newValue;
175  }
176 
177  protected function doChangeTTL( $key, $exptime, $flags ) {
178  $routeKey = $this->validateKeyAndPrependRoute( $key );
179 
180  $res = $this->client->touch( $routeKey, $this->fixExpiry( $exptime ) );
181 
182  if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
183  $this->setLastError( $this->client->_last_cmd_status );
184  }
185 
186  return $res;
187  }
188 
189  protected function doGetMulti( array $keys, $flags = 0 ) {
190  $routeKeys = [];
191  foreach ( $keys as $key ) {
192  $routeKeys[] = $this->validateKeyAndPrependRoute( $key );
193  }
194 
195  $resByRouteKey = $this->client->get_multi( $routeKeys );
196 
197  $res = [];
198  foreach ( $resByRouteKey as $routeKey => $value ) {
199  $res[$this->stripRouteFromKey( $routeKey )] = $value;
200  }
201 
202  if ( $this->client->_last_cmd_status !== self::ERR_NONE ) {
203  $this->setLastError( $this->client->_last_cmd_status );
204  }
205 
206  return $res;
207  }
208 
209  protected function serialize( $value ) {
210  return is_int( $value ) ? $value : $this->client->serialize( $value );
211  }
212 
213  protected function unserialize( $value ) {
214  return $this->isInteger( $value ) ? (int)$value : $this->client->unserialize( $value );
215  }
216 }
$success
getLastError( $watchPoint=0)
Get the "last error" registry.
Definition: BagOStuff.php:509
setLastError( $error)
Set the "last error" registry due to a problem encountered during an attempted operation.
Definition: BagOStuff.php:529
watchErrors()
Get a "watch point" token that can be used to get the "last error" to occur after now.
Definition: BagOStuff.php:487
const PASS_BY_REF
Idiom for doGet() to return extra information by reference.
isInteger( $value)
Check if a value is an integer.
Base class for memcached clients.
memcached client class implemented using (p)fsockopen()
A wrapper class for the pure-PHP memcached client, exposing a BagOStuff interface.
doSet( $key, $value, $exptime=0, $flags=0)
Set an item.
doChangeTTL( $key, $exptime, $flags)
__construct( $params)
Available parameters are:
incr( $key, $value=1, $flags=0)
Increase stored value of $key by $value while preserving its TTL.
doAdd( $key, $value, $exptime=0, $flags=0)
Insert an item if it does not already exist.
decr( $key, $value=1, $flags=0)
Decrease stored value of $key by $value while preserving its TTL.
doCas( $casToken, $key, $value, $exptime=0, $flags=0)
Set an item if the current CAS token matches the provided CAS token.
doGet( $key, $flags=0, &$casToken=null)
Get an item.
doIncrWithInitAsync( $key, $exptime, $step, $init)
doGetMulti(array $keys, $flags=0)
Get an associative array containing the item for each of the keys that have items.
doIncrWithInitSync( $key, $exptime, $step, $init)
doDelete( $key, $flags=0)
Delete an item.