mirror of
https://github.com/Oreolek/ifhub.club.git
synced 2024-06-26 03:30:48 +03:00
ввод поддержки псевдо мульти-запросов к кешу, в дальнейшем сделать её реальной для memcache
This commit is contained in:
parent
2a1f681886
commit
f38ec56f31
95
classes/lib/external/DklabCache/Cache/Backend/MemcachedMultiload.php
vendored
Normal file
95
classes/lib/external/DklabCache/Cache/Backend/MemcachedMultiload.php
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
/**
|
||||
* Dklab_Cache_Backend_MemcachedMultiload: memcached native backend
|
||||
* with multi-get query support (for faster tag-based operations).
|
||||
*
|
||||
* Note that class uses a dirty hack to fetch the real memcache handle from
|
||||
* a private property of Zend_Cache_Backend_Memcached. No chanse that ZF
|
||||
* developers will do it protected in a next release...
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
require_once "Zend/Cache/Backend/Memcached.php";
|
||||
|
||||
class Dklab_Cache_Backend_MemcachedMultiload extends Zend_Cache_Backend_Memcached
|
||||
{
|
||||
private $_handle;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @see Zend_Cache_Backend_Memcached::__construct()
|
||||
*/
|
||||
public function __construct($options = array())
|
||||
{
|
||||
parent::__construct($options);
|
||||
$this->_handle = self::_getPrivateProp($this, "_memcache");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns native handle.
|
||||
*
|
||||
* @return Memcache Native PHP memcache handle.
|
||||
*/
|
||||
protected function _getHandle()
|
||||
{
|
||||
return $this->_handle;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads an array of items from the memcached.
|
||||
* Extends Zend_Cache_Backend_Memcached with support of multi-get feature.
|
||||
*
|
||||
* @param array $ids A list of IDs to be loaded.
|
||||
* @param bool $doNotTestCacheValidity See parent method.
|
||||
* @return array An array of values for each ID.
|
||||
*/
|
||||
public function multiLoad($ids, $doNotTestCacheValidity = false)
|
||||
{
|
||||
if (!is_array($ids)) {
|
||||
Zend_Cache::throwException('multiLoad() expects parameter 1 to be array, ' . gettype($ids) . ' given');
|
||||
}
|
||||
if ($doNotTestCacheValidity) {
|
||||
$this->_log("Zend_Cache_Backend_Memcached::load() : \$doNotTestCacheValidity=true is unsupported by the Memcached backend");
|
||||
}
|
||||
$tmp = $this->_getHandle()->get($ids);
|
||||
if (!is_array($tmp)) {
|
||||
$tmp=array($tmp);
|
||||
}
|
||||
foreach ($tmp as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
$tmp[$k] = $v[0];
|
||||
}
|
||||
}
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads a private or protected property from the object.
|
||||
* Unfortunately we have to use this hack, because Zend_Cache_Backend_Memcached
|
||||
* does not declare $_memcache handle as protected.
|
||||
*
|
||||
* In PHP private properties are named with \x00 in the name.
|
||||
*
|
||||
* @param object $obj Object to read a property from.
|
||||
* @param string $name Name of a protected or private property.
|
||||
* @return mixed Property value or exception if property is not found.
|
||||
*/
|
||||
private static function _getPrivateProp($obj, $name)
|
||||
{
|
||||
$arraized = (array)$obj;
|
||||
foreach ($arraized as $k => $v) {
|
||||
if (substr($k, -strlen($name)) === $name) {
|
||||
return $v;
|
||||
}
|
||||
}
|
||||
throw new Exception(
|
||||
"Cannot find $name property in Zend_Cache_Backend_Memcached; properties are: "
|
||||
. array_map('addslashes', array_keys($arraized))
|
||||
);
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
* Calls $incrementor each time the code invokes a backend call.
|
||||
* This class may be used in debugging purposes.
|
||||
*
|
||||
* $Id: MetaForm.php 238 2008-03-17 21:07:17Z dk $
|
||||
* $Id$
|
||||
*/
|
||||
require_once "Zend/Cache/Backend/Interface.php";
|
||||
|
||||
|
@ -32,16 +32,37 @@ class Dklab_Cache_Backend_Profiler implements Zend_Cache_Backend_Interface
|
|||
{
|
||||
$t0 = microtime(true);
|
||||
$result = $this->_backend->load($id, $doNotTestCacheValidity);
|
||||
call_user_func($this->_incrementor, microtime(true) - $t0, __METHOD__);
|
||||
call_user_func($this->_incrementor, microtime(true) - $t0, __METHOD__, $id);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function multiLoad($ids, $doNotTestCacheValidity = false)
|
||||
{
|
||||
if (!is_array($ids)) {
|
||||
Zend_Cache::throwException('multiLoad() expects parameter 1 to be array, ' . gettype($ids) . ' given');
|
||||
}
|
||||
if (method_exists($this->_backend, 'multiLoad')) {
|
||||
$t0 = microtime(true);
|
||||
$result = $this->_backend->multiLoad($ids, $doNotTestCacheValidity);
|
||||
call_user_func($this->_incrementor, microtime(true) - $t0, __METHOD__, $ids);
|
||||
return $result;
|
||||
}
|
||||
// No multiLoad() method avalilable, so we have to emulate it to keep
|
||||
// the interface consistent.
|
||||
$result = array();
|
||||
foreach ($ids as $i => $id) {
|
||||
$result[$id] = $this->load($id, $doNotTestCacheValidity);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function test($id)
|
||||
{
|
||||
$t0 = microtime(true);
|
||||
$result = $this->_backend->test($id);
|
||||
call_user_func($this->_incrementor, microtime(true) - $t0, __METHOD__);
|
||||
call_user_func($this->_incrementor, microtime(true) - $t0, __METHOD__, $id);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -50,7 +71,7 @@ class Dklab_Cache_Backend_Profiler implements Zend_Cache_Backend_Interface
|
|||
{
|
||||
$t0 = microtime(true);
|
||||
$result = $this->_backend->save($data, $id, $tags, $specificLifetime);
|
||||
call_user_func($this->_incrementor, microtime(true) - $t0, __METHOD__);
|
||||
call_user_func($this->_incrementor, microtime(true) - $t0, __METHOD__, $id);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -59,7 +80,7 @@ class Dklab_Cache_Backend_Profiler implements Zend_Cache_Backend_Interface
|
|||
{
|
||||
$t0 = microtime(true);
|
||||
$result = $this->_backend->remove($id);
|
||||
call_user_func($this->_incrementor, microtime(true) - $t0, __METHOD__);
|
||||
call_user_func($this->_incrementor, microtime(true) - $t0, __METHOD__, $id);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -68,7 +89,7 @@ class Dklab_Cache_Backend_Profiler implements Zend_Cache_Backend_Interface
|
|||
{
|
||||
$t0 = microtime(true);
|
||||
$result = $this->_backend->clean($mode, $tags);
|
||||
call_user_func($this->_incrementor, microtime(true) - $t0, __METHOD__);
|
||||
call_user_func($this->_incrementor, microtime(true) - $t0, __METHOD__, null);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
* increases the data read cost (the more tags are assigned to a key,
|
||||
* the more read cost becomes).
|
||||
*
|
||||
* $Id: MetaForm.php 238 2008-03-17 21:07:17Z dk $
|
||||
* $Id$
|
||||
*/
|
||||
require_once "Zend/Cache/Backend/Interface.php";
|
||||
|
||||
class Dklab_Cache_Backend_TagEmuWrapper implements Zend_Cache_Backend_Interface
|
||||
{
|
||||
const VERSION = "01";
|
||||
const VERSION = "1.50";
|
||||
|
||||
private $_backend = null;
|
||||
|
||||
|
@ -34,7 +34,7 @@ class Dklab_Cache_Backend_TagEmuWrapper implements Zend_Cache_Backend_Interface
|
|||
return $this->_loadOrTest($id, $doNotTestCacheValidity, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function save($data, $id, $tags = array(), $specificLifetime = false)
|
||||
{
|
||||
// Save/update tags as usual infinite keys with value of tag version.
|
||||
|
@ -84,7 +84,6 @@ class Dklab_Cache_Backend_TagEmuWrapper implements Zend_Cache_Backend_Interface
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Mangles the name to deny intersection of tag keys & data keys.
|
||||
* Mangled tag names are NOT saved in memcache $combined[0] value,
|
||||
|
@ -99,6 +98,22 @@ class Dklab_Cache_Backend_TagEmuWrapper implements Zend_Cache_Backend_Interface
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* The same as _mangleTag(), but mangles a list of tags.
|
||||
*
|
||||
* @see self::_mangleTag
|
||||
* @param array $tags Tags to mangle.
|
||||
* @return array List of mangled tags.
|
||||
*/
|
||||
private function _mangleTags($tags)
|
||||
{
|
||||
foreach ($tags as $i => $tag) {
|
||||
$tags[$i] = $this->_mangleTag($tag);
|
||||
}
|
||||
return $tags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common method called from load() and test().
|
||||
*
|
||||
|
@ -121,11 +136,27 @@ class Dklab_Cache_Backend_TagEmuWrapper implements Zend_Cache_Backend_Interface
|
|||
}
|
||||
// Test if all tags has the same version as when the slot was created
|
||||
// (i.e. still not removed and then recreated).
|
||||
if (is_array($combined[0])) {
|
||||
foreach ($combined[0] as $tag => $savedTagVersion) {
|
||||
$actualTagVersion = $this->_backend->load($this->_mangleTag($tag));
|
||||
if ($actualTagVersion !== $savedTagVersion) {
|
||||
return false;
|
||||
if (is_array($combined[0]) && $combined[0]) {
|
||||
if (method_exists($this->_backend, 'multiLoad')) {
|
||||
// If we have multiLoad(), optimize queries into one.
|
||||
$allMangledTagValues = $this->_backend->multiLoad($this->_mangleTags(array_keys($combined[0])));
|
||||
foreach ($combined[0] as $tag => $savedTagVersion) {
|
||||
$actualTagVersion = @$allMangledTagValues[$this->_mangleTag($tag)];
|
||||
if ($actualTagVersion !== $savedTagVersion) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check all tags versions AND STOP IF WE FOUND AN INCONSISTENT ONE.
|
||||
// Note that this optimization works fine only if $this->_backend is
|
||||
// references to Dklab_Cache_Backend, but NOT via Dklab_Cache_Backend
|
||||
// wrappers, because such wrappers emulate multiLoad() via multiple
|
||||
// load() calls.
|
||||
foreach ($combined[0] as $tag => $savedTagVersion) {
|
||||
$actualTagVersion = $this->_backend->load($this->_mangleTag($tag));
|
||||
if ($actualTagVersion !== $savedTagVersion) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
require_once(DIR_SERVER_ROOT.'/classes/lib/external/DklabCache/config.php');
|
||||
require_once('Zend/Cache.php');
|
||||
require_once('Cache/Backend/MemcachedMultiload.php');
|
||||
require_once('Cache/Backend/TagEmuWrapper.php');
|
||||
require_once('Cache/Backend/Profiler.php');
|
||||
|
||||
|
@ -73,7 +74,7 @@ class LsCache extends Module {
|
|||
} elseif ($this->sCacheType==SYS_CACHE_TYPE_MEMORY) {
|
||||
require_once('Zend/Cache/Backend/Memcached.php');
|
||||
$aConfigMem=include(DIR_SERVER_ROOT."/config/config.memcache.php");
|
||||
$oCahe = new Zend_Cache_Backend_Memcached($aConfigMem);
|
||||
$oCahe = new Dklab_Cache_Backend_MemcachedMultiload($aConfigMem);
|
||||
$this->oBackendCache = new Dklab_Cache_Backend_TagEmuWrapper(new Dklab_Cache_Backend_Profiler($oCahe,array($this,'CalcStats')));
|
||||
} else {
|
||||
throw new Exception($this->Lang_Get('system_error_cache_type').": ".$this->sCacheType." (file, memory)");
|
||||
|
@ -100,13 +101,35 @@ class LsCache extends Module {
|
|||
/**
|
||||
* Т.к. название кеша может быть любым то предварительно хешируем имя кеша
|
||||
*/
|
||||
$sName=md5(SYS_CACHE_PREFIX.$sName);
|
||||
if ($this->sCacheType==SYS_CACHE_TYPE_FILE) {
|
||||
return unserialize($this->oBackendCache->load($sName));
|
||||
if (!is_array($sName)) {
|
||||
$sName=md5(SYS_CACHE_PREFIX.$sName);
|
||||
if ($this->sCacheType==SYS_CACHE_TYPE_FILE) {
|
||||
return unserialize($this->oBackendCache->load($sName));
|
||||
} else {
|
||||
return $this->oBackendCache->load($sName);
|
||||
}
|
||||
} else {
|
||||
return $this->oBackendCache->load($sName);
|
||||
return $this->multiGet($sName);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* псевдо поддержка мульти-запросов к кешу
|
||||
*
|
||||
* @param unknown_type $aName
|
||||
* @return unknown
|
||||
*/
|
||||
public function multiGet($aName) {
|
||||
$aData=array();
|
||||
foreach ($aName as $key => $sName) {
|
||||
if ((false !== ($data = $this->Get($sName)))) {
|
||||
$aData[$sName]=$data;
|
||||
}
|
||||
}
|
||||
if (count($aData)>0) {
|
||||
return $aData;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Записать значение в кеш
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue