5 * Contains \Drupal\memcache\DrupalMemcacheFactory.
8 namespace Drupal\memcache;
13 * Factory class for creation of Memcache objects.
15 class DrupalMemcacheFactory {
18 * The settings object.
20 * @var \Drupal\memcache\DrupalMemcacheConfig
32 protected $memcachePersistent;
35 * @var \Drupal\memcache\DrupalMemcacheInterface[]
37 protected $memcacheCache = array();
42 protected $memcacheServers = array();
47 protected $memcacheBins = array();
52 protected $failedConnectionCache = array();
55 * Constructs a DrupalMemcacheFactory object.
57 * @param \Drupal\memcache\DrupalMemcacheConfig $settings
59 public function __construct(DrupalMemcacheConfig $settings) {
60 $this->settings = $settings;
66 * Returns a Memcache object based on settings and the bin requested.
69 * The bin which is to be used.
72 * Rebuild the bin/server/cache mapping.
74 * @return \Drupal\memcache\DrupalMemcacheInterface
77 public function get($bin = NULL, $flush = FALSE) {
82 if (empty($this->memcacheCache) || empty($this->memcacheCache[$bin])) {
83 // If there is no cluster for this bin in $memcache_bins, cluster is
85 $cluster = empty($this->memcacheBins[$bin]) ? 'default' : $this->memcacheBins[$bin];
87 // If this bin isn't in our $memcacheBins configuration array, and the
88 // 'default' cluster is already initialized, map the bin to 'default'
89 // because we always map the 'default' bin to the 'default' cluster.
90 if (empty($this->memcacheBins[$bin]) && !empty($this->memcacheCache['default'])) {
91 $this->memcacheCache[$bin] = &$this->memcacheCache['default'];
94 // Create a new Memcache object. Each cluster gets its own Memcache
96 // @todo Can't add a custom memcache class here yet.
97 if ($this->extension == 'Memcached') {
98 $memcache = new DrupalMemcached($this->settings);
100 elseif ($this->extension == 'Memcache') {
101 $memcache = new DrupalMemcache($this->settings);
104 // A variable to track whether we've connected to the first server.
107 // Link all the servers to this cluster.
108 foreach ($this->memcacheServers as $s => $c) {
109 if ($c == $cluster && !isset($this->failedConnectionCache[$s])) {
110 if ($memcache->addServer($s, $this->memcachePersistent) && !$init) {
115 // We can't use watchdog because this happens in a bootstrap phase
116 // where watchdog is non-functional. Register a shutdown handler
117 // instead so it gets recorded at the end of page load.
118 register_shutdown_function('memcache_log_warning', LogLevel::ERROR, 'Failed to connect to memcache server: !server', array('!server' => $s));
119 $this->failedConnectionCache[$s] = FALSE;
125 // Map the current bin with the new Memcache object.
126 $this->memcacheCache[$bin] = $memcache;
128 // Now that all the servers have been mapped to this cluster, look for
129 // other bins that belong to the cluster and map them too.
130 foreach ($this->memcacheBins as $b => $c) {
131 if (($c == $cluster) && ($b != $bin)) {
132 // Map this bin and cluster by reference.
133 $this->memcacheCache[$b] = &$this->memcacheCache[$bin];
138 throw new MemcacheException('Memcache instance could not be initialized. Check memcache is running and reachable');
143 return empty($this->memcacheCache[$bin]) ? FALSE : $this->memcacheCache[$bin];
147 * Initializes memcache settings.
149 protected function initialize() {
150 // If an extension is specified in settings.php, use that when available.
151 $preferred = $this->settings->get('extension', NULL);
152 if (isset($preferred) && class_exists($preferred)) {
153 $this->extension = $preferred;
155 // If no extension is set, default to Memcache. The Memcached extension has
156 // some features that the older extension lacks but also an unfixed bug that
157 // affects cache clears.
158 // @see http://pecl.php.net/bugs/bug.php?id=16829
159 elseif (class_exists('Memcache')) {
160 $this->extension = 'Memcache';
162 elseif (class_exists('Memcached')) {
163 $this->extension = 'Memcached';
166 throw new MemcacheException('No Memcache extension found');
169 // Values from settings.php
170 $this->memcacheServers = $this->settings->get('servers', ['127.0.0.1:11211' => 'default']);
171 $this->memcacheBins = $this->settings->get('bins', ['default' => 'default']);
173 // Indicate whether to connect to memcache using a persistent connection.
174 // Note: this only affects the Memcache PECL extension, and does not affect
175 // the Memcached PECL extension. For a detailed explanation see:
176 // http://drupal.org/node/822316#comment-4427676
177 $this->memcachePersistent = $this->settings->get('persistent', FALSE);
181 * Flushes the memcache bin/server/cache mappings and closes connections.
183 protected function flush() {
184 foreach ($this->memcacheCache as $cluster) {
188 $this->memcacheCache = array();