1<?php
2
3namespace Doctrine\Common\Cache;
4
5use Memcached;
6use function time;
7
8/**
9 * Memcached cache provider.
10 *
11 * @link   www.doctrine-project.org
12 */
13class MemcachedCache extends CacheProvider
14{
15    /** @var Memcached|null */
16    private $memcached;
17
18    /**
19     * Sets the memcache instance to use.
20     *
21     * @return void
22     */
23    public function setMemcached(Memcached $memcached)
24    {
25        $this->memcached = $memcached;
26    }
27
28    /**
29     * Gets the memcached instance used by the cache.
30     *
31     * @return Memcached|null
32     */
33    public function getMemcached()
34    {
35        return $this->memcached;
36    }
37
38    /**
39     * {@inheritdoc}
40     */
41    protected function doFetch($id)
42    {
43        return $this->memcached->get($id);
44    }
45
46    /**
47     * {@inheritdoc}
48     */
49    protected function doFetchMultiple(array $keys)
50    {
51        return $this->memcached->getMulti($keys) ?: [];
52    }
53
54    /**
55     * {@inheritdoc}
56     */
57    protected function doSaveMultiple(array $keysAndValues, $lifetime = 0)
58    {
59        if ($lifetime > 30 * 24 * 3600) {
60            $lifetime = time() + $lifetime;
61        }
62
63        return $this->memcached->setMulti($keysAndValues, $lifetime);
64    }
65
66    /**
67     * {@inheritdoc}
68     */
69    protected function doContains($id)
70    {
71        $this->memcached->get($id);
72
73        return $this->memcached->getResultCode() === Memcached::RES_SUCCESS;
74    }
75
76    /**
77     * {@inheritdoc}
78     */
79    protected function doSave($id, $data, $lifeTime = 0)
80    {
81        if ($lifeTime > 30 * 24 * 3600) {
82            $lifeTime = time() + $lifeTime;
83        }
84        return $this->memcached->set($id, $data, (int) $lifeTime);
85    }
86
87    /**
88     * {@inheritdoc}
89     */
90    protected function doDeleteMultiple(array $keys)
91    {
92        return $this->memcached->deleteMulti($keys)
93            || $this->memcached->getResultCode() === Memcached::RES_NOTFOUND;
94    }
95
96    /**
97     * {@inheritdoc}
98     */
99    protected function doDelete($id)
100    {
101        return $this->memcached->delete($id)
102            || $this->memcached->getResultCode() === Memcached::RES_NOTFOUND;
103    }
104
105    /**
106     * {@inheritdoc}
107     */
108    protected function doFlush()
109    {
110        return $this->memcached->flush();
111    }
112
113    /**
114     * {@inheritdoc}
115     */
116    protected function doGetStats()
117    {
118        $stats   = $this->memcached->getStats();
119        $servers = $this->memcached->getServerList();
120        $key     = $servers[0]['host'] . ':' . $servers[0]['port'];
121        $stats   = $stats[$key];
122        return [
123            Cache::STATS_HITS   => $stats['get_hits'],
124            Cache::STATS_MISSES => $stats['get_misses'],
125            Cache::STATS_UPTIME => $stats['uptime'],
126            Cache::STATS_MEMORY_USAGE     => $stats['bytes'],
127            Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'],
128        ];
129    }
130}
131