Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 6b637a7

Browse filesBrowse files
committed
initial cleanup of memcached cache adapter for upstream
squashed commits: - fabbot.io diff applied to fix style issues - removal of phpunit 5.x features to support legacy PHP versions, changes to texting server array for HHVM fix - fabbot.io patch for style fix - removed unnessissary abstract test class (copied from redis tests during initial creation of the tests for this code
1 parent 60b4dd0 commit 6b637a7
Copy full SHA for 6b637a7

File tree

2 files changed

+415
-0
lines changed
Filter options

2 files changed

+415
-0
lines changed
+252Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Adapter;
13+
14+
use Symfony\Component\Cache\Exception\InvalidArgumentException;
15+
16+
/**
17+
* @author Rob Frawley 2nd <rmf@src.run>
18+
*/
19+
class MemcachedAdapter extends AbstractAdapter
20+
{
21+
const DEFAULT_HOST = '127.0.0.1';
22+
const DEFAULT_PORT = 11211;
23+
const DEFAULT_WEIGHT = -1;
24+
25+
/**
26+
* @var \Memcached
27+
*/
28+
private $memcached;
29+
30+
/**
31+
* @param \Memcached $memcachedClient
32+
* @param string $namespace
33+
* @param int $defaultLifetime
34+
*/
35+
public function __construct(\Memcached $memcachedClient, $namespace = '', $defaultLifetime = 0)
36+
{
37+
parent::__construct($namespace, $defaultLifetime);
38+
39+
$this->memcached = $memcachedClient;
40+
}
41+
42+
/**
43+
* @param string|null $persistentId
44+
*
45+
* @return \Memcached
46+
*/
47+
public static function createClient($persistentId = null)
48+
{
49+
return new \Memcached($persistentId);
50+
}
51+
52+
/**
53+
* @param array $servers
54+
* @param array $options
55+
*
56+
* @return MemcachedAdapter
57+
*/
58+
public static function createAdapter(array $servers = array(), array $options = array())
59+
{
60+
$adapter = new static(static::createClient());
61+
$adapter->setupConnection($servers, $options);
62+
63+
return $adapter;
64+
}
65+
66+
/**
67+
* @param array $servers
68+
* @param array $options
69+
*
70+
* @return \Memcached
71+
*/
72+
public function setupConnection(array $servers = array(), array $options = array())
73+
{
74+
foreach ($servers as $server) {
75+
$this->addServer($server);
76+
}
77+
78+
foreach ($options as $opt => $val) {
79+
$this->setOption($opt, $val);
80+
}
81+
82+
return $this->memcached;
83+
}
84+
85+
/**
86+
* @param mixed[] $server
87+
*/
88+
public function addServer(array $server)
89+
{
90+
list($host, $port, $weight) = $this->filterServerValues(
91+
isset($server[0]) ? $server[0] : self::DEFAULT_HOST,
92+
isset($server[1]) ? $server[1] : self::DEFAULT_PORT,
93+
isset($server[2]) ? $server[2] : self::DEFAULT_WEIGHT
94+
);
95+
96+
if (!$this->isServerAlreadyEnabled($host, $port)) {
97+
$this->memcached->addServer($host, $port, $weight);
98+
}
99+
}
100+
101+
/**
102+
* @param mixed $opt
103+
* @param mixed $val
104+
*
105+
* @return bool
106+
*/
107+
public function setOption($opt, $val)
108+
{
109+
list($opt, $val) = $this->filterOptionValues($opt, $val);
110+
111+
return $this->memcached->setOption($opt, $val)
112+
&& $this->memcached->getResultCode() === \Memcached::RES_SUCCESS;
113+
}
114+
115+
/**
116+
* @param mixed $opt
117+
* @param mixed $val
118+
*
119+
* @return mixed[]
120+
*/
121+
private function filterOptionValues($opt, $val)
122+
{
123+
list($opt, $val) = array(
124+
$opt = $this->tryResolvingConstant($opt),
125+
$val = $this->tryResolvingConstant($val),
126+
);
127+
128+
if (false === filter_var($opt, FILTER_VALIDATE_INT)) {
129+
throw new InvalidArgumentException(sprintf('Option type invalid "%s": must resolve as int', $opt));
130+
}
131+
132+
if (false === filter_var($val, FILTER_VALIDATE_INT) && false === filter_var($val, FILTER_VALIDATE_BOOLEAN)) {
133+
throw new InvalidArgumentException(sprintf('Option value invalid "%s": must resolve as int or bool', $val));
134+
}
135+
136+
return array($opt, $val);
137+
}
138+
139+
/**
140+
* @param mixed $val
141+
*
142+
* @return mixed
143+
*/
144+
private function tryResolvingConstant($val)
145+
{
146+
return defined($constant = '\Memcached::'.$val) ? constant($constant) : $val;
147+
}
148+
149+
/**
150+
* {@inheritdoc}
151+
*/
152+
protected function doFetch(array $ids)
153+
{
154+
foreach ($this->memcached->getMulti($ids) as $id => $val) {
155+
try {
156+
yield $id => parent::unserialize($val);
157+
} catch (\Exception $e) {
158+
continue;
159+
}
160+
}
161+
}
162+
163+
/**
164+
* {@inheritdoc}
165+
*/
166+
protected function doHave($id)
167+
{
168+
return $this->memcached->get($id) !== false
169+
&& $this->memcached->getResultCode() !== \Memcached::RES_NOTFOUND;
170+
}
171+
172+
/**
173+
* {@inheritdoc}
174+
*/
175+
protected function doClear($namespace)
176+
{
177+
return $this->memcached->flush()
178+
&& $this->memcached->getResultCode() === \Memcached::RES_SUCCESS;
179+
}
180+
181+
/**
182+
* {@inheritdoc}
183+
*/
184+
protected function doDelete(array $ids)
185+
{
186+
$deletions = array_filter((array) $this->memcached->deleteMulti($ids), function ($ret) {
187+
return $ret === true || $ret === \Memcached::RES_NOTFOUND;
188+
});
189+
190+
return count($deletions) === count($ids);
191+
}
192+
193+
/**
194+
* {@inheritdoc}
195+
*/
196+
protected function doSave(array $values, $lifetime)
197+
{
198+
$serialized = $exceptions = array();
199+
200+
foreach ($values as $id => $val) {
201+
try {
202+
$serialized[$id] = serialize($val);
203+
} catch (\Exception $e) {
204+
$exceptions[] = $id;
205+
}
206+
}
207+
208+
$this->memcached->setMulti($serialized, $lifetime);
209+
210+
return $exceptions;
211+
}
212+
213+
/**
214+
* @param string $host
215+
* @param int $port
216+
* @param int $weight
217+
*
218+
* @return mixed[]
219+
*/
220+
private function filterServerValues($host, $port, $weight)
221+
{
222+
if (false === filter_var($host, FILTER_VALIDATE_IP) && false === filter_var(gethostbyname($host), FILTER_VALIDATE_IP)) {
223+
throw new InvalidArgumentException(sprintf('Server host option invalid "%s": must be a valid IP or resolvable hostname', $host));
224+
}
225+
226+
if (false === filter_var($port, FILTER_VALIDATE_INT)) {
227+
throw new InvalidArgumentException(sprintf('Server port option invalid "%s": must be an integer', $port));
228+
}
229+
230+
if (false === filter_var($weight, FILTER_VALIDATE_INT)) {
231+
throw new InvalidArgumentException(sprintf('Server weight option invalid "%s": must be an integer', $weight));
232+
}
233+
234+
return array($host, $port, $weight);
235+
}
236+
237+
/**
238+
* @param string $host
239+
* @param int $port
240+
*
241+
* @return bool
242+
*/
243+
private function isServerAlreadyEnabled($host, $port)
244+
{
245+
$matches = array_filter($this->memcached->getServerList(), function ($server) use ($host, $port) {
246+
return $host === array_shift($server)
247+
&& $port === array_shift($server);
248+
});
249+
250+
return count($matches) > 0;
251+
}
252+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.