mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-26 16:48:49 +01:00
moved egw_cache to Api\Cache
This commit is contained in:
parent
b4b12b2312
commit
9bf4dd288e
744
api/src/Cache.php
Normal file
744
api/src/Cache.php
Normal file
@ -0,0 +1,744 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API: Caching data
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage cache
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2009-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api;
|
||||
|
||||
use egw_exception_db;
|
||||
use egw_exception_wrong_parameter;
|
||||
use egw_session;
|
||||
|
||||
/**
|
||||
* Class to manage caching in eGroupware.
|
||||
*
|
||||
* It allows to cache on 4 levels:
|
||||
* a) tree: for all instances/domains runining on a certain source path
|
||||
* b) instance: for all sessions on a given instance
|
||||
* c) session: for all requests of a session, same as egw_session::appsession()
|
||||
* d) request: just for this request (same as using a static variable)
|
||||
*
|
||||
* There's a get, a set and a unset method for each level: eg. getTree() or setInstance(),
|
||||
* as well as a variant allowing to specify the level as first parameter: eg. unsetCache()
|
||||
*
|
||||
* getXXX($app,$location,$callback=null,array $callback_params,$expiration=0)
|
||||
* has three optional parameters allowing to specify:
|
||||
* 3. a callback if requested data is not yes stored. In that case the callback is called
|
||||
* and it's value is stored in the cache AND retured
|
||||
* 4. parameters to pass to the callback as array, see call_user_func_array
|
||||
* 5. an expiration time in seconds to specify how long data should be cached,
|
||||
* default 0 means infinit (this time is not garantied and not supported for all levels!)
|
||||
*
|
||||
* Data is stored under an application name and a location, like egw_session::appsession().
|
||||
* In fact data stored at cache level Api\Cache::SESSION, is stored in the same way as
|
||||
* egw_session::appsession() so both methods can be used with each other.
|
||||
*
|
||||
* The $app parameter should be either the app or the class name, which both are unique.
|
||||
*
|
||||
* The tree and instance wide cache uses a certain provider class, to store the data
|
||||
* eg. in memcached or if there's nothing else configured in the filesystem (eGW's temp_dir).
|
||||
*
|
||||
* "Admin >> clear cache and register hooks" allways only clears instance level cache of
|
||||
* calling instance. It never clears tree level cache, which makes it important to set
|
||||
* resonable expiry times or think about an other means of clearing that particular item.
|
||||
* (Not clearing of tree-level cache is important, as regenerating it is an expensive
|
||||
* operation for a huge scale EGroupware hosting operation.)
|
||||
*
|
||||
* Apps needing to talk to multiple EGroupware instances (eg. Stylite Managementserver)
|
||||
* can use install_id of instance as $level parameter to (set|get|unset)Cache method.
|
||||
*/
|
||||
class Cache
|
||||
{
|
||||
/**
|
||||
* tree-wide storage
|
||||
*/
|
||||
const TREE = 'Tree';
|
||||
/**
|
||||
* instance-wide storage
|
||||
*/
|
||||
const INSTANCE = 'Instance';
|
||||
/**
|
||||
* session-wide storage
|
||||
*/
|
||||
const SESSION = 'Session';
|
||||
/**
|
||||
* request-wide storage
|
||||
*/
|
||||
const REQUEST = 'Request';
|
||||
|
||||
/**
|
||||
* Default provider for tree and instance data
|
||||
*
|
||||
* Can be specified eg. in the header.inc.php by setting:
|
||||
* $GLOBALS['egw_info']['server']['cache_provider_instance'] and optional
|
||||
* $GLOBALS['egw_info']['server']['cache_provider_tree'] (defaults to instance)
|
||||
*
|
||||
* Default is set (if not set here) after class definition to Cache\Apc or Cache\Files,
|
||||
* depending on function 'apc_fetch' exists or not
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
static $default_provider; // = array('EGroupware\Api\Cache\Files');// array('EGroupware\Api\Cache\Memcache','localhost');
|
||||
|
||||
/**
|
||||
* Maximum expiration time, if set unlimited expiration (=0) or bigger expiration times are replaced with that time
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
static $max_expiration;
|
||||
|
||||
/**
|
||||
* Used to determine keys for tree- and instance-level caches
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
static $egw_server_root = EGW_SERVER_ROOT;
|
||||
|
||||
/**
|
||||
* Add some data in the cache, only if the key does not yet exist
|
||||
*
|
||||
* @param string $level use Api\Cache::(TREE|INSTANCE)
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @param mixed $data
|
||||
* @param int $expiration =0 expiration time in seconds, default 0 = never
|
||||
* @return boolean true if data could be stored, false otherwise incl. key already existed
|
||||
*/
|
||||
static public function addCache($level,$app,$location,$data,$expiration=0)
|
||||
{
|
||||
//error_log(__METHOD__."('$level','$app','$location',".array2string($data).",$expiration)");
|
||||
switch($level)
|
||||
{
|
||||
case self::SESSION:
|
||||
case self::REQUEST:
|
||||
throw new egw_exception_wrong_parameter(__METHOD__."('$level', ...) unsupported level parameter!");
|
||||
|
||||
case self::INSTANCE:
|
||||
case self::TREE:
|
||||
default:
|
||||
if (!($provider = self::get_provider($level)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// limit expiration to configured maximum time
|
||||
if (isset(self::$max_expiration) && (!$expiration || $expiration > self::$max_expiration))
|
||||
{
|
||||
$expiration = self::$max_expiration;
|
||||
}
|
||||
return $provider->add(self::keys($level,$app,$location),$data,$expiration);
|
||||
}
|
||||
throw new egw_exception_wrong_parameter(__METHOD__."() unknown level '$level'!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some data in the cache
|
||||
*
|
||||
* @param string $level use Api\Cache::(TREE|INSTANCE|SESSION|REQUEST)
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @param mixed $data
|
||||
* @param int $expiration =0 expiration time in seconds, default 0 = never
|
||||
* @return boolean true if data could be stored, false otherwise
|
||||
*/
|
||||
static public function setCache($level,$app,$location,$data,$expiration=0)
|
||||
{
|
||||
//error_log(__METHOD__."('$level','$app','$location',".array2string($data).",$expiration)");
|
||||
switch($level)
|
||||
{
|
||||
case self::SESSION:
|
||||
case self::REQUEST:
|
||||
return call_user_func(array(__CLASS__,'set'.$level),$app,$location,$data,$expiration);
|
||||
|
||||
case self::INSTANCE:
|
||||
case self::TREE:
|
||||
default:
|
||||
if (!($provider = self::get_provider($level)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// limit expiration to configured maximum time
|
||||
if (isset(self::$max_expiration) && (!$expiration || $expiration > self::$max_expiration))
|
||||
{
|
||||
$expiration = self::$max_expiration;
|
||||
}
|
||||
return $provider->set(self::keys($level,$app,$location),$data,$expiration);
|
||||
}
|
||||
throw new egw_exception_wrong_parameter(__METHOD__."() unknown level '$level'!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get some data from the cache
|
||||
*
|
||||
* @param string $level use Api\Cache::(TREE|INSTANCE|SESSION|REQUEST)
|
||||
* @param string $app application storing data
|
||||
* @param string|array $location location(s) name for data
|
||||
* @param callback $callback =null callback to get/create the value, if it's not cache
|
||||
* @param array $callback_params =array() array with parameters for the callback
|
||||
* @param int $expiration =0 expiration time in seconds, default 0 = never
|
||||
* @return mixed NULL if data not found in cache (and no callback specified) or
|
||||
* if $location is an array: location => data pairs for existing location-data, non-existing is not returned
|
||||
*/
|
||||
static public function getCache($level,$app,$location,$callback=null,array $callback_params=array(),$expiration=0)
|
||||
{
|
||||
switch($level)
|
||||
{
|
||||
case self::SESSION:
|
||||
case self::REQUEST:
|
||||
foreach((array)$location as $l)
|
||||
{
|
||||
$data[$l] = call_user_func(array(__CLASS__,'get'.$level),$app,$l,$callback,$callback_params,$expiration);
|
||||
}
|
||||
return is_array($location) ? $data : $data[$l];
|
||||
|
||||
case self::INSTANCE:
|
||||
case self::TREE:
|
||||
default:
|
||||
if (!($provider = self::get_provider($level)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
if (is_array($location))
|
||||
{
|
||||
if (!is_null($callback))
|
||||
{
|
||||
throw new egw_exception_wrong_parameter(__METHOD__."() you can NOT use multiple locations (\$location parameter is an array) together with a callback!");
|
||||
}
|
||||
if (is_a($provider, 'EGroupware\Api\Cache\ProviderMultiple'))
|
||||
{
|
||||
$data = $provider->mget($keys=self::keys($level,$app,$location));
|
||||
}
|
||||
else // default implementation calls get multiple times
|
||||
{
|
||||
$data = array();
|
||||
foreach($location as $l)
|
||||
{
|
||||
$data[$l] = $provider->get($keys=self::keys($level,$app,$l));
|
||||
if (!isset($data[$l])) unset($data[$l]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = $provider->get($keys=self::keys($level,$app,$location));
|
||||
if (is_null($data) && !is_null($callback))
|
||||
{
|
||||
$data = call_user_func_array($callback,$callback_params);
|
||||
// limit expiration to configured maximum time
|
||||
if (isset(self::$max_expiration) && (!$expiration || $expiration > self::$max_expiration))
|
||||
{
|
||||
$expiration = self::$max_expiration;
|
||||
}
|
||||
$provider->set($keys,$data,$expiration);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception $e) {
|
||||
unset($e);
|
||||
$data = null;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
throw new egw_exception_wrong_parameter(__METHOD__."() unknown level '$level'!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset some data in the cache
|
||||
*
|
||||
* @param string $level use Api\Cache::(TREE|INSTANCE|SESSION|REQUEST)
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @return boolean true if data was set, false if not (like isset())
|
||||
*/
|
||||
static public function unsetCache($level,$app,$location)
|
||||
{
|
||||
switch($level)
|
||||
{
|
||||
case self::SESSION:
|
||||
case self::REQUEST:
|
||||
return call_user_func(array(__CLASS__,'unset'.$level),$app,$location);
|
||||
|
||||
case self::INSTANCE:
|
||||
case self::TREE:
|
||||
default:
|
||||
if (!($provider = self::get_provider($level, false)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return $provider->delete(self::keys($level,$app,$location));
|
||||
}
|
||||
throw new egw_exception_wrong_parameter(__METHOD__."() unknown level '$level'!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some data in the cache for the whole source tree (all instances)
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @param mixed $data
|
||||
* @param int $expiration =0 expiration time in seconds, default 0 = never
|
||||
* @return boolean true if data could be stored, false otherwise
|
||||
*/
|
||||
static public function setTree($app,$location,$data,$expiration=0)
|
||||
{
|
||||
//error_log(__METHOD__."('$app','$location',".array2string($data).",$expiration)");
|
||||
return self::setCache(self::TREE,$app,$location,$data,$expiration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get some data from the cache for the whole source tree (all instances)
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @param callback $callback =null callback to get/create the value, if it's not cache
|
||||
* @param array $callback_params =array() array with parameters for the callback
|
||||
* @param int $expiration =0 expiration time in seconds, default 0 = never
|
||||
* @return mixed NULL if data not found in cache (and no callback specified)
|
||||
*/
|
||||
static public function getTree($app,$location,$callback=null,array $callback_params=array(),$expiration=0)
|
||||
{
|
||||
return self::getCache(self::TREE,$app,$location,$callback,$callback_params,$expiration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset some data in the cache for the whole source tree (all instances)
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @return boolean true if data was set, false if not (like isset())
|
||||
*/
|
||||
static public function unsetTree($app,$location)
|
||||
{
|
||||
return self::unsetCache(self::TREE,$app,$location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some data in the cache for the whole source tree (all instances)
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @param mixed $data
|
||||
* @param int $expiration =0 expiration time in seconds, default 0 = never
|
||||
* @return boolean true if data could be stored, false otherwise
|
||||
*/
|
||||
static public function setInstance($app,$location,$data,$expiration=0)
|
||||
{
|
||||
return self::setCache(self::INSTANCE,$app,$location,$data,$expiration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get some data from the cache for the whole source tree (all instances)
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @param callback $callback =null callback to get/create the value, if it's not cache
|
||||
* @param array $callback_params =array() array with parameters for the callback
|
||||
* @param int $expiration =0 expiration time in seconds, default 0 = never
|
||||
* @return mixed NULL if data not found in cache (and no callback specified)
|
||||
*/
|
||||
static public function getInstance($app,$location,$callback=null,array $callback_params=array(),$expiration=0)
|
||||
{
|
||||
return self::getCache(self::INSTANCE,$app,$location,$callback,$callback_params,$expiration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset some data in the cache for the whole source tree (all instances)
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @return boolean true if data was set, false if not (like isset())
|
||||
*/
|
||||
static public function unsetInstance($app,$location)
|
||||
{
|
||||
return self::unsetCache(self::INSTANCE,$app,$location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some data in the cache for the whole source tree (all instances)
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @param mixed $data
|
||||
* @param int $expiration =0 expiration time in seconds, default 0 = never
|
||||
* @return boolean true if data could be stored, false otherwise
|
||||
*/
|
||||
static public function setSession($app,$location,$data,$expiration=0)
|
||||
{
|
||||
unset($expiration); // not used, but required by function signature
|
||||
if (isset($_SESSION[egw_session::EGW_SESSION_ENCRYPTED]))
|
||||
{
|
||||
if (egw_session::ERROR_LOG_DEBUG) error_log(__METHOD__.' called after session was encrypted --> ignored!');
|
||||
return false; // can no longer store something in the session, eg. because commit_session() was called
|
||||
}
|
||||
$_SESSION[egw_session::EGW_APPSESSION_VAR][$app][$location] = $data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get some data from the cache for the whole source tree (all instances)
|
||||
*
|
||||
* Returns a reference to the var in the session!
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @param callback $callback =null callback to get/create the value, if it's not cache
|
||||
* @param array $callback_params =array() array with parameters for the callback
|
||||
* @param int $expiration =0 expiration time in seconds, default 0 = never
|
||||
* @return mixed NULL if data not found in cache (and no callback specified)
|
||||
*/
|
||||
static public function &getSession($app,$location,$callback=null,array $callback_params=array(),$expiration=0)
|
||||
{
|
||||
unset($expiration); // not used, but required by function signature
|
||||
if (isset($_SESSION[egw_session::EGW_SESSION_ENCRYPTED]))
|
||||
{
|
||||
if (egw_session::ERROR_LOG_DEBUG) error_log(__METHOD__.' called after session was encrypted --> ignored!');
|
||||
return null; // can no longer store something in the session, eg. because commit_session() was called
|
||||
}
|
||||
if (!isset($_SESSION[egw_session::EGW_APPSESSION_VAR][$app][$location]) && !is_null($callback))
|
||||
{
|
||||
$_SESSION[egw_session::EGW_APPSESSION_VAR][$app][$location] = call_user_func_array($callback,$callback_params);
|
||||
}
|
||||
return $_SESSION[egw_session::EGW_APPSESSION_VAR][$app][$location];
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset some data in the cache for the whole source tree (all instances)
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @return boolean true if data was set, false if not (like isset())
|
||||
*/
|
||||
static public function unsetSession($app,$location)
|
||||
{
|
||||
if (isset($_SESSION[egw_session::EGW_SESSION_ENCRYPTED]))
|
||||
{
|
||||
if (egw_session::ERROR_LOG_DEBUG) error_log(__METHOD__.' called after session was encrypted --> ignored!');
|
||||
return false; // can no longer store something in the session, eg. because commit_session() was called
|
||||
}
|
||||
if (!isset($_SESSION[egw_session::EGW_APPSESSION_VAR][$app][$location]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
unset($_SESSION[egw_session::EGW_APPSESSION_VAR][$app][$location]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static varible to cache request wide
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $request_cache = array();
|
||||
|
||||
/**
|
||||
* Set some data in the cache for the whole source tree (all instances)
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @param mixed $data
|
||||
* @param int $expiration =0 expiration time is NOT used for REQUEST!
|
||||
* @return boolean true if data could be stored, false otherwise
|
||||
*/
|
||||
static public function setRequest($app,$location,$data,$expiration=0)
|
||||
{
|
||||
unset($expiration); // not used, but required by function signature
|
||||
self::$request_cache[$app][$location] = $data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get some data from the cache for the whole source tree (all instances)
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @param callback $callback =null callback to get/create the value, if it's not cache
|
||||
* @param array $callback_params =array() array with parameters for the callback
|
||||
* @param int $expiration =0 expiration time is NOT used for REQUEST!
|
||||
* @return mixed NULL if data not found in cache (and no callback specified)
|
||||
*/
|
||||
static public function getRequest($app,$location,$callback=null,array $callback_params=array(),$expiration=0)
|
||||
{
|
||||
unset($expiration); // not used, but required by function signature
|
||||
if (!isset(self::$request_cache[$app][$location]) && !is_null($callback))
|
||||
{
|
||||
self::$request_cache[$app][$location] = call_user_func_array($callback,$callback_params);
|
||||
}
|
||||
return self::$request_cache[$app][$location];
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset some data in the cache for the whole source tree (all instances)
|
||||
*
|
||||
* @param string $app application storing data
|
||||
* @param string $location location name for data
|
||||
* @return boolean true if data was set, false if not (like isset())
|
||||
*/
|
||||
static public function unsetRequest($app,$location)
|
||||
{
|
||||
if (!isset(self::$request_cache[$app][$location]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
unset(self::$request_cache[$app][$location]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a caching provider for tree or instance level
|
||||
*
|
||||
* The returned provider already has an opened connection
|
||||
*
|
||||
* @param string $level Api\Cache::(TREE|INSTANCE) or install_id
|
||||
* @param boolean $log_not_found =true false do not log if no provider found, used eg. to supress error via unsetCache during installation
|
||||
* @return Api\Cache\Provider
|
||||
*/
|
||||
static protected function get_provider($level, $log_not_found=true)
|
||||
{
|
||||
static $providers = array();
|
||||
|
||||
if ($level != self::TREE) $level = self::INSTANCE;
|
||||
|
||||
if (!isset($providers[$level]))
|
||||
{
|
||||
$params = $GLOBALS['egw_info']['server']['cache_provider_'.strtolower($level)];
|
||||
if (!isset($params) && $level == self::INSTANCE && isset(self::$default_provider))
|
||||
{
|
||||
$params = self::$default_provider;
|
||||
}
|
||||
if (!isset($params))
|
||||
{
|
||||
if ($level == self::TREE) // if no tree level provider use the instance level one
|
||||
{
|
||||
$providers[$level] = self::get_provider(self::INSTANCE);
|
||||
}
|
||||
else
|
||||
{
|
||||
$providers[$level] = false; // no provider specified
|
||||
$reason = 'no provider specified';
|
||||
}
|
||||
}
|
||||
elseif (!$params)
|
||||
{
|
||||
$providers[$level] = false; // cache for $level disabled
|
||||
$reason = "cache for $level disabled";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!is_array($params)) $params = (array)$params;
|
||||
|
||||
$class = array_shift($params);
|
||||
if (!class_exists($class))
|
||||
{
|
||||
$providers[$level] = false; // provider class not found
|
||||
$reason = "provider $class not found";
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
$providers[$level] = new $class($params);
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$providers[$level] = false; // eg. could not open connection to backend
|
||||
$reason = "error instanciating provider $class: ".$e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$providers[$level] && $log_not_found) error_log(__METHOD__."($level) no provider found ($reason)!".function_backtrace());
|
||||
}
|
||||
//error_log(__METHOD__."($level) = ".array2string($providers[$level]).', cache_provider='.array2string($GLOBALS['egw_info']['server']['cache_provider_'.strtolower($level)]));
|
||||
return $providers[$level];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a system configuration, even if in setup and it's not read
|
||||
*
|
||||
* @param string $name
|
||||
* @param boolean $throw =true throw an exception, if we can't retriev the value
|
||||
* @return string|boolean string with config or false if not found and !$throw
|
||||
*/
|
||||
static public function get_system_config($name,$throw=true)
|
||||
{
|
||||
if(!isset($GLOBALS['egw_info']['server'][$name]))
|
||||
{
|
||||
if (isset($GLOBALS['egw_setup']) && isset($GLOBALS['egw_setup']->db) || $GLOBALS['egw']->db)
|
||||
{
|
||||
$db = $GLOBALS['egw']->db ? $GLOBALS['egw']->db : $GLOBALS['egw_setup']->db;
|
||||
|
||||
try {
|
||||
if (($rs = $db->select(config::TABLE,'config_value',array(
|
||||
'config_app' => 'phpgwapi',
|
||||
'config_name' => $name,
|
||||
),__LINE__,__FILE__)))
|
||||
{
|
||||
$GLOBALS['egw_info']['server'][$name] = $rs->fetchColumn();
|
||||
}
|
||||
else
|
||||
{
|
||||
error_log(__METHOD__."('$name', $throw) config value NOT found!");//.function_backtrace());
|
||||
}
|
||||
}
|
||||
catch(egw_exception_db $e)
|
||||
{
|
||||
if ($throw) error_log(__METHOD__."('$name', $throw) cound NOT query value: ".$e->getMessage());//.function_backtrace());
|
||||
}
|
||||
}
|
||||
if (!$GLOBALS['egw_info']['server'][$name] && $throw)
|
||||
{
|
||||
throw new Exception (__METHOD__."($name) \$GLOBALS['egw_info']['server']['$name'] is NOT set!");
|
||||
}
|
||||
}
|
||||
return $GLOBALS['egw_info']['server'][$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush (delete) whole (instance) cache or application/class specific part of it
|
||||
*
|
||||
* @param string $level =self::INSTANCE
|
||||
* @param string $app =null
|
||||
*/
|
||||
static public function flush($level=self::INSTANCE, $app=null)
|
||||
{
|
||||
$ret = true;
|
||||
if (!($provider = self::get_provider($level)))
|
||||
{
|
||||
$ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$provider->flush(self::keys($level, $app)))
|
||||
{
|
||||
if ($level == self::INSTANCE)
|
||||
{
|
||||
self::generate_instance_key();
|
||||
}
|
||||
else
|
||||
{
|
||||
$ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//error_log(__METHOD__."('$level', '$app') returning ".array2string($ret));
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset instance key, so it get read again and re-read install_id from database
|
||||
*/
|
||||
static public function unset_instance_key()
|
||||
{
|
||||
self::$instance_key = null;
|
||||
$GLOBALS['egw_info']['server']['install_id'] = self::get_system_config('install_id', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Key used for instance specific data
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $instance_key;
|
||||
|
||||
/**
|
||||
* Generate a new instance key and by doing so effectivly flushes whole instance cache
|
||||
*
|
||||
* @param string $install_id =null default use install_id of current instance
|
||||
* @return string new key also stored in self::$instance_key
|
||||
*/
|
||||
static public function generate_instance_key($install_id=null)
|
||||
{
|
||||
if (!isset($install_id))
|
||||
{
|
||||
self::$instance_key = null;
|
||||
$install_id = self::get_system_config('install_id');
|
||||
}
|
||||
$instance_key = self::INSTANCE.'-'.$install_id.'-'.microtime(true);
|
||||
self::setTree(__CLASS__, $install_id, $instance_key);
|
||||
|
||||
//error_log(__METHOD__."(install_id='$install_id') returning '".$instance_key."'");
|
||||
return $instance_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get keys array from $level, $app and $location
|
||||
*
|
||||
* @param string $level Api\Cache::(TREE|INSTANCE) or instance_id
|
||||
* @param string $app =null
|
||||
* @param string $location =null
|
||||
* @return array
|
||||
*/
|
||||
static public function keys($level, $app=null, $location=null)
|
||||
{
|
||||
static $tree_key = null;
|
||||
|
||||
switch($level)
|
||||
{
|
||||
case self::TREE:
|
||||
if (!isset($tree_key))
|
||||
{
|
||||
$tree_key = $level.'-'.str_replace(array(':','/','\\'),'-', self::$egw_server_root);
|
||||
// add charset to key, if not utf-8 (as everything we store depends on charset!)
|
||||
if (($charset = self::get_system_config('system_charset',false)) && $charset != 'utf-8')
|
||||
{
|
||||
$tree_key .= '-'.$charset;
|
||||
}
|
||||
}
|
||||
$level_key = $tree_key;
|
||||
break;
|
||||
default: // arbitrary install_id given --> check for current instance
|
||||
if ($level !== $GLOBALS['egw_info']['server']['install_id'])
|
||||
{
|
||||
$level_key = self::getTree(__CLASS__, $level);
|
||||
if (!isset($level_key)) $level_key = self::generate_instance_key($level);
|
||||
break;
|
||||
}
|
||||
// fall-through for current instance
|
||||
case self::INSTANCE:
|
||||
if (!isset(self::$instance_key))
|
||||
{
|
||||
self::$instance_key = self::getTree(__CLASS__, self::get_system_config('install_id'));
|
||||
//error_log(__METHOD__."('$level',...) instance_key read from tree-cache=".array2string(self::$instance_key));
|
||||
if (!isset(self::$instance_key)) self::$instance_key = self::generate_instance_key();
|
||||
}
|
||||
$level_key = self::$instance_key;
|
||||
break;
|
||||
}
|
||||
$keys = array($level_key);
|
||||
if (isset($app))
|
||||
{
|
||||
$keys[] = $app;
|
||||
if (isset($location)) $keys[] = $location;
|
||||
}
|
||||
return $keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Let everyone know the methods of this class should be used only statically
|
||||
*
|
||||
*/
|
||||
function __construct()
|
||||
{
|
||||
throw new egw_exception_wrong_parameter("All methods of class ".__CLASS__." should be called static!");
|
||||
}
|
||||
}
|
||||
|
||||
// setting apc as default provider, if apc_fetch function exists AND further checks in Api\Cache\Apc recommed it
|
||||
if (is_null(Cache::$default_provider))
|
||||
{
|
||||
Cache::$default_provider = function_exists('apc_fetch') && Cache\Apc::available() ?
|
||||
'EGroupware\Api\Cache\Apc' : 'EGroupware\Api\Cache\Files';
|
||||
}
|
||||
|
||||
//error_log('Cache::$default_provider='.array2string(Cache::$default_provider));
|
@ -7,17 +7,19 @@
|
||||
* @package api
|
||||
* @subpackage cache
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2010-15 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2010-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Cache;
|
||||
|
||||
/**
|
||||
* Caching provider storing data in PHP's APC or APCu extension / shared memory.
|
||||
*
|
||||
* The provider concats all $keys with '::' to get a single string.
|
||||
*
|
||||
* This provider is used by default, if it is available or explicit enabled in your header.inc.php:
|
||||
* $GLOBALS['egw_info']['server']['cache_provider_instance'] = array('egw_cache_apc');
|
||||
* $GLOBALS['egw_info']['server']['cache_provider_instance'] = array('EGroupware\Api\Cache\Apc');
|
||||
* and optional also $GLOBALS['egw_info']['server']['cache_provider_tree'] (defaults to instance)
|
||||
*
|
||||
* APC(u) and CLI:
|
||||
@ -25,14 +27,14 @@
|
||||
* APC(u) is not enabled by default for CLI (apc.enable_cli), nor would it access same shared memory!
|
||||
* It makes no sense to fall back to files cache, as this is probably quite outdated,
|
||||
* if PHP via Webserver uses APC. Better to use no cache at all.
|
||||
* egw_cache::get*() will return NULL for not found and egw_cache::[un]set*()
|
||||
* Api\Cache::get*() will return NULL for not found and Api\Cache::[un]set*()
|
||||
* false for not being able to (un)set anything.
|
||||
* It also does not make sense to report failure by throwing an Exception and filling
|
||||
* up cron logs.
|
||||
* --> if APC(u) is available for Webserver, we report availability for CLI too,
|
||||
* but use no cache at all!
|
||||
*/
|
||||
class egw_cache_apc extends egw_cache_provider_check implements egw_cache_provider
|
||||
class Apc extends Base implements Provider
|
||||
{
|
||||
/**
|
||||
* Constructor, eg. opens the connection to the backend
|
206
api/src/Cache/Base.php
Normal file
206
api/src/Cache/Base.php
Normal file
@ -0,0 +1,206 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API: Base class for all caching providers
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage cache
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2009-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Cache;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* Base class for all caching providers
|
||||
*
|
||||
* Implements some checks used for testing providers.
|
||||
*/
|
||||
abstract class Base implements Provider
|
||||
{
|
||||
/**
|
||||
* Run several checks on a caching provider
|
||||
*
|
||||
* @param boolean $verbose =false true: echo failed checks
|
||||
* @return int number of failed checks
|
||||
*/
|
||||
function check($verbose=false)
|
||||
{
|
||||
// set us up as provider for Api\Cache class
|
||||
$GLOBALS['egw_info']['server']['install_id'] = md5(microtime(true));
|
||||
unset($GLOBALS['egw_info']['server']['cache_provider_instance']);
|
||||
unset($GLOBALS['egw_info']['server']['cache_provider_tree']);
|
||||
Api\Cache::$default_provider = get_class($this);
|
||||
|
||||
$failed = 0;
|
||||
foreach(array(
|
||||
Api\Cache::TREE => 'tree',
|
||||
Api\Cache::INSTANCE => 'instance',
|
||||
) as $level => $label)
|
||||
{
|
||||
$locations = array();
|
||||
foreach(array('string',123,true,false,null,array(),array(1,2,3)) as $data)
|
||||
{
|
||||
$location = md5(microtime(true).$label.serialize($data));
|
||||
$get_before_set = $this->get(array($level,__CLASS__,$location));
|
||||
if (!is_null($get_before_set))
|
||||
{
|
||||
if ($verbose) echo "$label: get_before_set=".array2string($get_before_set)." != NULL\n";
|
||||
++$failed;
|
||||
}
|
||||
if (($set = $this->set(array($level,__CLASS__,$location), $data, 10)) !== true)
|
||||
{
|
||||
if ($verbose) echo "$label: set returned ".array2string($set)." !== TRUE\n";
|
||||
++$failed;
|
||||
}
|
||||
$get_after_set = $this->get(array($level,__CLASS__,$location));
|
||||
if ($get_after_set !== $data)
|
||||
{
|
||||
if ($verbose) echo "$label: get_after_set=".array2string($get_after_set)." !== ".array2string($data)."\n";
|
||||
++$failed;
|
||||
}
|
||||
if (is_a($this, 'EGroupware\Api\Cache\ProviderMultiple'))
|
||||
{
|
||||
$mget_after_set = $this->mget(array($level,__CLASS__,array($location)));
|
||||
if ($mget_after_set[$location] !== $data)
|
||||
{
|
||||
if ($verbose) echo "$label: mget_after_set['$location']=".array2string($mget_after_set[$location])." !== ".array2string($data)."\n";
|
||||
++$failed;
|
||||
}
|
||||
}
|
||||
$add_after_set = $this->add(array($level,__CLASS__,$location), 'other-data');
|
||||
if ($add_after_set !== false)
|
||||
{
|
||||
if ($verbose) echo "$label: add_after_set=".array2string($add_after_set)."\n";
|
||||
++$failed;
|
||||
}
|
||||
if (($delete = $this->delete(array($level,__CLASS__,$location))) !== true)
|
||||
{
|
||||
if ($verbose) echo "$label: delete returned ".array2string($delete)." !== TRUE\n";
|
||||
++$failed;
|
||||
}
|
||||
$get_after_delete = $this->get(array($level,__CLASS__,$location));
|
||||
if (!is_null($get_after_delete))
|
||||
{
|
||||
if ($verbose) echo "$label: get_after_delete=".array2string($get_after_delete)." != NULL\n";
|
||||
++$failed;
|
||||
}
|
||||
// prepare for mget of everything
|
||||
if (is_a($this, 'EGroupware\Api\Cache\ProviderMultiple'))
|
||||
{
|
||||
$locations[$location] = $data;
|
||||
$mget_after_delete = $this->mget(array($level,__CLASS__,array($location)));
|
||||
if (isset($mget_after_delete[$location]))
|
||||
{
|
||||
if ($verbose) echo "$label: mget_after_delete['$location']=".array2string($mget_after_delete[$location])." != NULL\n";
|
||||
++$failed;
|
||||
}
|
||||
}
|
||||
elseif (!is_null($data)) // emulation can NOT distinquish between null and not set
|
||||
{
|
||||
$locations[$location] = $data;
|
||||
}
|
||||
$add_after_delete = $this->add(array($level,__CLASS__,$location), $data, 10);
|
||||
if ($add_after_delete !== true)
|
||||
{
|
||||
if ($verbose) echo "$label: add_after_delete=".array2string($add_after_delete)."\n";
|
||||
++$failed;
|
||||
}
|
||||
else
|
||||
{
|
||||
$get_after_add = $this->get(array($level,__CLASS__,$location));
|
||||
if ($get_after_add !== $data)
|
||||
{
|
||||
if ($verbose) echo "$label: get_after_add=".array2string($get_after_add)." !== ".array2string($data)."\n";
|
||||
++$failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
// get all above in one request
|
||||
$keys = array_keys($locations);
|
||||
$keys_bogus = array_merge(array('not-set'),array_keys($locations),array('not-set-too'));
|
||||
if (is_a($this, 'EGroupware\Api\Cache\ProviderMultiple'))
|
||||
{
|
||||
$mget = $this->mget(array($level,__CLASS__,$keys));
|
||||
$mget_bogus = $this->mget(array($level,__CLASS__,$keys_bogus));
|
||||
/* Api\Cache::getCache() gives a different result, as it does NOT use $level direkt
|
||||
}
|
||||
else
|
||||
{
|
||||
$mget = Api\Cache::getCache($level, __CLASS__, $keys);
|
||||
$mget_bogus = Api\Cache::getCache($level, __CLASS__, $keys_bogus);
|
||||
}*/
|
||||
if ($mget !== $locations)
|
||||
{
|
||||
if ($verbose) echo "$label: mget=\n".array2string($mget)." !==\n".array2string($locations)."\n";
|
||||
++$failed;
|
||||
}
|
||||
if ($mget_bogus !== $locations)
|
||||
{
|
||||
if ($verbose) echo "$label: mget(".array2string($keys_bogus).")=\n".array2string($mget_bogus)." !==\n".array2string($locations)."\n";
|
||||
++$failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $failed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all data under given keys
|
||||
*
|
||||
* Providers can return false, if they do not support flushing part of the cache (eg. memcache)
|
||||
*
|
||||
* @param array $keys eg. array($level,$app,$location)
|
||||
* @return boolean true on success, false on error (eg. $key not set)
|
||||
*/
|
||||
function flush(array $keys)
|
||||
{
|
||||
unset($keys); // required by function signature
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// some testcode, if this file is called via it's URL
|
||||
// can be run on command-line: sudo php -d apc.enable_cli=1 -f api/src/Cache/Base.php
|
||||
/*if (isset($_SERVER['SCRIPT_FILENAME']) && realpath($_SERVER['SCRIPT_FILENAME']) == __FILE__)
|
||||
{
|
||||
if (!isset($_SERVER['HTTP_HOST']))
|
||||
{
|
||||
chdir(dirname(__FILE__)); // to enable our relative pathes to work
|
||||
}
|
||||
$GLOBALS['egw_info'] = array(
|
||||
'flags' => array(
|
||||
'noapi' => true,
|
||||
),
|
||||
);
|
||||
include_once '../../../header.inc.php';
|
||||
|
||||
if (isset($_SERVER['HTTP_HOST'])) echo "<pre style='whitespace: nowrap'>\n";
|
||||
|
||||
foreach(array(
|
||||
'EGroupware\Api\Cache\Apc' => array(),
|
||||
'EGroupware\Api\Cache\Memcache' => array('localhost'),
|
||||
'EGroupware\Api\Cache\Files' => array('/tmp'),
|
||||
) as $class => $param)
|
||||
{
|
||||
echo "Checking $class:\n";
|
||||
try {
|
||||
$start = microtime(true);
|
||||
$provider = new $class($param);
|
||||
$n = 100;
|
||||
for($i=1; $i <= $n; ++$i)
|
||||
{
|
||||
$failed = $provider->check($i == 1);
|
||||
}
|
||||
printf("$failed checks failed, $n iterations took %5.3f sec\n\n", microtime(true)-$start);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
printf($e->getMessage()."\n\n");
|
||||
}
|
||||
}
|
||||
}*/
|
@ -7,17 +7,21 @@
|
||||
* @package api
|
||||
* @subpackage cache
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2009-15 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2009-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Cache;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* Caching provider storing data in files
|
||||
*
|
||||
* The provider creates subdirs under a given path
|
||||
* for each values in $key
|
||||
*/
|
||||
class egw_cache_files extends egw_cache_provider_check implements egw_cache_provider
|
||||
class Files extends Base implements Provider
|
||||
{
|
||||
/**
|
||||
* Extension of file used to store expiration > 0
|
||||
@ -45,7 +49,7 @@ class egw_cache_files extends egw_cache_provider_check implements egw_cache_prov
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->base_path = egw_cache::get_system_config('temp_dir', false);
|
||||
$this->base_path = Api\Cache::get_system_config('temp_dir', false);
|
||||
if (isset($this->base_path)) $this->base_path .= '/egw_cache';
|
||||
}
|
||||
if (!isset($this->base_path) || !file_exists($this->base_path) && !mkdir($this->base_path,0700,true))
|
@ -7,24 +7,26 @@
|
||||
* @package api
|
||||
* @subpackage cache
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2009-15 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2009-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Cache;
|
||||
|
||||
/**
|
||||
* Caching provider storing data in memcached via PHP's memcache extension
|
||||
*
|
||||
* The provider concats all $keys with '::' to get a single string.
|
||||
*
|
||||
* To use this provider set in your header.inc.php:
|
||||
* $GLOBALS['egw_info']['server']['cache_provider_instance'] = array('egw_cache_memcache','localhost'[,'otherhost:port']);
|
||||
* $GLOBALS['egw_info']['server']['cache_provider_instance'] = array('EGroupware\Api\Cache\Memcache','localhost'[,'otherhost:port']);
|
||||
* and optional also $GLOBALS['egw_info']['server']['cache_provider_tree'] (defaults to instance)
|
||||
*
|
||||
* You can set more then one server and specify a port, if it's not the default one 11211.
|
||||
*
|
||||
* If igbinary extension is available, it is prefered over PHP (un)serialize.
|
||||
*/
|
||||
class egw_cache_memcache extends egw_cache_provider_check implements egw_cache_provider_multiple
|
||||
class Memcache extends Base implements ProviderMultiple
|
||||
{
|
||||
/**
|
||||
* Instance of Memcache
|
@ -7,17 +7,19 @@
|
||||
* @package api
|
||||
* @subpackage cache
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2009-15 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2009-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Cache;
|
||||
|
||||
/**
|
||||
* Caching provider storing data in memcached via PHP's memcached extension
|
||||
*
|
||||
* The provider concats all $keys with '::' to get a single string.
|
||||
*
|
||||
* To use this provider set in your header.inc.php:
|
||||
* $GLOBALS['egw_info']['server']['cache_provider_instance'] = array('egw_cache_memcached','localhost'[,'otherhost:port']);
|
||||
* $GLOBALS['egw_info']['server']['cache_provider_instance'] = array('EGroupware\Api\Cache\Memcached','localhost'[,'otherhost:port']);
|
||||
* and optional also $GLOBALS['egw_info']['server']['cache_provider_tree'] (defaults to instance)
|
||||
*
|
||||
* You can set more then one server and specify a port, if it's not the default one 11211.
|
||||
@ -26,7 +28,7 @@
|
||||
*
|
||||
* If igbinary extension is available, it is prefered over PHP (un)serialize.
|
||||
*/
|
||||
class egw_cache_memcached extends egw_cache_provider_check implements egw_cache_provider_multiple
|
||||
class Memcached extends Base implements ProviderMultiple
|
||||
{
|
||||
/**
|
||||
* Instance of Memcached
|
78
api/src/Cache/Provider.php
Normal file
78
api/src/Cache/Provider.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API: Caching provider interface
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage cache
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2009-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Cache;
|
||||
|
||||
/**
|
||||
* Interface for a caching provider for tree and instance level
|
||||
*
|
||||
* The provider can eg. create subdirs under /tmp for each key
|
||||
* to store data as a file or concat them with a separator to
|
||||
* get a single string key to eg. store data in memcached
|
||||
*/
|
||||
interface Provider
|
||||
{
|
||||
/**
|
||||
* Constructor, eg. opens the connection to the backend
|
||||
*
|
||||
* @throws Exception if connection to backend could not be established
|
||||
* @param array $params eg. array(host,port) or array(directory) depending on the provider
|
||||
*/
|
||||
function __construct(array $params);
|
||||
|
||||
/**
|
||||
* Stores some data in the cache, if it does NOT already exists there
|
||||
*
|
||||
* @param array $keys eg. array($level,$app,$location)
|
||||
* @param mixed $data
|
||||
* @param int $expiration =0
|
||||
* @return boolean true on success, false on error, incl. key already exists in cache
|
||||
*/
|
||||
function add(array $keys,$data,$expiration=0);
|
||||
|
||||
/**
|
||||
* Stores some data in the cache
|
||||
*
|
||||
* @param array $keys eg. array($level,$app,$location)
|
||||
* @param mixed $data
|
||||
* @param int $expiration =0
|
||||
* @return boolean true on success, false on error
|
||||
*/
|
||||
function set(array $keys,$data,$expiration=0);
|
||||
|
||||
/**
|
||||
* Get some data from the cache
|
||||
*
|
||||
* @param array $keys eg. array($level,$app,$location)
|
||||
* @return mixed data stored or NULL if not found in cache
|
||||
*/
|
||||
function get(array $keys);
|
||||
|
||||
/**
|
||||
* Delete some data from the cache
|
||||
*
|
||||
* @param array $keys eg. array($level,$app,$location)
|
||||
* @return boolean true on success, false on error (eg. $key not set)
|
||||
*/
|
||||
function delete(array $keys);
|
||||
|
||||
/**
|
||||
* Delete all data under given keys
|
||||
*
|
||||
* Providers can return false, if they do not support flushing part of the cache (eg. memcache)
|
||||
*
|
||||
* @param array $keys eg. array($level,$app,$location)
|
||||
* @return boolean true on success, false on error (eg. $key not set)
|
||||
*/
|
||||
function flush(array $keys);
|
||||
}
|
28
api/src/Cache/ProviderMultiple.php
Normal file
28
api/src/Cache/ProviderMultiple.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API: Caching data
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage cache
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2009-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Cache;
|
||||
|
||||
/**
|
||||
* Interface for a caching provider being able to retrieve multiple entires
|
||||
*/
|
||||
interface ProviderMultiple
|
||||
{
|
||||
/**
|
||||
* Get multiple data from the cache
|
||||
*
|
||||
* @param array $keys eg. array of array($level,$app,array $locations)
|
||||
* @return array key => data stored, not found keys are NOT returned
|
||||
*/
|
||||
function mget(array $keys);
|
||||
}
|
@ -13,7 +13,6 @@
|
||||
|
||||
namespace EGroupware\Api;
|
||||
|
||||
use egw_cache;
|
||||
use egw_exception_db_connection;
|
||||
use egw_exception_db_invalid_sql;
|
||||
use egw_exception_wrong_parameter;
|
||||
@ -406,7 +405,7 @@ class Db
|
||||
{
|
||||
$hosts = explode(';', $this->Host[0] == '@' ? getenv(substr($this->Host, 1)) : $this->Host);
|
||||
$num_hosts = count($hosts);
|
||||
$n =& egw_cache::getSession(__CLASS__, $this->Host);
|
||||
$n =& Cache::getSession(__CLASS__, $this->Host);
|
||||
if (!isset($n)) $n = 0;
|
||||
|
||||
if ($next && ++$n >= $num_hosts+2)
|
||||
|
@ -14,8 +14,8 @@
|
||||
namespace EGroupware\Api\Db;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
use egw_exception_db_invalid_sql;
|
||||
use egw_cache;
|
||||
use config;
|
||||
use translation;
|
||||
use html;
|
||||
@ -493,9 +493,9 @@ class Backup
|
||||
return lang('Restore failed');
|
||||
}
|
||||
}
|
||||
// generate an install_id if we dont have one (it breaks egw_cache::flush() stalling the upgrade)
|
||||
// generate an install_id if we dont have one (it breaks Api\Cache::flush() stalling the upgrade)
|
||||
unset($GLOBALS['egw_info']['server']['install_id']);
|
||||
if (!($GLOBALS['egw_info']['server']['install_id'] = egw_cache::get_system_config('install_id', false)))
|
||||
if (!($GLOBALS['egw_info']['server']['install_id'] = Api\Cache::get_system_config('install_id', false)))
|
||||
{
|
||||
$GLOBALS['egw_info']['server']['install_id'] = md5(microtime(true).$_SERVER['HTTP_HOST']);
|
||||
$this->db->insert('egw_config', array(
|
||||
@ -506,7 +506,7 @@ class Backup
|
||||
), __LINE__, __FILE__);
|
||||
}
|
||||
// flush instance cache
|
||||
egw_cache::flush(egw_cache::INSTANCE);
|
||||
Api\Cache::flush(Api\Cache::INSTANCE);
|
||||
|
||||
// search-and-register-hooks
|
||||
$GLOBALS['egw']->hooks->register_all_hooks();
|
||||
|
@ -27,7 +27,6 @@ use egw_exception_wrong_parameter;
|
||||
use egw_exception_wrong_userinput;
|
||||
use egw_exception;
|
||||
use egw_time;
|
||||
use egw_cache;
|
||||
|
||||
/**
|
||||
* Class containing static methods to use the new eGW virtual file system
|
||||
@ -987,7 +986,7 @@ class Vfs extends Vfs\StreamWrapper
|
||||
{
|
||||
if ($session_only)
|
||||
{
|
||||
$session_eacls =& egw_cache::getSession(__CLASS__, self::SESSION_EACL);
|
||||
$session_eacls =& Cache::getSession(__CLASS__, self::SESSION_EACL);
|
||||
$session_eacls[] = array(
|
||||
'path' => $url[0] == '/' ? $url : self::parse_url($url, PHP_URL_PATH),
|
||||
'owner' => $owner ? $owner : self::$user,
|
||||
@ -1010,7 +1009,7 @@ class Vfs extends Vfs\StreamWrapper
|
||||
{
|
||||
$eacls = self::_call_on_backend('get_eacl',array($path),true); // true = fail silent (no PHP Warning)
|
||||
|
||||
$session_eacls =& egw_cache::getSession(__CLASS__, self::SESSION_EACL);
|
||||
$session_eacls =& Cache::getSession(__CLASS__, self::SESSION_EACL);
|
||||
if ($session_eacls)
|
||||
{
|
||||
// eacl is recursive, therefore we have to match all parent-dirs too
|
||||
|
@ -7,19 +7,18 @@
|
||||
* @package api
|
||||
* @subpackage vfs
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2008-15 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2008-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Vfs\Sqlfs;
|
||||
|
||||
use EGroupware\Api\Vfs;
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old phpgwapi classes used:
|
||||
use egw_cache;
|
||||
use mime_magic;
|
||||
use config;
|
||||
use translation;
|
||||
use egw_exception_db;
|
||||
use egw_exception_wrong_parameter;
|
||||
use egw_exception_assertion_failed;
|
||||
@ -186,7 +185,7 @@ class StreamWrapper implements Vfs\StreamWrapperIface
|
||||
|
||||
self::$stat_cache = array();
|
||||
|
||||
egw_cache::setSession(self::EACL_APPNAME, 'extended_acl', self::$extended_acl = null);
|
||||
Api\Cache::setSession(self::EACL_APPNAME, 'extended_acl', self::$extended_acl = null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1377,7 +1376,7 @@ class StreamWrapper implements Vfs\StreamWrapperIface
|
||||
*/
|
||||
static protected function _read_extended_acl()
|
||||
{
|
||||
if ((self::$extended_acl = egw_cache::getSession(self::EACL_APPNAME, 'extended_acl')))
|
||||
if ((self::$extended_acl = Api\Cache::getSession(self::EACL_APPNAME, 'extended_acl')))
|
||||
{
|
||||
return; // ext. ACL read from session.
|
||||
}
|
||||
@ -1398,7 +1397,7 @@ class StreamWrapper implements Vfs\StreamWrapperIface
|
||||
uksort(self::$extended_acl, function($a,$b) {
|
||||
return strlen($b)-strlen($a);
|
||||
});
|
||||
egw_cache::setSession(self::EACL_APPNAME, 'extended_acl', self::$extended_acl);
|
||||
Api\Cache::setSession(self::EACL_APPNAME, 'extended_acl', self::$extended_acl);
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__.'() '.array2string(self::$extended_acl));
|
||||
}
|
||||
|
||||
@ -1464,7 +1463,7 @@ class StreamWrapper implements Vfs\StreamWrapperIface
|
||||
}
|
||||
if ($ret)
|
||||
{
|
||||
egw_cache::setSession(self::EACL_APPNAME, 'extended_acl', self::$extended_acl);
|
||||
Api\Cache::setSession(self::EACL_APPNAME, 'extended_acl', self::$extended_acl);
|
||||
}
|
||||
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($path,$rights,$owner,$fs_id)=".(int)$ret);
|
||||
return $ret;
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user