3 namespace Drupal\memcache\Driver;
5 use Drupal\memcache\Connection\MemcacheConnection;
6 use Drupal\memcache\Connection\MemcachedConnection;
7 use Drupal\memcache\MemcacheSettings;
8 use Drupal\memcache\MemcacheException;
11 * Factory class for creation of Memcache objects.
13 class MemcacheDriverFactory {
16 * The settings object.
18 * @var \Drupal\memcache\MemcacheSettings
23 * The connection class reference.
27 protected $connectionClass;
30 * The driver class reference.
34 protected $driverClass;
37 * Whether to connect to memcache using a persistent connection.
41 protected $persistent;
44 * An array of Memcache connections keyed by bin.
46 * @var \Drupal\memcache\Connection\MemcacheConnectionInterface[]
48 protected $connections = [];
51 * An array of configured servers.
55 protected $servers = [];
58 * An array of configured bins.
65 * An array of failed connections to configured servers keyed by server name.
69 protected $failedConnectionCache = [];
72 * Constructs a MemcacheDriverFactory object.
74 * @param \Drupal\memcache\MemcacheSettings $settings
75 * The settings object.
77 public function __construct(MemcacheSettings $settings) {
78 $this->settings = $settings;
84 * Returns a Memcache object based on settings and the bin requested.
87 * The bin which is to be used.
89 * Rebuild the bin/server/cache mapping.
91 * @return \Drupal\memcache\DrupalMemcacheInterface|bool
94 public function get($bin = NULL, $flush = FALSE) {
99 if (empty($this->connections) || empty($this->connections[$bin])) {
100 // If there is no cluster for this bin in $bins, cluster is
102 $cluster = empty($this->bins[$bin]) ? 'default' : $this->bins[$bin];
104 // If this bin isn't in our $bins configuration array, and the
105 // 'default' cluster is already initialized, map the bin to 'default'
106 // because we always map the 'default' bin to the 'default' cluster.
107 if (empty($this->bins[$bin]) && !empty($this->connections['default'])) {
108 $this->connections[$bin] = &$this->connections['default'];
111 // Create a new Memcache object. Each cluster gets its own Memcache
113 /** @var \Drupal\memcache\Connection\MemcacheConnectionInterface $memcache */
114 $memcache = new $this->connectionClass($this->settings);
116 // A variable to track whether we've connected to the first server.
119 // Link all the servers to this cluster.
120 foreach ($this->servers as $s => $c) {
121 if ($c == $cluster && !isset($this->failedConnectionCache[$s])) {
122 if ($memcache->addServer($s, $this->persistent) && !$init) {
127 $this->failedConnectionCache[$s] = FALSE;
133 // Map the current bin with the new Memcache object.
134 $this->connections[$bin] = $memcache;
136 // Now that all the servers have been mapped to this cluster, look for
137 // other bins that belong to the cluster and map them too.
138 foreach ($this->bins as $b => $c) {
139 if (($c == $cluster) && ($b != $bin)) {
140 // Map this bin and cluster by reference.
141 $this->connections[$b] = &$this->connections[$bin];
146 throw new MemcacheException('Memcache instance could not be initialized. Check memcache is running and reachable');
151 return empty($this->connections[$bin]) ? FALSE : new $this->driverClass($this->settings, $this->connections[$bin]->getMemcache(), $bin);
155 * Initializes memcache settings.
157 protected function initialize() {
158 // If an extension is specified in settings.php, use that when available.
159 $preferred = $this->settings->get('extension', NULL);
161 if (isset($preferred) && class_exists($preferred)) {
162 $extension = $preferred;
164 // If no extension is set, default to Memcached.
165 elseif (class_exists('Memcached')) {
166 $extension = \Memcached::class;
168 elseif (class_exists('Memcache')) {
169 $extension = \Memcache::class;
172 throw new MemcacheException('No Memcache extension found');
175 // @todo Make driver class configurable?
176 $this->connectionClass = MemcachedConnection::class;
177 $this->driverClass = MemcachedDriver::class;
179 if ($extension === \Memcache::class) {
180 $this->connectionClass = MemcacheConnection::class;
181 $this->driverClass = MemcacheDriver::class;
184 // Values from settings.php.
185 $this->servers = $this->settings->get('servers', ['127.0.0.1:11211' => 'default']);
186 $this->bins = $this->settings->get('bins', ['default' => 'default']);
188 // Indicate whether to connect to memcache using a persistent connection.
189 // Note: this only affects the Memcache PECL extension, and does not affect
190 // the Memcached PECL extension. For a detailed explanation see:
191 // http://drupal.org/node/822316#comment-4427676
192 $this->persistent = $this->settings->get('persistent', FALSE);
196 * Flushes the memcache bin/server/cache mappings and closes connections.
198 protected function flush() {
199 foreach ($this->connections as $cluster) {
203 $this->connections = [];