Unverified Commit a815d073 authored by damiankloip's avatar damiankloip Committed by damiankloip
Browse files

Issue #2996626 by Fabianx, damiankloip: Class structure is very confusing,...

Issue #2996626 by Fabianx, damiankloip: Class structure is very confusing, unclear when to use factory and when instance
parent fe643be4
<?php
namespace Drupal\memcache\Driver;
use Drupal\memcache\DrupalMemcacheConfig;
class MemcacheConnection implements MemcacheConnectionInterface {
/**
* The memcache object.
*
* @var \Memcache
*/
protected $memcache;
/**
* Constructs a MemcacheConnection object.
*/
public function __construct() {
$this->memcache = new \Memcache();
}
/**
* @{@inheritdoc}
*/
public function addServer($server_path, $persistent = FALSE) {
list($host, $port) = explode(':', $server_path);
// Support unix sockets in the format 'unix:///path/to/socket'.
if ($host == 'unix') {
// When using unix sockets with Memcache use the full path for $host.
$host = $server_path;
// Port is always 0 for unix sockets.
$port = 0;
}
// When using the PECL memcache extension, we must use ->(p)connect
// for the first connection.
return $this->connect($host, $port, $persistent);
}
/**
* {@inheritdoc}
*/
public function getMemcache() {
return $this->memcache;
}
/**
* {@inheritdoc}
*/
public function close() {
$this->memcache->close();
}
/**
* Connects to a memcache server.
*
* @param string $host
* @param int $port
* @param bool $persistent
*
* @return bool|mixed
*/
protected function connect($host, $port, $persistent) {
if ($persistent) {
return @$this->memcache->pconnect($host, $port);
}
else {
return @$this->memcache->connect($host, $port);
}
}
}
<?php
namespace Drupal\memcache\Driver;
interface MemcacheConnectionInterface {
/**
* Adds a memcache server.
*
* @param string $server_path
* The server path including port.
* @param bool $persistent
* Whether this server connection is persistent or not.
*/
public function addServer($server_path, $persistent = FALSE);
/**
* Returns the internal memcache object.
*
* @return object
* e.g. \Memcache|\Memcached
*/
public function getMemcache();
/**
* Closes the memcache instance connection.
*/
public function close();
}
<?php
namespace Drupal\memcache\Driver;
use Drupal\memcache\DrupalMemcacheConfig;
class MemcachedConnection implements MemcacheConnectionInterface {
/**
* The memcache object.
*
* @var \Memcached
*/
protected $memcache;
/**
* Constructs a MemcachedConnection object.
*
* @param \Drupal\memcache\DrupalMemcacheConfig $settings
* The memcache config object.
*/
public function __construct(DrupalMemcacheConfig $settings) {
$this->memcache = new \Memcached();
$default_opts = [
\Memcached::OPT_COMPRESSION => TRUE,
\Memcached::OPT_DISTRIBUTION => \Memcached::DISTRIBUTION_CONSISTENT,
];
foreach ($default_opts as $key => $value) {
$this->memcache->setOption($key, $value);
}
// See README.txt for setting custom Memcache options when using the
// memcached PECL extension.
foreach ($settings->get('options', []) as $key => $value) {
$this->memcache->setOption($key, $value);
}
// SASL configuration to authenticate with Memcached.
// Note: this only affects the Memcached PECL extension.
if ($sasl_config = $settings->get('sasl', [])) {
$this->memcache->setSaslAuthData($sasl_config['username'], $sasl_config['password']);
}
}
/**
* {@inheritdoc}
*/
public function addServer($server_path, $persistent = FALSE) {
list($host, $port) = explode(':', $server_path);
if ($host == 'unix') {
// Memcached expects just the path to the socket without the protocol
$host = substr($server_path, 7);
// Port is always 0 for unix sockets.
$port = 0;
}
return $this->memcache->addServer($host, $port, $persistent);
}
/**
* {@inheritdoc}
*/
public function getMemcache() {
return $this->memcache;
}
/**
* {@inheritdoc}
*/
public function close() {
$this->memcache->quit();
}
}
......@@ -15,59 +15,6 @@ use Drupal\Component\Utility\Timer;
*/
class DrupalMemcache extends DrupalMemcacheBase {
/**
* {@inheritdoc}
*/
public function __construct(DrupalMemcacheConfig $settings) {
parent::__construct($settings);
$this->memcache = new \Memcache();
}
/**
* @{@inheritdoc}
*/
public function addServer($server_path, $persistent = FALSE) {
list($host, $port) = explode(':', $server_path);
// Support unix sockets in the format 'unix:///path/to/socket'.
if ($host == 'unix') {
// When using unix sockets with Memcache use the full path for $host.
$host = $server_path;
// Port is always 0 for unix sockets.
$port = 0;
}
// When using the PECL memcache extension, we must use ->(p)connect
// for the first connection.
return $this->connect($host, $port, $persistent);
}
/**
* {@inheritdoc}
*/
public function close() {
$this->memcache->close();
}
/**
* Connects to a memcache server.
*
* @param string $host
* @param int $port
* @param bool $persistent
*
* @return bool|mixed
*/
protected function connect($host, $port, $persistent) {
if ($persistent) {
return @$this->memcache->pconnect($host, $port);
}
else {
return @$this->memcache->connect($host, $port);
}
}
/**
* {@inheritdoc}
*/
......
......@@ -7,7 +7,6 @@
namespace Drupal\memcache;
use Psr\Log\LogLevel;
use Drupal\Component\Utility\Timer;
/**
......@@ -59,12 +58,26 @@ abstract class DrupalMemcacheBase implements DrupalMemcacheInterface {
*
* @param \Drupal\memcache\DrupalMemcacheConfig
* The memcache config object.
* @param \Memcached|\Memcache $connection
* An existing memcache connection object.
* @param string $bin
* The class instance specific cache bin to use.
*/
public function __construct(DrupalMemcacheConfig $settings) {
public function __construct(DrupalMemcacheConfig $settings, $memcache, $bin = NULL) {
$this->settings = $settings;
$this->memcache = $memcache;
$this->hashAlgorithm = $this->settings->get('key_hash_algorithm', 'sha1');
$this->prefix = $this->settings->get('key_prefix', '');
$prefix = $this->settings->get('key_prefix', '');
if ($prefix) {
$this->prefix = $prefix . ':';
}
if ($bin) {
$this->prefix .= $bin . ':';
}
}
/**
......@@ -239,7 +252,7 @@ abstract class DrupalMemcacheBase implements DrupalMemcacheInterface {
/**
* Helper function to get memcache.
*/
public function memcache() {
public function getMemcache() {
return $this->memcache;
}
......
......@@ -9,6 +9,9 @@ namespace Drupal\memcache;
use Psr\Log\LogLevel;
use Drupal\memcache\Driver\MemcacheConnection;
use Drupal\memcache\Driver\MemcachedConnection;
/**
* Factory class for creation of Memcache objects.
*/
......@@ -24,7 +27,12 @@ class DrupalMemcacheFactory {
/**
* @var string
*/
protected $extension;
protected $driverClass;
/**
* @var string
*/
protected $drupalClass;
/**
* @var bool
......@@ -32,7 +40,7 @@ class DrupalMemcacheFactory {
protected $memcachePersistent;
/**
* @var \Drupal\memcache\DrupalMemcacheInterface[]
* @var \Drupal\memcache\Driver\MemcacheConnectionInterface[]
*/
protected $memcacheCache = [];
......@@ -93,13 +101,8 @@ class DrupalMemcacheFactory {
else {
// Create a new Memcache object. Each cluster gets its own Memcache
// object.
// @todo Can't add a custom memcache class here yet.
if ($this->extension == 'Memcached') {
$memcache = new DrupalMemcached($this->settings);
}
elseif ($this->extension == 'Memcache') {
$memcache = new DrupalMemcache($this->settings);
}
/** @var \Drupal\memcache\Driver\MemcacheConnectionInterface $memcache */
$memcache = new $this->driverClass($this->settings);
// A variable to track whether we've connected to the first server.
$init = FALSE;
......@@ -136,7 +139,7 @@ class DrupalMemcacheFactory {
}
}
return empty($this->memcacheCache[$bin]) ? FALSE : $this->memcacheCache[$bin];
return empty($this->memcacheCache[$bin]) ? FALSE : new $this->drupalClass($this->settings, $this->memcacheCache[$bin]->getMemcache(), $bin);
}
/**
......@@ -145,23 +148,30 @@ class DrupalMemcacheFactory {
protected function initialize() {
// If an extension is specified in settings.php, use that when available.
$preferred = $this->settings->get('extension', NULL);
if (isset($preferred) && class_exists($preferred)) {
$this->extension = $preferred;
}
// If no extension is set, default to Memcache. The Memcached extension has
// some features that the older extension lacks but also an unfixed bug that
// affects cache clears.
// @see http://pecl.php.net/bugs/bug.php?id=16829
elseif (class_exists('Memcache')) {
$this->extension = 'Memcache';
$extension = $preferred;
}
// If no extension is set, default to Memcached.
elseif (class_exists('Memcached')) {
$this->extension = 'Memcached';
$extension = \Memcached::class;
}
elseif (class_exists('Memcache')) {
$extension = \Memcache::class;
}
else {
throw new MemcacheException('No Memcache extension found');
}
// @todo Make driver class configurable?
$this->driverClass = MemcachedConnection::class;
$this->drupalClass = DrupalMemcached::class;
if ($extension === \Memcache::class) {
$this->driverClass = MemcacheConnection::class;
$this->drupalClass = DrupalMemcache::class;
}
// Values from settings.php
$this->memcacheServers = $this->settings->get('servers', ['127.0.0.1:11211' => 'default']);
$this->memcacheBins = $this->settings->get('bins', ['default' => 'default']);
......
......@@ -105,18 +105,4 @@ interface DrupalMemcacheInterface {
*/
public function flush();
/**
* Closes the memacache instance connection.
*/
public function close();
/**
* Adds a memcache server.
*
* @param string $server_path
* The server path including port.
* @param bool $persistent
* Whether this server connection is persistent or not.
*/
public function addServer($server_path, $persistent = FALSE);
}
......@@ -14,57 +14,6 @@ use Drupal\Component\Utility\Timer;
*/
class DrupalMemcached extends DrupalMemcacheBase {
/**
* {@inheritdoc}
*/
public function __construct(DrupalMemcacheConfig $settings) {
parent::__construct($settings);
$this->memcache = new \Memcached();
$default_opts = [
\Memcached::OPT_COMPRESSION => TRUE,
\Memcached::OPT_DISTRIBUTION => \Memcached::DISTRIBUTION_CONSISTENT,
];
foreach ($default_opts as $key => $value) {
$this->memcache->setOption($key, $value);
}
// See README.txt for setting custom Memcache options when using the
// memcached PECL extension.
foreach ($this->settings->get('options', []) as $key => $value) {
$this->memcache->setOption($key, $value);
}
// SASL configuration to authenticate with Memcached.
// Note: this only affects the Memcached PECL extension.
if ($sasl_config = $this->settings->get('sasl', [])) {
$this->memcache->setSaslAuthData($sasl_config['username'], $sasl_config['password']);
}
}
/**
* {@inheritdoc}
*/
public function addServer($server_path, $persistent = FALSE) {
list($host, $port) = explode(':', $server_path);
if ($host == 'unix') {
// Memcached expects just the path to the socket without the protocol
$host = substr($server_path, 7);
// Port is always 0 for unix sockets.
$port = 0;
}
return $this->memcache->addServer($host, $port, $persistent);
}
/**
* {@inheritdoc}
*/
public function close() {
$this->memcache->quit();
}
/**
* {@inheritdoc}
*/
......
......@@ -71,14 +71,10 @@ class MemcacheBackend implements CacheBackendInterface {
* {@inheritdoc}
*/
public function getMultiple(&$cids, $allow_invalid = FALSE) {
$keys = array_map(function($cid) {
return $this->key($cid);
}, $cids);
$cache = $this->memcache->getMulti($keys);
$cache = $this->memcache->getMulti($cids);
$fetched = [];
foreach ($cache as $key => $result) {
foreach ($cache as $result) {
if (!$this->timeIsGreaterThanBinDeletionTime($result->created)) {
continue;
}
......@@ -145,7 +141,7 @@ class MemcacheBackend implements CacheBackendInterface {
$cache->checksum = $this->checksumProvider->getCurrentChecksum($tags);
// Cache all items permanently. We handle expiration in our own logic.
return $this->memcache->set($this->key($cid), $cache);
return $this->memcache->set($cid, $cache);
}
/**
......@@ -166,7 +162,7 @@ class MemcacheBackend implements CacheBackendInterface {
* {@inheritdoc}
*/
public function delete($cid) {
$this->memcache->delete($this->key($cid));
$this->memcache->delete($cid);
}
/**
......@@ -174,7 +170,7 @@ class MemcacheBackend implements CacheBackendInterface {
*/
public function deleteMultiple(array $cids) {
foreach ($cids as $cid) {
$this->memcache->delete($this->key($cid));
$this->memcache->delete($cid);
}
}
......@@ -210,7 +206,7 @@ class MemcacheBackend implements CacheBackendInterface {
foreach ($cids as $cid) {
if ($item = $this->get($cid)) {
$item->expire = REQUEST_TIME - 1;
$this->memcache->set($this->key($cid), $item);
$this->memcache->set($cid, $item);
}
}
}
......@@ -252,17 +248,6 @@ class MemcacheBackend implements CacheBackendInterface {
return TRUE;
}
/**
* Returns a cache key prefixed with the current bin.
*
* @param string $cid
*
* @return string
*/
protected function key($cid) {
return sprintf('%s:%s', $this->bin, $cid);
}
/**
* Determines if a (micro)time is greater than the last bin deletion time.
*
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment