Subversion Repositories Sigmater

Rev

Blame | Last modification | View Log | Download | RSS feed

<?php
/* fastcache.inc -- gestione veloce di cache file con validità
 *                  temporale impostabile dall'utente.
 *                  L'accesso al file da parte di processi
 *                  concorrenti viene serializzato.
 *
 * Il file fastcache_test.php contiene un esempio di uso.
 *
 * Versione 1.1, ultima modifica 8 marzo 2004 [27781]
 */


/* La funzione fcache_read legge il contenuto di un cache file
 * e lo deserializza nella variabile PHP passata come argomento.
 *
 * Parametri di input:
 *
 * $fname = nome del file di cache da leggere. Si consiglia di
 *          fornire il path completo.
 * $data  = variabile passata per riferimento, che viene impostata
 *          con il risultato della deserializzazione dei dati letti
 *          nel file di cache.
 *
 * Codici di ritorno:
 *
 * 0 = Tutto OK.
 * 1 = File inesistente.
 * 2 = Impossibile creare lock file.
 * 3 = Impossibile acquisire READ lock.
 * 4 = Impossibile aprire il file in lettura.
 * 5 = Cache scaduta.
 * 6 = Impossibile deserializzare i dati.
 */

function fcache_read($fname, &$data)
  {
  clearstatcache();
  if(false == file_exists($fname))
    return(1); // File inesistente.
  $om = file_exists($fname.'.lock') ? 'rb' : 'ab';
  $fd = @fopen($fname.'.lock', $om);
  if(false == $fd)
    return(2); // Impossibile creare lock file.
  if(!(@flock($fd, LOCK_SH)))
    {
    @fclose($fd);
    return(3); // Impossibile acquisire READ lock.
    }
  $fh = @fopen($fname, 'rb');
  if(false == $fh)
    {
    @flock($fd, LOCK_UN);
    @fclose($fd);
    return(4); // Impossibile aprire il file in lettura.
    }
  $ts = hexdec(rtrim(@fgets($fh, 32)));
  if(time() > $ts)
    {
    @fclose($fh);
    @flock($fd, LOCK_UN);
    @fclose($fd);
    return(5); // Cache scaduta.
    }
  $s = '';
  while(!feof($fh))
    $s .= fread($fh, 8192);
  @fclose($fh);
  @flock($fd, LOCK_UN);
  @fclose($fd);
  $data = unserialize($s);
  if(false == $data)
    return(6); // Impossibile deserializzare i dati.
  return(0); // Tutto OK.
  }

/* La funzione fcache_write inizializza il contenuto di un cache file
 * con i dati passati ed imposta il periodo di validità di questi ultimi.
 *
 * Parametri di input:
 *
 * $fname =   nome del file di cache da scrivere. Si consiglia di
 *            fornire il path completo.
 * $data  =   variabile che contiene i dati da impostare. Ciascun cache file
 *            contiene solo una variabile PHP, ma questa può essere anche un
 *            array associativo multidimensionale grande a piacere. Su Linux
 *            si consiglia di scrivere i file nel filesystem /dev/shm che è
 *            contenuto in memoria e di dimensioni massime pari a metà della
 *            memoria fisica della macchina.
 *            Ovviamente questo significa che i file in /dev/shm devono essere
 *            di piccole dimensioni e sacrificabili in caso di shutdown o crash
 *            del server: qualora non fosse rispettato uno dei vincoli esposti
 *            il cache file va creato su disco, magari in una directory tmp dove
 *            i file non più usati vengono automaticamente cancellati.
 * $timeout = numero di secondi di validità del cache file. Il parametro può
 *            essere omesso nella chiamata, ed in tal caso viene impostato
 *            a 60 secondi.
 *
 * Codici di ritorno:
 *
 * 0 = Tutto OK.
 * 1 = Non ci sono dati da scrivere!
 * 2 = Impossibile creare lock file.
 * 3 = Impossibile acquisire WRITE lock.
 * 4 = Impossibile aprire il file in scrittura.
 * 5 = Fallita scrittura cache file.
 * 6 = Il timeout non è valido.
 */

function fcache_write($fname, $data, $timeout = 60)
  {
  if(empty($data))
    return(1); // Non devo scrivere niente!
  if(!is_numeric($timeout) || $timeout <= 0)
    return(6); // Il timeout non è valido.
  clearstatcache();
  $om = file_exists($fname.'.lock') ? 'rb' : 'ab';
  $fd = @fopen($fname.'.lock', $om);
  if(false == $fd)
    return(2); // Impossibile creare lock file.
  if(!(@flock($fd, LOCK_EX)))
    {
    @fclose($fd);
    return(3); // Impossibile acquisire WRITE lock.
    }
  $fh = @fopen($fname, 'wb');
  if(false == $fh)
    {
    @flock($fd, LOCK_UN);
    @fclose($fd);
    return(4); // Impossibile aprire il file in scrittura.
    }
  $buffer = dechex(time() + (int)$timeout)."\n".serialize($data);
  $rc = @fwrite($fh, $buffer, strlen($buffer));
  @fclose($fh);
  if(0 == $rc)
    {
    @unlink($fname);
    @flock($fd, LOCK_UN);
    @fclose($fd);
    return(5); // Fallita scrittura cache file.
    }
  @flock($fd, LOCK_UN);
  @fclose($fd);
  return(0); // Tutto OK.
  }

/* La funzione fcache_delete cancella un cache file incondizionatamente.
 *
 * Parametri di input:
 *
 * $fname = nome del file di cache da cancellare. Si consiglia di
 *          fornire il path completo.
 *
 * Codici di ritorno:
 *
 * 0 = Tutto OK.
 * 1 = File inesistente.
 * 2 = Impossibile creare lock file.
 * 3 = Impossibile acquisire WRITE lock.
 */

function fcache_delete($fname)
  {
  clearstatcache();
  if(false == file_exists($fname))
    return(1); // File inesistente.
  $om = file_exists($fname.'.lock') ? 'rb' : 'ab';
  $fd = @fopen($fname.'.lock', $om);
  if(false == $fd)
    return(2); // Impossibile creare lock file.
  if(!(@flock($fd, LOCK_EX)))
    {
    @fclose($fd);
    return(3); // Impossibile acquisire WRITE lock.
    }
  @unlink($fname);
  @unlink($fname.'.lock');
  @flock($fd, LOCK_UN);
  @fclose($fd);
  return(0); // Tutto OK.
  }
?>