Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1031629
cache.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Jun 17, 6:03 PM
Size
25 KB
Mime Type
text/x-php
Expires
Thu, Jun 19, 6:03 PM (51 m, 38 s)
Engine
blob
Format
Raw Data
Handle
666338
Attached To
rINP In-Portal
cache.php
View Options
<?php
/**
* @version $Id: cache.php 16772 2023-11-22 08:42:00Z alex $
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined
(
'FULL_PATH'
)
or
die
(
'restricted access!'
);
/**
* Manager of all implemented caching handlers
*
*/
class
kCache
extends
kBase
{
/**
* Rebuild cache now
*
*/
const
REBUILD_NOW
=
1
;
/**
* Rebuild cache later
*
*/
const
REBUILD_LATER
=
2
;
/**
* Cache waiting step (in seconds)
*
*/
const
WAIT_STEP
=
2
;
/**
* Object of cache handler
*
* @var FakeCacheHandler
*/
var
$_handler
=
null
;
/**
* Part of what we retrieve will be stored locally (per script run) not to bother memcache a lot
*
* @var Array
*/
var
$_localStorage
=
Array
();
/**
* What type of caching is being used
*
* @var int
*/
var
$cachingType
=
CACHING_TYPE_NONE
;
/**
* Debug cache usage
*
* @var bool
*/
var
$debugCache
=
false
;
/**
* Displays cache usage statistics
*
* @var bool
* @access protected
*/
protected
$_storeStatistics
=
false
;
/**
* Site key name
* Prepended to each cached key name
*
* @var string
*/
var
$siteKeyName
=
''
;
/**
* Site key value
* Prepended to each cached key name
*
* @var string
*/
var
$siteKeyValue
=
null
;
/**
* Cache prefix.
*
* @var string
*/
protected
$cachePrefix
=
''
;
/**
* Maximum cache duration.
*
* @var integer
*/
protected
$maxCacheDuration
;
/**
* Creates cache manager
*
* @param integer $max_cache_duration Maximum cache duration.
*/
public
function
__construct
(
$max_cache_duration
)
{
parent
::
__construct
();
$this
->
maxCacheDuration
=
$max_cache_duration
;
$this
->
siteKeyName
=
'site_serial:'
.
crc32
(
SQL_TYPE
.
'://'
.
SQL_USER
.
':'
.
SQL_PASS
.
'@'
.
SQL_SERVER
.
':'
.
TABLE_PREFIX
.
':'
.
SQL_DB
);
// get cache handler class to use
$handler_class
=
kUtil
::
getSystemConfig
()->
get
(
'CacheHandler'
,
''
)
.
'CacheHandler'
;
// defined cache handler doesn't exist -> use default
if
(
!
class_exists
(
$handler_class
)
)
{
$handler_class
=
'FakeCacheHandler'
;
}
$handler
=
new
$handler_class
(
$this
);
if
(
!
$handler
->
isWorking
()
)
{
// defined cache handler is not working -> use default
trigger_error
(
'Failed to initialize "<strong>'
.
$handler_class
.
'</strong>" caching handler.'
,
E_USER_WARNING
);
$handler
=
new
FakeCacheHandler
(
$this
);
}
elseif
(
$this
->
Application
->
isDebugMode
()
&&
(
$handler
->
getCachingType
()
==
CACHING_TYPE_MEMORY
)
)
{
$this
->
Application
->
Debugger
->
appendHTML
(
'Memory Caching: "<strong>'
.
$handler_class
.
'</strong>"'
);
}
$this
->
_handler
=
$handler
;
$this
->
cachingType
=
$handler
->
getCachingType
();
$this
->
debugCache
=
$handler
->
getCachingType
()
==
CACHING_TYPE_MEMORY
&&
$this
->
Application
->
isDebugMode
();
$this
->
_storeStatistics
=
defined
(
'DBG_CACHE'
)
&&
DBG_CACHE
;
$this
->
cachePrefix
=
$this
->
_cachePrefix
();
if
(
$this
->
_storeStatistics
)
{
// don't use FileHelper, since kFactory isn't ready yet
if
(
!
file_exists
(
RESTRICTED
.
DIRECTORY_SEPARATOR
.
'cache_usage'
)
)
{
mkdir
(
RESTRICTED
.
DIRECTORY_SEPARATOR
.
'cache_usage'
);
}
}
}
/**
* Returns caching type of current storage engine
*
* @return int
*/
function
getCachingType
()
{
return
$this
->
cachingType
;
}
/**
* Stores new $value in cache with $name name.
*
* @param string $name Key name to add to cache.
* @param mixed $value Value of cached record.
* @param integer|null $expiration When value expires (0 - doesn't expire).
*
* @return boolean
*/
function
setCache
(
$name
,
$value
,
$expiration
=
null
)
{
if
(
$expiration
===
null
)
{
$expiration
=
$this
->
maxCacheDuration
;
}
// 1. stores current version of serial for given cache key
$this
->
_setCache
(
$name
.
'_serials'
,
$this
->
replaceSerials
(
$name
),
$expiration
);
$this
->
storeStatistics
(
$name
,
'W'
);
// 2. don't replace serials within the key
$saved
=
$this
->
_setCache
(
$name
,
$value
,
$expiration
);
$this
->
storeStatistics
(
$name
,
'U'
);
// 3. remove rebuilding mark
$this
->
delete
(
$name
.
'_rebuilding'
);
return
$saved
;
}
/**
* Stores value to cache
*
* @param string $name
* @param mixed $value
* @param int $expiration cache record expiration time in seconds
* @return bool
*/
function
_setCache
(
$name
,
$value
,
$expiration
)
{
$prepared_name
=
$this
->
prepareKeyName
(
$name
);
$this
->
_localStorage
[
$prepared_name
]
=
$value
;
return
$this
->
_handler
->
set
(
$prepared_name
,
$value
,
$expiration
);
}
/**
* Stores value to cache (only if it's not there already).
*
* @param string $name Key name to add to cache.
* @param mixed $value Value of cached record.
* @param integer|null $expiration When value expires (0 - doesn't expire).
*
* @return boolean
*/
function
addCache
(
$name
,
$value
,
$expiration
=
null
)
{
if
(
$expiration
===
null
)
{
$expiration
=
$this
->
maxCacheDuration
;
}
// 1. stores current version of serial for given cache key
$this
->
_setCache
(
$name
.
'_serials'
,
$this
->
replaceSerials
(
$name
),
$expiration
);
// 2. remove rebuilding mark
$this
->
delete
(
$name
.
'_rebuilding'
);
// 3. don't replace serials within the key
return
$this
->
_addCache
(
$name
,
$value
,
$expiration
);
}
/**
* Stores value to cache (only if it's not there already)
*
* @param string $name
* @param mixed $value
* @param int $expiration cache record expiration time in seconds
* @return bool
*/
function
_addCache
(
$name
,
$value
,
$expiration
)
{
$prepared_name
=
$this
->
prepareKeyName
(
$name
);
$added
=
$this
->
_handler
->
add
(
$prepared_name
,
$value
,
$expiration
);
if
(
$added
)
{
$this
->
_localStorage
[
$prepared_name
]
=
$value
;
}
return
$added
;
}
/**
* Sets rebuilding mode for given cache
*
* @param string $name
* @param int $mode
* @param int $max_rebuilding_time
* @param string $miss_type
* @return bool
*/
function
rebuildCache
(
$name
,
$mode
=
null
,
$max_rebuilding_time
=
0
,
$miss_type
=
'M'
)
{
if
(
!
isset
(
$mode
)
||
$mode
==
self
::
REBUILD_NOW
)
{
$this
->
storeStatistics
(
$name
,
$miss_type
);
if
(
!
$max_rebuilding_time
)
{
return
true
;
}
// prevent parallel rebuild attempt by using "add" instead of "set" method
if
(
!
$this
->
_addCache
(
$name
.
'_rebuilding'
,
1
,
$max_rebuilding_time
)
)
{
$this
->
storeStatistics
(
$name
,
'l'
);
return
false
;
}
$this
->
storeStatistics
(
$name
,
'L'
);
$this
->
delete
(
$name
.
'_rebuild'
);
}
elseif
(
$mode
==
self
::
REBUILD_LATER
)
{
$this
->
_setCache
(
$name
.
'_rebuild'
,
1
,
0
);
$this
->
delete
(
$name
.
'_rebuilding'
);
}
return
true
;
}
/**
* Returns value from cache
*
* @param string $name
* @param bool $store_locally store data locally after retrieved
* @param int $max_rebuild_seconds
* @return mixed
*/
function
getCache
(
$name
,
$store_locally
=
true
,
$max_rebuild_seconds
=
0
)
{
$cached_data
=
$this
->
_getCache
(
Array
(
$name
.
'_rebuild'
,
$name
.
'_serials'
),
Array
(
true
,
true
));
if
(
$cached_data
[
$name
.
'_rebuild'
]
)
{
// cache rebuild requested -> rebuild now
$this
->
delete
(
$name
.
'_rebuild'
);
if
(
$this
->
rebuildCache
(
$name
,
self
::
REBUILD_NOW
,
$max_rebuild_seconds
,
'[M1]'
)
)
{
return
false
;
}
}
// There are 2 key types:
// - with serials, e.g. with_serial_key[%LangSerial%]
// - without serials, e.g. without_serial
// Evaluated serials of each cache key are stored in '{$name}_serials' cache key.
// If cache is present, but serial is outdated, then cache value is assumed to be outdated.
$new_serial
=
$this
->
replaceSerials
(
$name
);
$old_serial
=
$cached_data
[
$name
.
'_serials'
];
if
(
$name
==
$new_serial
||
$new_serial
!=
$old_serial
)
{
// no serials in cache key OR cache is outdated
$wait_seconds
=
$max_rebuild_seconds
;
while
(
true
)
{
$cached_data
=
$this
->
_getCache
(
Array
(
$name
,
$name
.
'_rebuilding'
),
Array
(
$store_locally
,
false
));
$cache
=
$cached_data
[
$name
];
$rebuilding
=
$cached_data
[
$name
.
'_rebuilding'
];
if
(
(
$cache
===
false
)
&&
(!
$rebuilding
||
$wait_seconds
==
0
)
)
{
// cache missing and nobody rebuilding it -> rebuild; enough waiting for cache to be ready
$this
->
rebuildCache
(
$name
,
self
::
REBUILD_NOW
,
$max_rebuild_seconds
,
'[M2'
.
(
$rebuilding
?
'R'
:
'!R'
)
.
',WS='
.
$wait_seconds
.
']'
);
return
false
;
}
elseif
(
$cache
!==
false
)
{
// re-read serial, since it might have been changed in parallel process !!!
$old_serial
=
$this
->
_getCache
(
$name
.
'_serials'
,
false
);
// cache present (if other user is rebuilding it, then it's outdated cache) -> return it
if
(
$rebuilding
||
$new_serial
==
$old_serial
)
{
$this
->
storeStatistics
(
$name
,
$rebuilding
?
'h'
:
'H'
);
return
$cache
;
}
$this
->
rebuildCache
(
$name
,
self
::
REBUILD_NOW
,
$max_rebuild_seconds
,
'[M3'
.
(
$rebuilding
?
'R'
:
'!R'
)
.
',WS='
.
$wait_seconds
.
']'
);
return
false
;
}
$wait_seconds
-=
self
::
WAIT_STEP
;
sleep
(
self
::
WAIT_STEP
);
}
}
$cache
=
$this
->
_getCache
(
$name
,
$store_locally
);
if
(
$cache
===
false
)
{
$this
->
rebuildCache
(
$name
,
self
::
REBUILD_NOW
,
$max_rebuild_seconds
,
'[M4]'
);
}
else
{
$this
->
storeStatistics
(
$name
,
'H'
);
}
return
$cache
;
}
/**
* Returns cached value from local cache
*
* @param string $prepared_name Prepared key name from kCache::prepareKeyName() function
* @return mixed
* @see prepareKeyName
* @access public
*/
public
function
getFromLocalStorage
(
$prepared_name
)
{
return
array_key_exists
(
$prepared_name
,
$this
->
_localStorage
)
?
$this
->
_localStorage
[
$prepared_name
]
:
false
;
}
/**
* Returns value from cache
*
* @param string|Array $names
* @param bool|Array $store_locally store data locally after retrieved
* @return mixed
*/
function
_getCache
(
$names
,
$store_locally
=
true
)
{
static
$request_number
=
1
;
$res
=
Array
();
$names
=
(
array
)
$names
;
$store_locally
=
(
array
)
$store_locally
;
$to_get
=
$prepared_names
=
array_map
(
Array
(&
$this
,
'prepareKeyName'
),
$names
);
foreach
(
$prepared_names
as
$index
=>
$prepared_name
)
{
$name
=
$names
[
$index
];
if
(
$store_locally
[
$index
]
&&
array_key_exists
(
$prepared_name
,
$this
->
_localStorage
)
)
{
$res
[
$name
]
=
$this
->
_localStorage
[
$prepared_name
];
unset
(
$to_get
[
$index
]);
}
}
if
(
$to_get
)
{
$multi_res
=
$this
->
_handler
->
get
(
$to_get
);
foreach
(
$to_get
as
$index
=>
$prepared_name
)
{
$name
=
$names
[
$index
];
if
(
array_key_exists
(
$prepared_name
,
$multi_res
)
)
{
$res
[
$name
]
=&
$multi_res
[
$prepared_name
];
}
else
{
$res
[
$name
]
=
false
;
}
$this
->
_postProcessGetCache
(
$prepared_name
,
$res
[
$name
],
$store_locally
[
$index
],
$request_number
);
}
$request_number
++;
}
return
count
(
$res
)
==
1
?
array_pop
(
$res
)
:
$res
;
}
/**
* Stores variable in local cache & collects debug info about cache
*
* @param string $name
* @param mixed $res
* @param bool $store_locally
* @param int $request_number
* @return void
* @access protected
*/
protected
function
_postProcessGetCache
(
$name
,
&
$res
,
$store_locally
=
true
,
$request_number
)
{
if
(
$this
->
debugCache
)
{
// don't display subsequent serial cache retrievals (ones, that are part of keys)
if
(
is_array
(
$res
)
)
{
$this
->
Application
->
Debugger
->
appendHTML
(
'r'
.
$request_number
.
': Restoring key "'
.
$name
.
'". Type: '
.
gettype
(
$res
)
.
'.'
);
}
else
{
$res_display
=
strip_tags
(
$res
);
if
(
strlen
(
$res_display
)
>
200
)
{
$res_display
=
substr
(
$res_display
,
0
,
50
)
.
' ...'
;
}
$this
->
Application
->
Debugger
->
appendHTML
(
'r'
.
$request_number
.
': Restoring key "'
.
$name
.
'" resulted ['
.
$res_display
.
']'
);
}
}
if
(
$store_locally
/*&& ($res !== false)*/
)
{
$this
->
_localStorage
[
$name
]
=
$res
;
}
}
/**
* Deletes value from cache
*
* @param string $name
* @return mixed
*/
function
delete
(
$name
)
{
$name
=
$this
->
prepareKeyName
(
$name
);
unset
(
$this
->
_localStorage
[
$name
]);
return
$this
->
_handler
->
delete
(
$name
);
}
/**
* Reset's all memory cache at once
*/
function
reset
()
{
// don't check for enabled, because we maybe need to reset cache anyway
if
(
$this
->
cachingType
==
CACHING_TYPE_TEMPORARY
)
{
return
;
}
$site_key
=
$this
->
_cachePrefix
(
true
);
$this
->
_handler
->
set
(
$site_key
,
$this
->
_handler
->
get
(
$site_key
)
+
1
,
0
);
}
/**
* Replaces serials and adds unique site prefix to cache variable name
*
* @param string $name
* @return string
*/
protected
function
prepareKeyName
(
$name
)
{
if
(
$this
->
cachingType
==
CACHING_TYPE_TEMPORARY
)
{
return
$name
;
}
// add site-wide prefix to key
return
$this
->
cachePrefix
.
$name
;
}
/**
* Replaces serials within given string
*
* @param string $value
* @return string
* @access protected
*/
protected
function
replaceSerials
(
$value
)
{
if
(
preg_match_all
(
'/
\[
%(.*?)%
\]
/'
,
$value
,
$regs
)
)
{
// [%LangSerial%] - prefix-wide serial in case of any change in "lang" prefix
// [%LangIDSerial:5%] - one id-wide serial in case of data, associated with given id was changed
// [%CiIDSerial:ItemResourceId:5%] - foreign key-based serial in case of data, associated with given foreign key was changed
$serial_names
=
$regs
[
1
];
$serial_count
=
count
(
$serial_names
);
$store_locally
=
Array
();
for
(
$i
=
0
;
$i
<
$serial_count
;
$i
++)
{
$store_locally
[]
=
true
;
}
$serial_values
=
$this
->
_getCache
(
$serial_names
,
$store_locally
);
if
(
!
is_array
(
$serial_values
)
)
{
$serial_values
=
Array
(
current
(
$serial_names
)
=>
$serial_values
);
}
foreach
(
$serial_names
as
$serial_name
)
{
$value
=
str_replace
(
'[%'
.
$serial_name
.
'%]'
,
'['
.
$serial_name
.
'='
.
$serial_values
[
$serial_name
]
.
']'
,
$value
);
}
}
return
$value
;
}
/**
* Returns site-wide caching prefix
*
* @param bool $only_site_key_name
* @return string
*/
function
_cachePrefix
(
$only_site_key_name
=
false
)
{
if
(
$only_site_key_name
)
{
return
$this
->
siteKeyName
;
}
if
(
!
isset
(
$this
->
siteKeyValue
)
)
{
$this
->
siteKeyValue
=
$this
->
_handler
->
get
(
$this
->
siteKeyName
);
if
(!
$this
->
siteKeyValue
)
{
$this
->
siteKeyValue
=
1
;
$this
->
_handler
->
set
(
$this
->
siteKeyName
,
$this
->
siteKeyValue
);
}
}
return
"{$this->siteKeyName}:{$this->siteKeyValue}:"
;
}
/**
* Stores statistics about cache usage in a file (one file per cache)
*
* @param string $name
* @param string $action_type {M - miss, L - lock, W - write, U - unlock, H - actual hit, h - outdated hit}
* @return void
* @access public
*/
public
function
storeStatistics
(
$name
,
$action_type
)
{
if
(
!
$this
->
_storeStatistics
)
{
return
;
}
$name
=
str_replace
(
Array
(
'/'
,
'
\\
'
,
':'
),
'_'
,
$name
);
$fp
=
fopen
(
RESTRICTED
.
DIRECTORY_SEPARATOR
.
'cache_usage'
.
DIRECTORY_SEPARATOR
.
$name
,
'a'
);
fwrite
(
$fp
,
$action_type
);
fclose
(
$fp
);
}
}
abstract
class
kCacheHandler
{
/**
* Remembers status of cache handler (working or not)
*
* @var bool
* @access protected
*/
protected
$_enabled
=
false
;
/**
* Caching type that caching handler implements
*
* @var int
* @access protected
*/
protected
$cachingType
;
/**
*
* @var kCache
* @access protected
*/
protected
$parent
;
public
function
__construct
(
kCache
$parent
)
{
$this
->
parent
=
$parent
;
}
/**
* Retrieves value from cache
*
* @param string $names
* @return mixed
* @access public
*/
abstract
public
function
get
(
$names
);
/**
* Stores value in cache
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
abstract
public
function
set
(
$name
,
$value
,
$expiration
=
null
);
/**
* Stores value in cache (only if it's not there already)
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
abstract
public
function
add
(
$name
,
$value
,
$expiration
=
null
);
/**
* Deletes key from cach
*
* @param string $name
* @return bool
* @access public
*/
abstract
public
function
delete
(
$name
);
/**
* Determines, that cache storage is working fine
*
* @return bool
* @access public
*/
public
function
isWorking
()
{
return
$this
->
_enabled
;
}
/**
* Returns caching type of current storage engine
*
* @return int
* @access public
*/
public
function
getCachingType
()
{
return
$this
->
cachingType
;
}
}
class
FakeCacheHandler
extends
kCacheHandler
{
public
function
__construct
(
kCache
$parent
)
{
parent
::
__construct
(
$parent
);
$this
->
_enabled
=
true
;
$this
->
cachingType
=
CACHING_TYPE_TEMPORARY
;
}
/**
* Retrieves value from cache
*
* @param string|Array $names
* @return mixed
* @access public
*/
public
function
get
(
$names
)
{
if
(
is_array
(
$names
)
)
{
$res
=
Array
();
foreach
(
$names
as
$name
)
{
$res
[
$name
]
=
$this
->
parent
->
getFromLocalStorage
(
$name
);
}
return
$res
;
}
return
$this
->
parent
->
getFromLocalStorage
(
$names
);
}
/**
* Stores value in cache
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
public
function
set
(
$name
,
$value
,
$expiration
=
null
)
{
return
true
;
}
/**
* Stores value in cache (only if it's not there already)
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
public
function
add
(
$name
,
$value
,
$expiration
=
null
)
{
return
true
;
}
/**
* Deletes key from cach
*
* @param string $name
* @return bool
* @access public
*/
public
function
delete
(
$name
)
{
return
true
;
}
}
class
MemcacheCacheHandler
extends
kCacheHandler
{
/**
* Memcache connection
*
* @var Memcache
* @access protected
*/
protected
$_handler
=
null
;
public
function
__construct
(
kCache
$parent
,
$default_servers
=
''
)
{
parent
::
__construct
(
$parent
);
$this
->
cachingType
=
CACHING_TYPE_MEMORY
;
$memcached_servers
=
kUtil
::
getSystemConfig
()->
get
(
'MemcacheServers'
,
$default_servers
);
if
(
$memcached_servers
&&
class_exists
(
'Memcache'
)
)
{
$this
->
_enabled
=
true
;
$this
->
_handler
=
new
Memcache
();
$servers
=
explode
(
';'
,
$memcached_servers
);
foreach
(
$servers
as
$server
)
{
if
(
preg_match
(
'/(.*):([
\d
]+)$/'
,
$server
,
$regs
)
)
{
// "hostname:port" OR "unix:///path/to/socket:0"
$server
=
$regs
[
1
];
$port
=
$regs
[
2
];
}
else
{
$port
=
11211
;
}
$this
->
_handler
->
addServer
(
$server
,
$port
);
}
// Verify, that memcache server is working.
if
(
!
$this
->
set
(
'test'
,
1
)
)
{
$this
->
_enabled
=
false
;
}
}
}
/**
* Retrieves value from cache
*
* @param string $name
* @return mixed
* @access public
*/
public
function
get
(
$name
)
{
return
$this
->
_handler
->
get
(
$name
);
}
/**
* Stores value in cache
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
public
function
set
(
$name
,
$value
,
$expiration
=
null
)
{
// 0 - don't use compression
return
$this
->
_handler
->
set
(
$name
,
$value
,
0
,
$expiration
);
}
/**
* Stores value in cache (only if it's not there already)
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
public
function
add
(
$name
,
$value
,
$expiration
=
null
)
{
// 0 - don't use compression
return
$this
->
_handler
->
add
(
$name
,
$value
,
0
,
$expiration
);
}
/**
* Deletes key from cache
*
* @param string $name
* @return bool
* @access public
*/
public
function
delete
(
$name
)
{
return
$this
->
_handler
->
delete
(
$name
,
0
);
}
}
class
MemcachedCacheHandler
extends
kCacheHandler
{
/**
* Memcache connection
*
* @var Memcached
* @access protected
*/
protected
$_handler
=
null
;
/**
* MemcachedCacheHandler constructor.
*
* @param kCache $parent Parent.
* @param string $default_servers Default servers.
*/
public
function
__construct
(
kCache
$parent
,
$default_servers
=
''
)
{
parent
::
__construct
(
$parent
);
$this
->
cachingType
=
CACHING_TYPE_MEMORY
;
$memcached_servers
=
kUtil
::
getSystemConfig
()->
get
(
'MemcacheServers'
,
$default_servers
);
if
(
$memcached_servers
&&
class_exists
(
'Memcached'
)
)
{
$this
->
_enabled
=
true
;
$this
->
_handler
=
new
Memcached
();
$servers
=
explode
(
';'
,
$memcached_servers
);
foreach
(
$servers
as
$server
)
{
if
(
preg_match
(
'/(.*):([
\d
]+)$/'
,
$server
,
$regs
)
)
{
// Possible format: "hostname:port" OR "unix:///path/to/socket:0".
$server
=
$regs
[
1
];
$port
=
$regs
[
2
];
}
else
{
$port
=
11211
;
}
$this
->
_handler
->
addServer
(
$server
,
$port
);
}
// Verify, that memcache server is working.
if
(
!
$this
->
set
(
'test'
,
1
)
)
{
$this
->
_enabled
=
false
;
}
}
}
/**
* Retrieves value from cache
*
* @param string|array $name Name.
*
* @return mixed
* @access public
*/
public
function
get
(
$name
)
{
if
(
is_array
(
$name
)
)
{
return
$this
->
_handler
->
getMulti
(
$name
);
}
return
$this
->
_handler
->
get
(
$name
);
}
/**
* Stores value in cache
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
public
function
set
(
$name
,
$value
,
$expiration
=
null
)
{
return
$this
->
_handler
->
set
(
$name
,
$value
,
$expiration
);
}
/**
* Stores value in cache (only if it's not there already)
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
public
function
add
(
$name
,
$value
,
$expiration
=
null
)
{
return
$this
->
_handler
->
add
(
$name
,
$value
,
$expiration
);
}
/**
* Deletes key from cache
*
* @param string $name Name.
*
* @return boolean
* @access public
*/
public
function
delete
(
$name
)
{
return
$this
->
_handler
->
delete
(
$name
);
}
}
class
ApcCacheHandler
extends
kCacheHandler
{
public
function
__construct
(
kCache
$parent
)
{
parent
::
__construct
(
$parent
);
$this
->
cachingType
=
CACHING_TYPE_MEMORY
;
$this
->
_enabled
=
function_exists
(
'apc_fetch'
);
// verify, that apc is working
if
(
$this
->
_enabled
&&
!
$this
->
set
(
'test'
,
1
)
)
{
$this
->
_enabled
=
false
;
}
}
/**
* Retrieves value from cache
*
* @param string $name
* @return mixed
* @access public
*/
public
function
get
(
$name
)
{
return
apc_fetch
(
$name
);
}
/**
* Stores value in cache
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
public
function
set
(
$name
,
$value
,
$expiration
=
null
)
{
return
apc_store
(
$name
,
$value
,
$expiration
);
}
/**
* Stores value in cache (only if it's not there already)
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
public
function
add
(
$name
,
$value
,
$expiration
=
null
)
{
return
apc_add
(
$name
,
$value
,
$expiration
);
}
/**
* Deletes key from cache
*
* @param string $name
* @return bool
* @access public
*/
public
function
delete
(
$name
)
{
return
apc_delete
(
$name
);
}
}
class
XCacheCacheHandler
extends
kCacheHandler
{
public
function
__construct
(
kCache
$parent
)
{
parent
::
__construct
(
$parent
);
$this
->
cachingType
=
CACHING_TYPE_MEMORY
;
$this
->
_enabled
=
function_exists
(
'xcache_get'
);
// verify, that xcache is working
if
(
$this
->
_enabled
&&
!
$this
->
set
(
'test'
,
1
)
)
{
$this
->
_enabled
=
false
;
}
}
/**
* Retrieves value from cache
*
* @param string|Array $names
* @return mixed
* @access public
*/
public
function
get
(
$names
)
{
if
(
is_array
(
$names
)
)
{
$res
=
Array
();
foreach
(
$names
as
$name
)
{
$res
[
$name
]
=
$this
->
get
(
$name
);
}
return
$res
;
}
return
xcache_isset
(
$names
)
?
xcache_get
(
$names
)
:
false
;
}
/**
* Stores value in cache
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
public
function
set
(
$name
,
$value
,
$expiration
=
null
)
{
return
xcache_set
(
$name
,
$value
,
$expiration
);
}
/**
* Stores value in cache (only if it's not there already)
*
* @param string $name Name.
* @param mixed $value Value.
* @param integer|null $expiration Expiration.
*
* @return boolean
*/
public
function
add
(
$name
,
$value
,
$expiration
=
null
)
{
// not atomic operation, like in Memcached and may fail
if
(
xcache_isset
(
$name
)
)
{
return
false
;
}
return
$this
->
set
(
$name
,
$value
,
$expiration
);
}
/**
* Deletes key from cache
*
* @param string $name
* @return bool
* @access public
*/
public
function
delete
(
$name
)
{
return
xcache_unset
(
$name
);
}
}
Event Timeline
Log In to Comment