Navigation Menu

Skip to content
This repository has been archived by the owner on Jan 8, 2020. It is now read-only.

memcached changes #2876

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
198 changes: 137 additions & 61 deletions library/Zend/Cache/Storage/Adapter/Memcached.php
Expand Up @@ -37,11 +37,32 @@ class Memcached extends AbstractAdapter implements
protected static $extMemcachedMajorVersion;

/**
* The memcached resource
* Has this instance be initialized
*
* @var MemcachedResource
* @var boolean
*/
protected $memcachedResource;
protected $initialized = false;

/**
* The memcached resource manager
*
* @var null|MemcachedResourceManager
*/
protected $resourceManager;

/**
* The memcached resource id
*
* @var null|string
*/
protected $resourceId;

/**
* The namespace prefix
*
* @var string
*/
protected $namespacePrefix = '';

/**
* Constructor
Expand All @@ -61,6 +82,12 @@ public function __construct($options = null)
}

parent::__construct($options);

// reset initialized flag on update option(s)
$initialized = & $this->initialized;
$this->getEventManager()->attach('option', function ($event) use (& $initialized) {
$initialized = false;
});
}

/**
Expand All @@ -70,45 +97,26 @@ public function __construct($options = null)
*/
protected function getMemcachedResource()
{
if ($this->memcachedResource) {
return $this->memcachedResource;
}
if (!$this->initialized) {
$options = $this->getOptions();

$options = $this->getOptions();
// get resource manager and resource id
$this->resourceManager = $options->getResourceManager();
$this->resourceId = $options->getResourceId();

// use a configured resource or a new one
$memcached = $options->getMemcachedResource() ?: new MemcachedResource();

// init lib options
if (static::$extMemcachedMajorVersion > 1) {
$memcached->setOptions($options->getLibOptions());
} else {
foreach ($options->getLibOptions() as $k => $v) {
$memcached->setOption($k, $v);
}
}
$memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options->getNamespace());

// Allow updating namespace
$this->getEventManager()->attach('option', function ($event) use ($memcached) {
$params = $event->getParams();
if (!isset($params['namespace'])) {
// Cannot set lib options after initialization
return;
// init namespace prefix
$namespace = $options->getNamespace();
if ($namespace !== '') {
$this->namespacePrefix = $namespace . $options->getNamespaceSeparator();
} else {
$this->namespacePrefix = '';
}
$memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $params['namespace']);
});

// init servers
$servers = $options->getServers();
if ($servers) {
$memcached->addServers($servers);
// update initialized flag
$this->initialized = true;
}

// use the initialized resource
$this->memcachedResource = $memcached;

return $this->memcachedResource;
return $this->resourceManager->getResource($this->resourceId);
}

