Source for file c_cache.inc
Documentation is available at c_cache.inc
* Classe di gestione cache di metadati, pagine, xsl e dati
* Classe di generazione istanza unica (factory pattern)
* @author Ubik <emiliano.leporati@gmail.com>
* Gestisce le cache di metadati, pagine, xsl e dati su sdb
* Conteggi per le statistiche di esecuzione
public static $time = array('CACHE' => 0);
* Imposta flag e directory
$this->db_dir = path(PHDIR, 'system/cache/query');
$this->lang_src_dir = path(PHDIR, 'system/lang');
$this->lang_dir = path(PHDIR, 'system/cache/lang');
* Cache in memoria delle stringhe di localizzazione
if (!isset ($_SESSION['lang']))
throw new CodeException("Richiesta localizzazione ma lingua non impostata.");
$source = path($this->lang_src_dir, $_SESSION['lang']. '.xml');
$cache = path($this->lang_dir, $_SESSION['lang']. '.xml.obj');
if (!$d -> load($source))
throw new CodeException("File di localizzazione $source non valido (XML).");
$xpath = new DOMXPath($d);
$root = $d->documentElement;
$this->lang_data['LC_TIME'] = $root->getAttribute('lc-time');
$this->lang_data['DATE_TYPE'] = $root->getAttribute('date-type');
$nodes = $xpath->query("//application/string[@id='$id']");
$string = $nodes->item(0)->textContent;
* Carica la cache delle stringhe
if (!isset ($_SESSION['lang']))
throw new CodeException("Richiesta localizzazione ma lingua non impostata.");
// se voglio un refresh o non ho caricato ancora nulla
if ($force || !isset ($_SESSION['lang_data'])) {
$source = path($this->lang_src_dir, $_SESSION['lang']. '.xml');
$cache = path($this->lang_dir, $_SESSION['lang']. '.xml.obj');
throw new CodeException("File di localizzazione $source non trovato.");
// se non esiste il file di cache oppure il file source รจ + recente, carico il source
if (!$d -> load($source))
throw new CodeException("File di localizzazione $source non valido (XML).");
$xpath = new DOMXPath($d);
$root = $d->documentElement;
$this->lang_data['LC_TIME'] = $root->getAttribute('lc-time');
$this->lang_data['DATE_TYPE'] = $root->getAttribute('date-type');
$nodes = $xpath->query('//application/string|//system/string'); //$root->getElementsByTagName('string');
for($i = 0; $i < $nodes->length; $i ++ ) {
$key = $nodes->item($i)->getAttribute('id');
$val = $nodes->item($i)->textContent;
$dbmss = array('FBIRD' => 'firebird', 'MYSQL' => 'mysql', 'MSSQL' => 'mssql', 'ODBC' => 'odbc');
foreach($dbmss as $ubk => $dbms) {
$nodes = $xpath->query("//{$dbms}/string");
for($i = 0; $i < $nodes->length; $i ++ ) {
$key = $nodes->item($i)->getAttribute('id');
$val = $nodes->item($i)->textContent;
// altrimenti carico la cache
* Ritorna la stringa indicata
* @param mixed ... Parametri per stringhe parametriche (sprintf)
* Ritorna la stringa indicata
* @param string $db Database per cui si vuole ottenere la stringa (FBIRD, MYSQL, MSSQL, ODBC, ...)
* @param string $id Stringa voluta
* Array associativo con il codice trasformato di immagini con rollover (gfx:img)
* Ritorna il codice HTML rappresentante un'immagine con rollover dato il nome di base ($name => $name_dis.ext / $name.ext)
* Si basa sul template XSL gfx:img, che usa a sua volta il parametro ini DEF_IMG_EXT
* @param string $name nome dell'immagine
* Cache metadati attiva / disattiva
* Si basa sul parametro ini CACHE_METADATI
* Directory in cui vengono memorizzati i file di cache delle meta-informazioni
* Sotto PHDIR, system/cache/metadata
* Cache in memoria delle meta-informazioni
* Fornisce il nome file contenente le meta-informazioni
* @param string $signature Firma dell'oggetto di cui reperire le informazioni, fornita da {@link mtd_signature}
* Fornisce il nome file contenente le meta-informazioni
* @param array $db_connection Informazioni di connessione al db contenente l'oggetto
* @param string $sql Oggetto del db (tabella, vista, stored procedure)
if (($p = stripos($sql,' where ')) !== FALSE) {
return CRYPTER::hash($db_connection['DB_SERVER']. $db_connection['DB_NAME']. $sql);
* Registra le meta-informazioni su file
* @param array $db_connection Informazioni di connessione al db contenente l'oggetto
* @param string $sql Oggetto del db (tabella, vista, stored procedure)
* @param array $info Meta-informazioni
public function mtd_write($db_connection, $sql, $info)
* Ritorna le meta-informazioni associate all'oggetto, se esistono
* @param array $db_connection Informazioni di connessione al db contenente l'oggetto
* @param string $sql Oggetto del db (tabella, vista, stored procedure)
public function mtd_get($db_connection, $sql)
* Cache pagine attiva / disattiva
* Si basa sul parametro ini CACHE_XML
* Directory in cui vengono memorizzati i file di cache delle pagine
* Sotto PHDIR, system/cache/xml
* Fornisce il nome file contenente la pagina pre-trasformata
* @param string $filename Nome del file da reperire, completo di percorso (relativo alla PHDIR)
* Memorizza la pagina trasformata sul filesystem
* @param string $filename Nome del file trasformato
* @param TAG $DOM Trasformazione del file
* Fornisce la trasformazione del file XML indicato
* @param string $filename Nome del file da reperire, completo di percorso (relativo alla PHDIR)
* Attiva l'uso della cache se consentito dai parametri di configurazione
* Disattiva l'uso della cache
* Cache trasformazioni XSL attiva / disattiva
* Si basa sul parametro ini CACHE_XSL
* Restituisce il file XSL, tenuto in sessione
* Memorizza in sessione il file XSL
if ($this->xsl_cache && !isset ($_SESSION['CACHE_XSL']))
$_SESSION['CACHE_XSL'] = $xsl;
* Array associativo nome_tabella => true / false, indica se la cache e' da aggiornare
* Array associativo nome_tabella => ultimo aggiornamento cache
* File con le informazioni della cache
* sotto PHDIR, system/cache/registry.ser
* File di lock per accesso a {@link $reg_file}
* sotto PHDIR, system/cache/cache.lock
* Indica se registrare la funzione di shutdown per la scrittura del registry
* Cache query attiva / disattiva
* Si basa sul parametro ini CACHE_DB
* Directory salvataggio dati query
* sotto PHDIR, system/cache/query
* Numero record per ogni file di query
* Cache in memoria dei dati caricati via query
* Invalida la cache di una tabella, normalmente viene chiamato dalle funzioni
* di aggiornamento (update, add, delete).
* @param string $nome_tabella nome della tabella modificata
public function azzera($nome_tabella)
// aggiorna il registro a chiusura della pagina
* Carica i dati dalla cache di una tabella, se vecchia o non presente ricrea la cache.
* @param string $nome_tabella nome della tabella
* @param string $campo_id nome del campo su cui viene fatta la ricerca
* @param string $valore_id valore cercato
* @return array|NULLl'insieme dei record cercati
public function & carica_rs($nome_tabella, $campo_id, $valore_id)
$valore_id = substr($valore_id, 1, - 1);
$file_name = $this->nome_file($nome_tabella, $campo_id, $valore_id);
if (isset ($this->db_data[$file_name])){
$data = & $this->db_data[$file_name];
// carico il file da disco
if ($file_mtime && isset ($this->reg_cache[$nome_tabella]) && ($file_mtime >= $this->reg_cache[$nome_tabella])) {
log_value("CACHE: tabella $nome_tabella ok (mtime $file_mtime ) <= ");
if (!$file_mtime) log_value("CACHE: carico da db $file_name non esistente");
elseif (!isset ($this->reg_cache[$nome_tabella])) log_value("CACHE: carico da db $file_name non presente in cache");
elseif (!($file_mtime >= $this->reg_cache[$nome_tabella]))
log_value("CACHE: carico da db $file_name percha' piu' aggiornato $file_mtime > " . $this->reg_cache[$nome_tabella] .
' - ' . date("h:i:s d/m/Y",$file_mtime) . ' > ' . date("h:i:s d/m/Y",$this->reg_cache[$nome_tabella]));
// file non presente o scaduto, devo crearlo
$min = $valore_id - ($valore_id % $this->db_range);
$cond = "where ". c_and(gte($campo_id, $min), lt($campo_id, $max));
$sql = "select * from $nome_tabella $cond";
$data = $tmp_rs->getRS();
// aggiorno il file su disco
$this->db_data[$file_name] = &$data;
if (!isset ($this->reg_cache[$nome_tabella])) {
if (isset ($data[$valore_id])) {
log_value("CACHE: id richiesto $valore_id trovato");
$rs[] = $data[$valore_id];
self::$time['CACHE'] += ($_end - $_start);
* Carica il registro della cache se necessario (check sull'ora di modifica)
* @param bool $ignore_session ignora i dati di cache in sessione
* @return array il registro delle della cache ([nome_tabella] => time_stamp)
//echo "caricamento registry\n";
unset ($_SESSION['REGISTRY_TIME']);
//echo "Registry del ".date("h:i:s d/m/Y",$cache_reg_mtime)."\n";
if ($cache_reg_mtime && !empty($_SESSION['REGISTRY_TIME'])){
if ($cache_reg_mtime > $_SESSION['REGISTRY_TIME']){
// registro vecchio, ricaricare
log_value('CACHE: Registro session: '. date('d/m/Y h:i:s',$_SESSION['REGISTRY_TIME']).
' - ' . date('d/m/Y h:i:s',$cache_reg_mtime) . ' mtime file');
if ($cache_reg_mtime == null){
// errore nel caricamento del file
$_SESSION['REGISTRY_TIME'] = $cache_reg_mtime;
* Aggiorna il registro della cache su disco
if( !(flock($fp, LOCK_EX)) ) {
// da verificare l'aggiornamento della cache
$registry[$tabella] = time();
log_value('CACHE: Aggiornata tabella: ' . $tabella . ' ts: ($registry[$tabella]) ' . date("h:i:s d/m/Y",$registry[$tabella]));
if( !(flock($fp, LOCK_UN)) ){
throw new FatalException("Impossibile rilasciare il lock sulla cache");
* Restituisce il nome del file che deve contenere i dati.
* @param string $nome_tabella nome della tabella
* @param string $campo_id nome del campo su cui viene fatta la ricerca
* @param string $valore_id valore cercato
* @return string il nome del file
public function nome_file($nome_tabella, $campo_id, $valore_id)
return "{ $nome_tabella}_{ $campo_id}_ " . (floor($valore_id / $this->db_range) + 1) . '.db';
* Carica il recordset passato con i dati della cache locale
* @param mixed $sql Query da effettuare
* @param bool $carica_info Indica se impostare i meta-dati del recordset
* @param RECORDSET $db_object Il {@link RECORDSET} / {@link GESTORE} da caricare
* @return bool true se caricato, false se i dati non sono presenti
public function carica_sql($sql, $carica_info, &$db_object)
$sql = $sql['SQL'] . $sql['PAGE'] . $sql['PAGE-SIZE'];
if (!isset ($this->db_sql[$sql])){
$cache_rs = & $this->db_sql[$sql];
$db_object->setRS($cache_rs->getRS());
$db_object->campi = $cache_rs->campi;
$db_object->lunghezza = $cache_rs->lunghezza;
$db_object->tipo = $cache_rs->tipo;
* Dice se la cache e' valida
* @param string $campo_id
* @param string $condizione
public function validate($usa_cache, $table, $campo_id, $condizione)
if (!$this->db_cache) return array(FALSE, NULL);
if ($this->db_cache && $usa_cache && $table[0] == 't'){
if ($condizione && !(bool) preg_match('/^\s*'. $campo_id. '\s*=\s*(\d+)\s*$/', $condizione, $_info_condizione)) {
return array(FALSE, NULL);
return array($usa_cache, $_info_condizione[1]);
* Memorizza localmente la query effettuata
* @param RECORDSET $db_object
$sql = $sql['SQL'] . $sql['PAGE'] . $sql['PAGE-SIZE'];
$this->db_sql[$sql] = & $db_object;
* Ritorna il gestore della cache, assicurandosi che non vi siano istanze multiple
private static $instance = NULL;
final public static function & get()
self::$instance = new CACHE();
self::$instance->carica_registry();
* Shortcut globale per CACHE::lang
* Shortcut globale per CACHE::lang_database
* Shortcut globale per CACHE::lang_load
|