Source of file api.ubcache.php
Size: 12,911 Bytes - Last Modified: 2024-04-27T15:26:05+03:00
/tmp/current_snapshot/api/libs/api.ubcache.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 | <?php /** * System-wide caching abstraction engine */ class UbillingCache { /** * System alter.ini config content * * @var array */ protected $altCfg = array(); /** * Cache storage type: files, memcached, fake * via UBCACHE_STORAGE option * * @var string */ protected $storage = ''; /** * Memcached server IP/Hostname * via MEMCACHED_SERVER option * * @var string */ protected $memcachedServer = ''; /** * Memcached server port * via MEMCACHED_PORT option * * @var int */ protected $memcachedPort = ''; /** * Redis server IP/Hostname * via REDIS_SERVER option * * @var string */ protected $redisServer = ''; /** * Redis server port * via REDIS_PORT option * * @var int */ protected $redisPort = ''; /** * File storage path: "exports/" by default * * @var string */ protected $storagePath = ''; /** * Just debugging flag * * @var bool */ protected $debug = false; /** * Single instance of memcached object * * @var object */ protected $memcached = ''; // single memcached object /** * Cache keys prefix */ const CACHE_PREFIX = 'UBCACHE_'; /** * Default cache log path for debug mode */ const LOG_PATH = 'exports/cache.log'; /** * Creates new UbillingCache instance * * @param string $storageType overrides cache storage set in config files. * * @return void */ public function __construct($storageType = '') { $this->loadAlter(); $this->setOptions($storageType); $this->initStorageServerCache(); } /** * Loads global alter config into protected property * * @global object $ubillingConfig * * @return void */ protected function loadAlter() { global $ubillingConfig; $this->altCfg = $ubillingConfig->getAlter(); } /** * Sets object storage mode * * @param string $storageType overrides cache storage set in config files. * * @return void */ protected function setOptions($storageType = '') { if (isset($this->altCfg['UBCACHE_STORAGE'])) { $this->storage = $this->altCfg['UBCACHE_STORAGE']; } else { $this->storage = 'fake'; } //override storage type from constructor if (!empty($storageType)) { $this->storage = $storageType; } if (@$this->altCfg['UBCACHE_DEBUG']) { $this->debug = true; } if ($this->storage == 'memcached') { if (isset($this->altCfg['MEMCACHED_SERVER'])) { $this->memcachedServer = $this->altCfg['MEMCACHED_SERVER']; } else { $this->memcachedServer = 'localhost'; } if (isset($this->altCfg['MEMCACHED_PORT'])) { $this->memcachedPort = $this->altCfg['MEMCACHED_PORT']; } else { $this->memcachedPort = 11211; } } if ($this->storage == 'redis') { if (isset($this->altCfg['REDIS_SERVER'])) { $this->redisServer = $this->altCfg['REDIS_SERVER']; } else { $this->redisServer = 'localhost'; } if (isset($this->altCfg['REDIS_PORT'])) { $this->redisPort = $this->altCfg['REDIS_PORT']; } else { $this->redisPort = 6379; } } if ($this->storage == 'files') { $this->storagePath = 'exports/'; } } /** * Inits storage server cache if it needed * * @return void */ protected function initStorageServerCache() { // Init Memcached if ($this->storage == 'memcached') { $this->memcached = new Memcached(); $this->memcached->addServer($this->memcachedServer, $this->memcachedPort); } // Init Redis if ($this->storage == 'redis') { $this->redis = new Redis(); $this->redis->connect($this->redisServer, $this->redisPort); $this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); } } /** * Generates key storable internal name * * @param string $key * * @return string */ protected function genKey($key) { $result = self::CACHE_PREFIX . vf($key); return ($result); } /** * Logs data if logging is enabled * * @param string $event * @param string $dataSample * * @return void */ protected function logEvent($event, $dataSample = '') { if ($this->debug) { $curDate = curdatetime(); $dataSize = ''; if (!empty($dataSample)) { $dataSize = strlen(serialize($dataSample)) . ' bytes'; if (ispos($event, 'GET KEY')) { $dataSize .= ' HIT'; } } else { $dataSize = 'EMPTY_DATA'; if (ispos($event, 'GET KEY')) { $dataSize .= ' MISS YA'; } } $logData = $curDate . ' ' . $this->storage . ' ' . $event . ' ' . $dataSize . "\n"; file_put_contents(self::LOG_PATH, $logData, FILE_APPEND); } } /** * Puts data into cache storage * * @param string $key * @param string $data * @param int $expiration * * @return void */ public function set($key, $data, $expiration = 2592000) { $key = $this->genKey($key); // Set expiration time not more 1 month $expiration = ($expiration > 2592000) ? '2592000' : $expiration; //files storage if ($this->storage == 'files') { file_put_contents($this->storagePath . $key, serialize($data)); } //memcached storage if ($this->storage == 'memcached') { $this->memcached->set($key, $data, $expiration); } //redis storage if ($this->storage == 'redis') { $this->redis->set($key, $data); $this->redis->setTimeout($key, $expiration); } $this->logEvent('SET KEY: ' . $key, $data); } /** * Returns data by key name. Empty if no data exists or cache expired. * * @param string $key Storage key name * @param int $expiration Expiration time in seconds * * @return mixed */ public function get($key, $expiration = 2592000) { $result = ''; $keyRaw = $key; $key = $this->genKey($key); //files storage if ($this->storage == 'files') { $cacheName = $this->storagePath . $key; $cacheTime = time() - $expiration; $updateCache = false; if (file_exists($cacheName)) { $updateCache = false; if ((filemtime($cacheName) > $cacheTime)) { $updateCache = false; } else { $updateCache = true; } } else { $updateCache = true; } if (!$updateCache) { //read data directly from cache $data = file_get_contents($cacheName); $result = unserialize($data); } else { //cache expired, return empty result $result = ''; $this->delete($keyRaw); } $this->logEvent('GET KEY: ' . $key, $result); return ($result); } //memcached storage if ($this->storage == 'memcached') { $result = $this->memcached->get($key); if (!$result) { $result = ''; } $this->logEvent('GET KEY: ' . $key, $result); return ($result); } //redis storage if ($this->storage == 'redis') { $result = $this->redis->get($key); if (!$result) { $result = ''; } $this->logEvent('GET KEY: ' . $key, $result); return ($result); } //fake storage if ($this->storage == 'fake') { $result = ''; $this->logEvent('GET KEY: ' . $key, $result); return ($result); } return ($result); } /** * Returns data from cache by key or runs callback and fills new cache data * * @param string $key Storage key * @param Closure $callback Callback function * @param int $expiration Expiration time in seconds * * @return string */ public function getCallback($key, Closure $callback, $expiration = 2592000) { // Use this class get function $result = $this->get($key, $expiration); if (!$result) { // If not have result from class get function // return $callback data function and set new cache $result = $callback(); /** * Intensity - I feel the lava rushing through my veins * Stars are reforming - to enter the fourth dimension */ $this->set($key, $result, $expiration); } return ($result); } /** * Deletes data from cache by key name * * @param string $key * * @return void */ public function delete($key) { $key = $this->genKey($key); //files storage if ($this->storage == 'files') { if (file_exists($this->storagePath . $key)) { @unlink($this->storagePath . $key); } } //memcached storage if ($this->storage == 'memcached') { $this->memcached->delete($key); } //redis storage if ($this->storage == 'redis') { $this->redis->delete($key); } $this->logEvent('DELETE KEY: ' . $key); } /** * Show all data from cache * * @param bool $show_data * * @return array */ public function getAllcache($show_data = false) { $result = array(); //files storage if ($this->storage == 'files') { $cache = scandir($this->storagePath); $keys = array_diff($cache, array('..', '.', '.gitignore', '.htaccess')); $keys = preg_grep("/^" . self::CACHE_PREFIX . "/", $keys); if ($show_data) { $result = array(); foreach ($keys as $key => $file) { $result[$key]['key'] = $file; $result[$key]['value'] = unserialize(file_get_contents($this->storagePath . $file)); } } else { $result = $keys; } return($result); } //memcached storage if ($this->storage == 'memcached') { $keys = $this->memcached->getAllKeys(); if ($keys == false) { $keys = array(); //preventing issues on PHP 8.2 } $keys = preg_grep("/^" . self::CACHE_PREFIX . "/", $keys); if ($show_data) { $this->memcached->getDelayed($keys); $result = $this->memcached->fetchAll(); } else { $result = $keys; } return($result); } //redis storage if ($this->storage == 'redis') { $keys = $this->redis->keys(self::CACHE_PREFIX . '*'); if ($show_data) { $value = $this->redis->mGet($keys); foreach ($keys as $id => $key) { $result[$id]['key'] = $key; $result[$id]['value'] = $value[$id]; } } else { $result = $keys; } return($result); } } /** * Delete all data from cache * * @return void */ public function deleteAllcache() { $cache_data = $this->getAllcache(); $this->logEvent('TOTAL CLEANUP'); //files storage if ($this->storage == 'files' and !empty($cache_data)) { foreach ($cache_data as $cache) { unlink($this->storagePath . $cache); } } //memcached storage if ($this->storage == 'memcached' and !empty($cache_data)) { $result = $this->memcached->deleteMulti($cache_data); return($result); } //redis storage if ($this->storage == 'redis' and !empty($cache_data)) { $result = $this->redis->delete($cache_data); return($result); } } } ?> |