/* options */
Expand Down Expand Up @@ -210,12 +218,13 @@ public function getAvailableSpace()
*/
protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
{
$memc = $this->getMemcachedResource();
$memc = $this->getMemcachedResource();
$internalKey = $this->namespacePrefix . $normalizedKey;

if (func_num_args() > 2) {
$result = $memc->get($normalizedKey, null, $casToken);
$result = $memc->get($internalKey, null, $casToken);
} else {
$result = $memc->get($normalizedKey);
$result = $memc->get($internalKey);
}

$success = true;
Expand All @@ -242,12 +251,27 @@ protected function internalGetItem(& $normalizedKey, & $success = null, & $casTo
*/
protected function internalGetItems(array & $normalizedKeys)
{
$memc = $this->getMemcachedResource();
$memc = $this->getMemcachedResource();

foreach ($normalizedKeys as & $normalizedKey) {
$normalizedKey = $this->namespacePrefix . $normalizedKey;
}

$result = $memc->getMulti($normalizedKeys);
if ($result === false) {
throw $this->getExceptionByResultCode($memc->getResultCode());
}

// remove namespace prefix from result
if ($result && $this->namespacePrefix !== '') {
$tmp = array();
$nsPrefixLength = strlen($this->namespacePrefix);
foreach ($result as $internalKey => & $value) {
$tmp[ substr($internalKey, $nsPrefixLength) ] = & $value;
}
$result = $tmp;
}

return $result;
}

Expand All @@ -261,7 +285,7 @@ protected function internalGetItems(array & $normalizedKeys)
protected function internalHasItem(& $normalizedKey)
{
$memc = $this->getMemcachedResource();
$value = $memc->get($normalizedKey);
$value = $memc->get($this->namespacePrefix . $normalizedKey);
if ($value === false || $value === null) {
$rsCode = $memc->getResultCode();
if ($rsCode == MemcachedResource::RES_SUCCESS) {
Expand All @@ -285,13 +309,29 @@ protected function internalHasItem(& $normalizedKey)
*/
protected function internalHasItems(array & $normalizedKeys)
{
$memc = $this->getMemcachedResource();
$memc = $this->getMemcachedResource();

foreach ($normalizedKeys as & $normalizedKey) {
$normalizedKey = $this->namespacePrefix . $normalizedKey;
}

$result = $memc->getMulti($normalizedKeys);
if ($result === false) {
throw $this->getExceptionByResultCode($memc->getResultCode());
}

return array_keys($result);
// Convert to a simgle list
$result = array_keys($result);

// remove namespace prefix
if ($result && $this->namespacePrefix !== '') {
$nsPrefixLength = strlen($this->namespacePrefix);
foreach ($result as & $internalKey) {
$internalKey = substr($internalKey, $nsPrefixLength);
}
}

return $result;
}

/**
Expand All @@ -303,14 +343,29 @@ protected function internalHasItems(array & $normalizedKeys)
*/
protected function internalGetMetadatas(array & $normalizedKeys)
{
$memc = $this->getMemcachedResource();
$memc = $this->getMemcachedResource();

foreach ($normalizedKeys as & $normalizedKey) {
$normalizedKey = $this->namespacePrefix . $normalizedKey;
}

$result = $memc->getMulti($normalizedKeys);
if ($result === false) {
throw $this->getExceptionByResultCode($memc->getResultCode());
}

foreach ($result as & $value) {
$value = array();
// remove namespace prefix and use an empty array as metadata
if ($this->namespacePrefix !== '') {
$tmp = array();
$nsPrefixLength = strlen($this->namespacePrefix);
foreach (array_keys($result) as $internalKey) {
$tmp[ substr($internalKey, $nsPrefixLength) ] = array();
}
$result = $tmp;
} else {
foreach ($result as & $value) {
$value = array();
}
}

return $result;
Expand All @@ -330,7 +385,7 @@ protected function internalSetItem(& $normalizedKey, & $value)
{
$memc = $this->getMemcachedResource();
$expiration = $this->expirationTime();
if (!$memc->set($normalizedKey, $value, $expiration)) {
if (!$memc->set($this->namespacePrefix . $normalizedKey, $value, $expiration)) {
throw $this->getExceptionByResultCode($memc->getResultCode());
}

Expand All @@ -348,7 +403,13 @@ protected function internalSetItems(array & $normalizedKeyValuePairs)
{
$memc = $this->getMemcachedResource();
$expiration = $this->expirationTime();
if (!$memc->setMulti($normalizedKeyValuePairs, $expiration)) {

$namespacedKeyValuePairs = array();
foreach ($normalizedKeyValuePairs as $normalizedKey => & $value) {
$namespacedKeyValuePairs[ $this->namespacePrefix . $normalizedKey ] = & $value;
}

if (!$memc->setMulti($namespacedKeyValuePairs, $expiration)) {
throw $this->getExceptionByResultCode($memc->getResultCode());
}

Expand All @@ -367,7 +428,7 @@ protected function internalAddItem(& $normalizedKey, & $value)
{
$memc = $this->getMemcachedResource();
$expiration = $this->expirationTime();
if (!$memc->add($normalizedKey, $value, $expiration)) {
if (!$memc->add($this->namespacePrefix . $normalizedKey, $value, $expiration)) {
if ($memc->getResultCode() == MemcachedResource::RES_NOTSTORED) {
return false;
}
Expand All @@ -389,7 +450,7 @@ protected function internalReplaceItem(& $normalizedKey, & $value)
{
$memc = $this->getMemcachedResource();
$expiration = $this->expirationTime();
if (!$memc->replace($normalizedKey, $value, $expiration)) {
if (!$memc->replace($this->namespacePrefix . $normalizedKey, $value, $expiration)) {
$rsCode = $memc->getResultCode();
if ($rsCode == MemcachedResource::RES_NOTSTORED) {
return false;
Expand All @@ -415,7 +476,7 @@ protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value)
{
$memc = $this->getMemcachedResource();
$expiration = $this->expirationTime();
$result = $memc->cas($token, $normalizedKey, $value, $expiration);
$result = $memc->cas($token, $this->namespacePrefix . $normalizedKey, $value, $expiration);

if ($result === false) {
$rsCode = $memc->getResultCode();
Expand All @@ -438,7 +499,7 @@ protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value)
protected function internalRemoveItem(& $normalizedKey)
{
$memc = $this->getMemcachedResource();
$result = $memc->delete($normalizedKey);
$result = $memc->delete($this->namespacePrefix . $normalizedKey);

if ($result === false) {
$rsCode = $memc->getResultCode();
Expand Down Expand Up @@ -466,7 +527,12 @@ protected function internalRemoveItems(array & $normalizedKeys)
return parent::internalRemoveItems($normalizedKeys);
}

$memc = $this->getMemcachedResource();
$memc = $this->getMemcachedResource();

foreach ($normalizedKeys as & $normalizedKey) {
$normalizedKey = $this->namespacePrefix . $normalizedKey;
}

$rsCodes = $memc->deleteMulti($normalizedKeys);

$missingKeys = array();
Expand All @@ -479,6 +545,14 @@ protected function internalRemoveItems(array & $normalizedKeys)
}
}

// remove namespace prefix
if ($missingKeys && $this->namespacePrefix !== '') {
$nsPrefixLength = strlen($this->namespacePrefix);
foreach ($missingKeys as & $missingKey) {
$missingKey = substr($missingKey, $nsPrefixLength);
}
}

return $missingKeys;
}

Expand All @@ -492,17 +566,18 @@ protected function internalRemoveItems(array & $normalizedKeys)
*/
protected function internalIncrementItem(& $normalizedKey, & $value)
{
$memc = $this->getMemcachedResource();
$value = (int) $value;
$newValue = $memc->increment($normalizedKey, $value);
$memc = $this->getMemcachedResource();
$internalKey = $this->namespacePrefix . $normalizedKey;
$value = (int) $value;
$newValue = $memc->increment($internalKey, $value);

if ($newValue === false) {
$rsCode = $memc->getResultCode();

// initial value
if ($rsCode == MemcachedResource::RES_NOTFOUND) {
$newValue = $value;
$memc->add($normalizedKey, $newValue, $this->expirationTime());
$memc->add($internalKey, $newValue, $this->expirationTime());
$rsCode = $memc->getResultCode();
}

Expand All @@ -524,17 +599,18 @@ protected function internalIncrementItem(& $normalizedKey, & $value)
*/
protected function internalDecrementItem(& $normalizedKey, & $value)
{
$memc = $this->getMemcachedResource();
$value = (int)$value;
$newValue = $memc->decrement($normalizedKey, $value);
$memc = $this->getMemcachedResource();
$internalKey = $this->namespacePrefix . $normalizedKey;
$value = (int)$value;
$newValue = $memc->decrement($internalKey, $value);

if ($newValue === false) {
$rsCode = $memc->getResultCode();

// initial value
if ($rsCode == MemcachedResource::RES_NOTFOUND) {
$newValue = -$value;
$memc->add($normalizedKey, $newValue, $this->expirationTime());
$memc->add($internalKey, $newValue, $this->expirationTime());
$rsCode = $memc->getResultCode();
}

Expand Down