Initial commit
This commit is contained in:
248
www/classes/CacheBase.class.php
Normal file
248
www/classes/CacheBase.class.php
Normal file
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) 2005-2013 OpenStudio */
|
||||
/* email : info@thelia.fr */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
require_once __DIR__ . "/../fonctions/autoload.php";
|
||||
/*
|
||||
* Outil de cache à deux niveaux :
|
||||
* - utilisant les éléments static de PHP, permettant de s'assurer qu'une requete n'est pas exécutée 2 fois sur une meme page
|
||||
* - utilisant MEMCACHE
|
||||
*
|
||||
* Configuration du niveau : attribut LEVEL
|
||||
* - LEVEL=self::AUCUN_CACHE : pas de cache
|
||||
* - LEVEL=self::STATIC_CACHE : cache uniquement en memoire
|
||||
* - LEVEL=selff::MEMCACHE_CACHE : cache en memoire et via memcached
|
||||
*
|
||||
* fonctionne comme un Singleton :
|
||||
* $cache=CacheBase::getCache();
|
||||
*
|
||||
* puis :
|
||||
* $cache->set("cle","valeur");
|
||||
* $valeur=$cache->get("cle");
|
||||
*
|
||||
* Pour mettre en cache le résultat d'un SELECT :
|
||||
* $cache->query("requete")
|
||||
*
|
||||
* Pour mettre en cache le résultat d'un COUNT SQL :
|
||||
* $cache->query_count("requete")
|
||||
*
|
||||
* Pour changer temporairement le LEVEL
|
||||
* $cache->switchLevel(x) -> la prochaine opération (query...) se fera avec ce level temporaire
|
||||
*
|
||||
*/
|
||||
class CacheBase {
|
||||
|
||||
// Durée de vie d'un item dans le cache memcache (en secondes)
|
||||
const AGE = 600;
|
||||
|
||||
const AUCUN_CACHE = 0;
|
||||
const STATIC_CACHE = 1;
|
||||
const MEMCACHE_CACHE = 2;
|
||||
|
||||
public static $LEVEL = 2;
|
||||
|
||||
private $levelhistory;
|
||||
private $result_cache = array();
|
||||
private $memcache = false;
|
||||
|
||||
// singleton
|
||||
private static $cache = null;
|
||||
|
||||
private $cnx;
|
||||
|
||||
private function __construct() {
|
||||
$this->cnx = new Cnx();
|
||||
|
||||
// Déterminer le niveau courant en fonction
|
||||
// de la valeur de la variable mecached
|
||||
// 0 => cache local, <> 0 => utiliser memcache
|
||||
self::$LEVEL = $this->is_memcache_active() ? self::MEMCACHE_CACHE : self::STATIC_CACHE;
|
||||
|
||||
$this->levelhistory = self::$LEVEL;
|
||||
}
|
||||
|
||||
public static function getCache() {
|
||||
if (!self::$cache)
|
||||
self::$cache = new CacheBase();
|
||||
return self::$cache;
|
||||
}
|
||||
|
||||
public function switchLevel($level) {
|
||||
$this->levelhistory = self::$LEVEL;
|
||||
self::$LEVEL = $level;
|
||||
}
|
||||
|
||||
private function is_memcache_active() {
|
||||
// On ne peut pas utiliser Variable::lire() ici, qui fait appel à
|
||||
// cete classe.
|
||||
|
||||
//si on est dans le processus de maj on empêche l'activation de memcache
|
||||
if (defined('IN_UPDATE_THELIA')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$val = 1;
|
||||
|
||||
$hdl = $this->cnx->query("select valeur from ".Variable::TABLE." where nom = 'memcache'");
|
||||
|
||||
if ($hdl) {
|
||||
$val = $this->cnx->get_result($hdl);
|
||||
}
|
||||
|
||||
return intval($val) > 0;
|
||||
}
|
||||
|
||||
|
||||
private function switchBackLevel() {
|
||||
self::$LEVEL = $this->levelhistory;
|
||||
}
|
||||
|
||||
private function getMemcache() {
|
||||
if (self::$LEVEL != self::MEMCACHE_CACHE)
|
||||
return null;
|
||||
|
||||
if ($this->memcache === false) {
|
||||
|
||||
$this->memcache = new Memcache();
|
||||
|
||||
if (! $this->memcache->connect('localhost')) {
|
||||
|
||||
Tlog::fatal("Echec de connexion au serveur memcache. Arrêt.");
|
||||
|
||||
die("Echec de connexion au serveur memcache. Arrêt.");
|
||||
}
|
||||
}
|
||||
|
||||
return $this->memcache;
|
||||
}
|
||||
|
||||
private function setCache2($key, $value) {
|
||||
if (self::$LEVEL != self::MEMCACHE_CACHE)
|
||||
return false;
|
||||
|
||||
$this->getMemcache()->set($key, $value, false, self::AGE);
|
||||
}
|
||||
|
||||
private function getCache2($key) {
|
||||
if (self::$LEVEL != self::MEMCACHE_CACHE)
|
||||
return false;
|
||||
|
||||
return $this->getMemcache()->get($key);
|
||||
}
|
||||
|
||||
private function flushCache2() {
|
||||
if (self::$LEVEL != self::MEMCACHE_CACHE)
|
||||
return false;
|
||||
|
||||
return $this->getMemcache()->flush();
|
||||
}
|
||||
|
||||
public function get($key) {
|
||||
if (self::$LEVEL == 0)
|
||||
return false;
|
||||
|
||||
$hash = hash('md5', $key);
|
||||
|
||||
$retour = !isset($this->result_cache[$hash]) ? false : $this->result_cache[$hash];
|
||||
|
||||
if (!$retour) { // ce n'est pas dans le niveau 1
|
||||
|
||||
$retour = $this->getCache2($hash);
|
||||
|
||||
if ($retour == false) // ce n'est pas dans le niveau 2
|
||||
return false;
|
||||
else
|
||||
$this->result_cache[$hash] = $retour; // On le met en niveau 1 pour accélérer le prochain get
|
||||
}
|
||||
return $retour;
|
||||
}
|
||||
|
||||
public function set($key, $value) {
|
||||
if (self::$LEVEL == 0)
|
||||
return;
|
||||
|
||||
$hash = hash('md5', $key);
|
||||
$this->result_cache[$hash] = $value;
|
||||
$this->setCache2($hash, $value);
|
||||
}
|
||||
|
||||
public function query($query, $clazz = false) {
|
||||
$data = $this->get($query);
|
||||
|
||||
if (!$data) {
|
||||
$data = array();
|
||||
|
||||
$resul = $this->cnx->query($query);
|
||||
|
||||
while ($resul && $row = $this->fetch_object($resul, $clazz)) {
|
||||
$data[] = $row;
|
||||
}
|
||||
$this->set($query, $data);
|
||||
}
|
||||
|
||||
$this->switchBackLevel();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function fetch_object($resul, $clazz = false) {
|
||||
return $this->cnx->fetch_object($resul, $clazz);
|
||||
}
|
||||
|
||||
public function query_count($query) {
|
||||
$num = $this->get($query);
|
||||
|
||||
if ($num < 0 || $num == "") {
|
||||
$resul = $this->cnx->query($query);
|
||||
|
||||
if ($resul)
|
||||
$num = $this->cnx->num_rows($resul);
|
||||
else
|
||||
$num = 0;
|
||||
|
||||
$this->set($query, $num);
|
||||
}
|
||||
$this->switchBackLevel();
|
||||
return $num;
|
||||
}
|
||||
|
||||
public function reset_cache() {
|
||||
$this->result_cache = array();
|
||||
$this->flushCache2();
|
||||
}
|
||||
|
||||
/* Compatibilité pré-1.5.2 */
|
||||
|
||||
public function mysql_query($query, $link = null, $clazz = false) {
|
||||
return $this->query($query, $clazz);
|
||||
}
|
||||
|
||||
public function mysql_fetch_object($resul, $clazz = false) {
|
||||
return $this->fetch_object($resul, $clazz);
|
||||
}
|
||||
|
||||
public function mysql_query_count($query, $link = false) {
|
||||
return $this->query_count($query);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user