LE OPERAZIONI DI SET E GET PREVEDONO SERIALIZE ED UNSERIALIZE DEL VALORE (ATTENZIONE AGLI OGGETTI QUINDI) AD ECCEZIONE DELLE GENERAL * I DATI VENGONO SALVATI AUTOMATICAMENTE AL TERMINE DELLO SCRIPT OPPURE CON IL METODO flush() * * include('myForms/mySessions.php'); * * $s1=new mySessions('PROCEDURA A'); //istanzio una mySession per la Procedura A * echo "
Valore pippo in PROCEDURA A:".$s1->get('pippo'); //visualizzo l'eventuale valore associato alla chiave 'pippo' della PROCEDURA A * $s1->set('pippo',$s1->get('pippo')+1,'',10); //incremento il precedente valore e lo salvo per 10 secondi * * echo "
Valore pippo in GENERAL:".$s1->get_general('pippo'); //recupero dalla sessione un valore Generale di 'pippo' (comune a tutte le PROCEDURE e distinto da quello della PROCEDURA A) * $s1->set_general('pippo',$s1->get_general('pippo')+1,'',10); //incremento il precedente valore e lo salvo per 10 secondi * * $s2=new mySessions('PROCEDURA B'); //istanzio una mySession per la Procedura B * echo "
Valore pippo in PROCEDURA B:".$s2->get('pippo'); //visualizzo l'eventuale valore associato alla chiave 'pippo' della PROCEDURA B * $s2->set('pippo',$s2->get('pippo')+1,'',10); //incremento il precedente valore e lo salvo per 10 secondi * * echo "
Valore pippo in GENERAL:".$s2->get_general('pippo'); //recupero dalla sessione un valore Generale di 'pippo' (comune a tutte le PROCEDURE e distinto da quello della PROCEDURA A) * $s2->set_general('pippo',$s2->get_general('pippo')+1,'',10); //incremento il precedente valore e lo salvo per 10 secondi * * Rieseguire questo script ad intervalli di meno di 10 secondi per valutare come si incrementano le variabili, * poi attendere 10 secondi e rilanciarlo per osservare come le variabili si azzerino. * * Notare che il valore valore Generale di 'pippo' è comune a tutte le istanze mySessions, ed è inoltre facilmente accessibile da altri script che accedono * alla $_SESSION direttamente, consiglio quindi di usare i metodi set_general e get_general con estrema cautela e comunque * dando alle variabili nomi particolari. * *
* @access public * @package mySessions */ class mySessions { /**#@+ @ignore */ protected $procedura,$dati, $prefisso='mySessions>',$locks=array(); protected static $nomi=null; /**#@-*/ /** * Costruttore di classe * @access public * @param string $procedura E' il nome della procedura in uso, * tutti gli script che usano MySession con la stessa $procedura vedranno * le medesime variabili di sessione, $procedura non può essere una stringa nulla */ function MySessions($procedura) { if (!isset($_SESSION)) session_start(); if (!$procedura) {return null;} $this->procedura=$procedura; $this->dati=&$_SESSION; if(!is_array(self::$nomi)) self::$nomi=array_flip(@array_keys((array) $this->dati[$this->prefisso.$this->procedura])); } /** Restituisce il valore associato a $nome nella sessione generale è analogo ad eseguire $_SESSION[$nome] * (proprio il comando che si vuole evitare) ma con l'aggiunta dell'eventuale timeout * @param string $nome * @return qualunque */ function get_general($nome) { if (isset($_SESSION['mySessions_General>'][$nome]['Timeout']) && $_SESSION['mySessions_General>'][$nome]['Timeout']del_general($nome); return $_SESSION[$nome]; } /** * Restituisce il true o false se ci sono le condizioni per usare l'istanza * @return boolean */ function is_available() { return is_array(self::$nomi); } function get_procedura() { return $this->procedura; } /** * Inserisce una variabile nella sessione generale
* è analogo ad eseguire $_SESSION[$nome]=$valore * (proprio il comando che si vuole evitare) ma con l'aggiunta dell'eventuale timeout * TUTTI GLI SCRIPT (ANCHE QUELLI DI ALTRE PROCEDURE) POTRANNO UTILIZZARLA; * PERTANTO USARLA CON MOLTA CAUTELA E SOPRATTUTTO USARE NOMI PARTICOLARI * I DATI NON VENGONO SERIALIZZATI QUANDO SI USA QUESTO METODO, QUINDI E' IMPORTANTE CHE TUTTI * GLI SCRIPT DA INCLUDERE LO SIANO STATI PRIMA DI AVVIARE LA SESSIONE O RISULTERANNO INCOMPLETI * * @param string $nome Nome assegnato alla variabile (da usare per richiamarla) * @param qualunque $valore Valore da associare al $nome * @param boolean $forzaNulli Se vero $nome viene inserito nella sessione anche quando $valore è nullo di default è false * @param int $timeOut imposta la durata in secondi della variabile nella sessione, se omesso o 0 la variabile non ha scadenza * @return boolean esito dell'operazione (se $nome è nullo non fa nulla e restituisce false) */ function set_general($nome,$valore='',$forzaNulli=false,$timeOut=0) { if ($nome && ($forzaNulli || ($valore!==null && $valore!=='' && $valore!==0)) ) { $this->dati[$nome]=$valore; if ($timeOut) $_SESSION['mySessions_General>'][$nome]['Timeout']=time()+$timeOut; return true; } return false; } /** * elimina una variabile dalla sessione generale * * @param string $nome della variabile */ function del_general($nome) { unset($_SESSION[$nome]); unset($_SESSION['mySessions_General>'][$nome]); } /** * Inserisce una variabile nella sessione, durante l'inserimento * la variabile è serializzata. * OGNI VOLTA CHE SI ESEGUE QUESTA OPERAZIONE I DATI VENGONO SERIALIZZATI, (QUINDI ATTENZIONE AGLI OGGETTI) * IN QUESTO MODO E' POSSIBILE INCLUDERE GLI SCRIPT DI DEFINIZIONE DELLE CLASSI DI OGGETTI SALVATI ANCHE DOPO AVER AVVIATO LA SESSIONE, * MA COMUNQUE PRIMA DI RECUPERARLI. * * @param string $nome Nome assegnato alla variabile (da usare per richiamarla) * @param qualunque $valore Valore da associare al $nome * @param boolean $forzaNulli Se vero $nome viene inserito nella sessione anche quando $valore è nullo di default è false * @param int $timeOut imposta la durata in secondi della variabile nella sessione, se omesso o 0 la variabile non ha scadenza * @return boolean esito dell'operazione (se $nome è nullo non fa nulla e restituisce false) */ function set($nome,$valore='',$forzaNulli=false,$timeOut=0) { if ($nome && ($forzaNulli || ($valore!==null && $valore!=='' && $valore!==0)) && ($dato=@serialize($valore))!=='') {self::$nomi[$nome]=1; $this->dati[$this->prefisso.$this->procedura][$nome]['Dati']=$dato; if ($timeOut) $this->dati[$this->prefisso.$this->procedura][$nome]['Timeout']=time()+$timeOut; else unset($this->dati[$this->prefisso.$this->procedura][$nome]['Timeout']); return true; } return false; } /** * Ottiene un lock basato su file tra script diversi se true lock ottenuto, false non ottenuto * * @param string $nome_lock codice mnemonico lock * @param int $attesa_max attesa massima in microsecondi (su windows e con PHP<5.3 il lock è sempre bloccante quindi l'attesa non è applicabile) , 0 non ha attesa affatto * @param int $timeout_naturale inapplicato, il lock si rilascia con mySession::release_lock() o quando lo script termina * @param string $directory eventuale directory in cui salvare i file di lock * @return boolean */ function get_lock($nome_lock,$attesa_max=0,$timeout_naturale=0,$directory='') { if (!is_dir($directory) || !is_writable($directory)) $directory=ini_get('session.save_path'); if (!is_dir($directory) || !is_writable($directory)) $directory=$_SERVER["TEMP"]; if (!is_dir($directory) || !is_writable($directory)) $directory=dirname(__FILE__); $fine=microtime(1)+$attesa_max/1000000; $pref=str_replace(array('*','?',':','>','<','|'),'_',$this->prefisso); $this->locks[$nome_lock]=array('file'=>"$directory/{$pref}_{$nome_lock}.lck"); do { if(!is_resource($this->locks[$nome_lock]['res'])) $this->locks[$nome_lock]['res'] =@fopen($this->locks[$nome_lock]['file'],'c'); if(is_resource($this->locks[$nome_lock]['res'])) $this->locks[$nome_lock]['lock']=@flock($this->locks[$nome_lock]['res'], LOCK_NB|LOCK_EX); } while (!$this->locks[$nome_lock]['lock'] && microtime(1)<=$fine); if(!$this->locks[$nome_lock]['lock']) unset($this->locks[$nome_lock]); return $this->locks[$nome_lock]['lock']; } function release_lock($nome_lock) { @fclose($this->locks[$nome_lock]['res']); @unlink($this->locks[$nome_lock]['file']); unset($this->locks[$nome_lock]); } function __destruct(){ if($this->locks) foreach ($this->locks as $lock => $value) $this->release_lock($lock); } /** * Inserisce più variabili nella sessione in un'unica volta * @param array $valori Array associativo con tutti i 'nomi'=>'valori' da inserire * @param boolean $forzaNulli Se vero vengono inseriti nella sessione anche 'nomi' con 'valori' nulli; di default è false * @param int $timeOut imposta la durata in secondi della variabile nella sessione, se omesso o 0 la variabile non ha scadenza * @return boolean esito dell'operazione (se $valori è nullo non fa nulla e restituisce false) */ function sets($valori,$forzaNulli=false,$timeOut=0) { if ($valori && count($valori)>0) { foreach ($valori as $nome=>$valore) if ($nome) $this->set($nome,$valore,$forzaNulli,$timeOut); return true; } return false; } /** Restituisce il valore associato a $nome * @param string $nome * @return qualunque */ function get($nome) { $valore=null; if (isset($this->dati[$this->prefisso.$this->procedura][$nome]['Timeout']) && $this->dati[$this->prefisso.$this->procedura][$nome]['Timeout']del($nome); if (isset($this->dati[$this->prefisso.$this->procedura][$nome])) $valore=@unserialize($this->dati[$this->prefisso.$this->procedura][$nome]['Dati']); if ($valore===false) return $this->dati[$this->prefisso.$this->procedura][$nome]['Dati']; else return $valore; } /** Restituisce un array associativo con più valori della sessione * @param array $nomi array non associativo con l'elenco dei nomi da usare nell'estrazione, se omesso si estrarranno tutte i valori della sessione * @return qualunque */ function gets($nomi=array()) { $v=array(); if(self::$nomi) foreach (self::$nomi as $nome) if (!$nomi || in_array($nome,self::$nomi)) {$v[$nome]=$this->get($nome); if ($v[$nome]===null) unset($v[$nome]); } return $v; } /** Elimina $nome dalla sessione * @param string $nome */ function del($nome) { unset(self::$nomi[$nome]); unset($this->dati[$this->prefisso.$this->procedura][$nome]); } /** Elimina tutte le voci in $nomi dalla sessione * @param array $nomi non associativo con l'elenco dei nomi da usare nell'estrazione, se omesso SI DISTRUGGE TUTTO IL CONTENUTO DELL'INTERA SESSIONE */ function dels($nomi=array()) { if(self::$nomi) foreach (self::$nomi as $nome=>$null) if (!$nomi || in_array($nome,self::$nomi)) $this->del($nome); } /** * Crea una variabile GLOBALE di nome $nome estraendola (se esiste) dalla sessione * Es. Se in uno script scriviamo: * * include_once('../MyForms/mySessions.php'); * $s=new MySessions('procedura_x'); //istanzio la classe * $s->set('CF',$_GET['CODICE_FISCALE']); //senza terzo parametro ha effetto solo quando $_GET è valorizzato * ... * * * Ed in un altro script scriviamo: * * include_once('../MyForms/mySessions.php'); * $s=new MySessions('procedura_x'); * $s->globalize('CF'); * //da questo momento esiste una variabile $CF con il valore precedentemente memorizzato nella sessione * ... * * * @param string $nome * @return void */ function globalize($nome) { global $$nome; $$nome=$this->get($nome); } /** * Forza il salvataggio dei dati della sessione * @link http://it2.php.net/manual/it/function.session-write-close.php * */ function flush() { session_write_close(); } /** * Crea tante variabili GLOBALI con i nomi nell'array $nomi estraendone i valori (se esistono) dalla sessione * Es. Se in uno script scriviamo: * * include_once('../MyForms/mySessions.php'); * $s=new MySessions('procedura_x');//istanzio la classe * $s->set('CF',$_GET['CODICE_FISCALE']); //senza terzo parametro ha effetto solo quando $_GET è valorizzato * $s->set('ALTRO','PIPPO',true); //forza l'inserimento di ALTRO nella sessione con valore PIPPO * ... * * * Ed in un altro script scriviamo: * * include_once('../MyForms/mySessions.php'); * $s=new MySessions('procedura_x'); * $s->globalizes( array('CF','ALTRO') ); * //da questo momento esistono sia $CF che $ALTRO con i valori precedentemente memorizzati nella sessione * ... * * * @param array $nomi * @return void */ function globalizes($nomi=array()) { if (count($nomi)) foreach ($nomi as $nome) $this->globalize($nome); } /** Vedi globalize ma per la sessione generale * @param string $nome **/ function globalize_general($nome) { global $$nome; $$nome=$this->get_general($nome); } } /** * Analoga alle mySessions nei metodi ma diversa nel funzionamento. * Tutte le variabili vengono salvate in dei file condivisi da tutti gli script. * Mentre i dati di una mySessions sono accessibili dagli script eseguiti nell'ambito di una finestra del browser * i dati di una MyFileSessions sono condivisi tra tutti gli script ini esecuzione e non si perdono quando si chide la finestra (come con le sessioni). * Utile quando ci sono informazioni che si vogliono condividere per migliorare le prestazioni indipendentemente dalle sessioni attive (es. numero di accessi) * * * LE OPERAZIONI DI SET E GET PERVEDONO SEMPRE SERIALIZE ED UNSERIALIZE DEL VALORE (ATTENZIONE AGLI OGGETTI QUINDI) * I DATI VENGONO SALVATI AUTOMATICAMENTE AL TERMINE DELLO SCRIPT O ATTRAVERSO IL METODO flush() * * * PROVARE A LANCIARE QUESTO SCRIPT DA DUE SESSIONI DIVERSE E CONFRONTARLO CON IL COMPORTAMENTO DELL'ANALOGO SCRIPT DELLE mySessions. * * * include('myForms/mySessions.php'); * * $s1=new MyFileSessions('PROCEDURA A'); //istanzio una mySession per la Procedura A * echo "
Valore pippo in PROCEDURA A:".$s1->get('pippo');//visualizzo l'eventuale valore associato alla chiave 'pippo' della PROCEDURA A * $s1->set('pippo',$s1->get('pippo')+1,'',10); //incremento il precedente valore e lo salvo per 10 secondi * * echo "
Valore pippo in GENERAL:".$s1->get_general('pippo'); //recupero dalla sessione un valore Generale di 'pippo' (comune a tutte le PROCEDURE e distinto da quello della PROCEDURA A) * $s1->set_general('pippo',$s1->get_general('pippo')+1,'',10); //incremento il precedente valore e lo salvo per 10 secondi * * $s2=new MyFileSessions('PROCEDURA B'); //istanzio una mySession per la Procedura B * echo "
Valore pippo in PROCEDURA B:".$s2->get('pippo'); //visualizzo l'eventuale valore associato alla chiave 'pippo' della PROCEDURA B * $s2->set('pippo',$s2->get('pippo')+1,'',10); //incremento il precedente valore e lo salvo per 10 secondi * * echo "
Valore pippo in GENERAL:".$s2->get_general('pippo'); //recupero dalla sessione un valore Generale di 'pippo' (comune a tutte le PROCEDURE e distinto da quello della PROCEDURA A) * $s2->set_general('pippo',$s2->get_general('pippo')+1,'',10); //incremento il precedente valore e lo salvo per 10 secondi * * Rieseguire questo script ad intervalli di meno di 10 secondi per valutare come si incrementano le variabili, * poi attendere 10 secondi e rilanciarlo per osservare come le variabili si azzerino. * * Notare che il valore valore Generale di 'pippo' è comune a tutte le istanze mySessions, ed è inoltre facilmente accessibile da altri script che accedono * alla $_SESSION direttamente, consiglio quindi di usare i metodi set_general e get_general con estrema cautela e comunque * dando alle variabili nomi particolari. * * *
* @access public * @package mySessions * */ class myFileSessions extends MyStorageSessions { /**#@+ @ignore */ protected $percorso='', $prefisso='MFS_', $stato=null, $modificate=array(); protected static $percorso_default; protected function my_delete($k) {return mySessions::del($k);} protected function my_store($k,&$v,$ttl=0) {} protected function my_get($k) {} function is_available(){return @is_dir($this->percorso);} /**#@-*/ /** * Costruttore di classe * @access public * @param string $procedura E' il nome della procedura in uso,
* tutti gli script che usano MyFileSessions con la stessa $procedura vedranno * le medesime variabili, $procedura non può essere una stringa nulla */ function __construct($procedura,$directory='') { static $dati,$modificate; if (!$procedura) {return null;} $this->procedura=$procedura; if ($directory) {if(!is_dir($directory)) @mkdir($directory,0777,true); $this->percorso=$directory; } if (!is_dir($this->percorso)) {if(!is_dir(self::$percorso_default)) @mkdir(self::$percorso_default,0777,true); $this->percorso=self::$percorso_default; } if (!is_dir($this->percorso)) $this->percorso=ini_get('session.save_path'); if (!is_dir($this->percorso)) $this->percorso=$_SERVER["TEMP"]; if (!is_dir($this->percorso)) $this->percorso=dirname(__FILE__); $this->percorso.='/MyFileSessions'; if (!is_dir($this->percorso) && !@mkdir($this->percorso,null,1)) return null; $this->modificate=&$modificate; $this->dati=&$dati; if(!is_array(self::$nomi)) self::$nomi=array_flip(@array_keys((array) $this->dati[$this->prefisso.$this->procedura])); if (!$this->dati[$this->prefisso.$this->procedura]) $this->load_procedura(); } /** * Imposta il percorso di default in cui verranno salvati i dati delle istanze myFileSessions * * @param string $percorso */ static function set_percorso_default($percorso){ self::$percorso_default=$percorso; } function set_compress_status($status) {} function get_status() { return $this->stato; } /** @ignore */ function flock_get_contents($filename){ $return=false; if($handle = @fopen($filename, 'r')) {flock($handle, LOCK_SH); $return=@fread($handle,filesize($filename)); flock($handle, LOCK_UN); @fclose($handle); } return $return; } /** * Ottiene un lock basato su file tra script diversi se true lock ottenuto, false non ottenuto * * @param string $nome_lock codice mnemonico lock * @param int $attesa_max attesa massima in microsecondi (su windows e con PHP<5.3 il lock è sempre bloccante quindi l'attesa non è applicabile) , 0 non ha attesa affatto * @param int $timeout_naturale inapplicato, il lock si rilascia con mySession::release_lock() o quando lo script termina * @return boolean */ function get_lock($nome_lock,$attesa_max=0,$timeout_naturale=0) { $fine=microtime(1)+$attesa_max/1000000; $pref=str_replace(array('*','?',':','>','<','|'),'_',$this->prefisso); $this->locks[$nome_lock]=array('file'=>"{$this->get_nome_file_procedura()}.{$nome_lock}.lck"); print_r($this->locks[$nome_lock]); do { if(!is_resource($this->locks[$nome_lock]['res'])) $this->locks[$nome_lock]['res']=@fopen($this->locks[$nome_lock]['file'],'c'); if(is_resource($this->locks[$nome_lock]['res'])) $this->locks[$nome_lock]['lock']=@flock($this->locks[$nome_lock]['res'], LOCK_NB|LOCK_EX); } while (!$this->locks[$nome_lock]['lock'] && microtime(1)<=$fine); if(!$this->locks[$nome_lock]['lock']) unset($this->locks[$nome_lock]); return $this->locks[$nome_lock]['lock']; } /** @ignore */ function load_general($handle='') { if (!$handle) $dati=@$this->flock_get_contents($this->get_nome_file_generale()); else $dati=@fread($fp,@filesize($this->get_nome_file_generale())); if ($dati===false) return false; $this->dati[$this->prefisso]=@unserialize($dati); if (!$this->dati[$this->prefisso]) $this->dati[$this->prefisso]=array(); if (time()-@filemtime($this->get_nome_file_generale())>3600*24) $this->check_scaduti_generale(); return true; } function get($nome) { return mySessions::get($nome); } /** @ignore */ function load_procedura($handle='') { if (!$handle) $dati=@$this->flock_get_contents($this->get_nome_file_procedura()); else $dati=@fread($fp,@filesize($this->get_nome_file_procedura())); if ($dati===false) return false; $this->dati[$this->prefisso.$this->procedura]=@unserialize($dati); if (!$this->dati[$this->prefisso.$this->procedura]) $this->dati[$this->prefisso.$this->procedura]=array(); if (time()-@filemtime($this->get_nome_file_procedura())>3600) $this->check_scaduti_procedura(); //echo "
";	print_r($this->get('GRAFICA'));exit;
		return true;					
	}
	
	
	 function flush_procedura() {
            if (!$this->modificate['procedura'][$this->prefisso.$this->procedura]) return true;
            $temp=$this->dati[$this->prefisso.$this->procedura]; 
            
            $fp=@fopen($this->get_nome_file_procedura(),'w+');
            if(!$fp) return false;
            @flock($fp, LOCK_EX);
      
            $this->load_procedura($fp);        
            foreach ($this->modificate['procedura'][$this->prefisso.$this->procedura] as $chiave=>$segno)
                                          {
                                          if ($segno=='-') unset($this->dati[$this->prefisso.$this->procedura][$chiave]);
                                                    else $this->dati[$this->prefisso.$this->procedura][$chiave]=&$temp[$chiave];
                                          }                          
                                         
                                                                       
            $out=serialize($this->dati[$this->prefisso.$this->procedura]);
            $ok=rewind($fp) && (fwrite($fp,$out)===strlen($out)) && ftruncate($fp,strlen($out));
            @flock($fp, LOCK_UN);
            @fclose($fp);
            if ($ok) unset($this->modificate['procedura'][$this->prefisso.$this->procedura]);
                  else  @unlink($this->get_nome_file_procedura());
            return $ok;         
            }
      
           
      
      function flush_general() {
            if (!$this->modificate['general'][$this->prefisso]) return true;
            $temp=$this->dati[$this->prefisso];
            
            $fp=@fopen($this->get_nome_file_generale(),'w+');
                  
            @flock($fp, LOCK_EX);
            $this->load_general($fp);
            foreach ($this->modificate['general'][$this->prefisso] as $chiave=>$segno) {
						 if ($segno=='-') unset($this->dati[$this->prefisso][$chiave]);
									else $this->dati[$this->prefisso][$chiave]=&$temp[$chiave];
            			}                           
            
            $out=serialize($this->dati[$this->prefisso]);
            $ok=@rewind($fp) && @fwrite($fp,$out)===strlen($out) && @ftruncate($fp,strlen($out));
            
            @flock($fp, LOCK_UN);
            @fclose($fp);
            
            if (!$ok) @unlink($this->get_nome_file_generale());
                   else unset($this->modificate['general'][$this->prefisso]);      
            return $ok;
      }

	
	
	/** @ignore */
	function check_scaduti_generale() {
		foreach ( $this->dati[$this->prefisso] as $nome=>&$v ) $this->get_general($nome);
	}
	
	
	/** @ignore */
	function get_nome_file_procedura() {
		return "{$this->percorso}/{$this->prefisso}_".base64_encode($this->procedura).'.dat';
	}
	
	
	/** @ignore */
	function check_scaduti_procedura() {
		foreach ( $this->dati[$this->prefisso.$this->procedura] as $nome=>&$v ) $this->get($nome);
	}
	
	
	/** @ignore */
	function get_nome_file_generale() {
		return "{$this->percorso}/{$this->prefisso}.dat";
	}
	
	
	/**
	 * Salva i dati su disco, solo da quel momento diventano disponibili per gli altri script
	 * su PHP5 i dati si salvano in automatico anche al termine dello script, su PHP4 occorre invocarlo esplicitamente
	 *
	 * @param boolean $procedura salva i dati della procedura indicata nel costruttore
	 * @param boolean $general   salva i dati generali
	 * @return boolean esito
	 */
	function flush($procedura=true, $general=true){
		if ($procedura) $esito_procedura=$this->flush_procedura();
		if ($general)   $esito_general=$this->flush_general();
		return $this->stato=(!$procedura || $esito_procedura) && (!$general || $esito_general);
	}
	
	 
    
    function set($nome,$valore='',$forzaNulli=false,$timeOut=0) {
    	$this->modificate['procedura'][$this->prefisso.$this->procedura][$nome]='+';
        $esito=mySessions::set($nome,$valore,$forzaNulli,$timeOut);	
        if(!$esito) $this->del($nome)	;
        return $esito; 
    }
    
     function del($nome) {
    	$this->modificate['procedura'][$this->prefisso.$this->procedura][$nome]='-';
     	return mySessions::del($nome); 
    }
    
    
   
    
   function get_general($nome) {
		if (!isset($this->dati[$this->prefisso])) $this->load_generale();
        if (isset($this->dati[$this->prefisso][$nome]['Timeout']) && 
		 	 	   $this->dati[$this->prefisso][$nome]['Timeout']del_general($nome);
		 return @unserialize($this->dati[$this->prefisso][$nome]['Dati']);
    }    
    
    
    function set_general($nome,$valore='',$forzaNulli=false,$timeOut=0) {
    if (!isset($this->dati[$this->prefisso])) $this->load_general();
       if ($nome && ($forzaNulli || ($valore!==null && $valore!=='' && $valore!==0)) && ($dato=@serialize($valore))!=='')  
		 		{$this->modificate['general'][$this->prefisso][$nome]='+';
		 		 $this->dati[$this->prefisso][$nome]['Dati']=$dato;
		 		 if ($timeOut) $this->dati[$this->prefisso][$nome]['Timeout']=time()+$timeOut;
		 		 return true;
		 		}
		 return false;		
    }
	
    
   function del_general($nome) {
   		if (!isset($this->dati[$this->prefisso])) $this->load_generale();
   	    $this->modificate['general'][$this->prefisso][$nome]='-';
   	   	unset($this->dati[$this->prefisso][$nome]);
    }	
    
}


/**
 * I dati vengono salvati sul file ma in RAM, quindi ancora più performante.
 * Unico vincolo (oltre alla dimensione della memoria) è che sia attiva e funzionante l'estensione ZendCache dello Zend Server
 * Il salvataggio è contestuale al set/unset quindi il metodo flush() è inutile.
 *
 * @package mySessions
 */

class myZendSessions extends myStorageSessions {
/**#@+ @ignore */	
protected  $prefisso='MZS';

	protected function my_delete($k) {return @zend_shm_cache_delete($k); }
	protected function my_store($k,&$v,$ttl=0) {return @zend_shm_cache_store($k,$v,$ttl); }
	protected function my_get($k) {return @zend_shm_cache_fetch($k); }
	function dels()        {@zend_shm_cache_clear("{$this->prefisso}_{$this->procedura}");}
	function is_available(){return is_callable('zend_shm_cache_store');}
	
/**#@-*/
	
	
	
 	/**
     * Ottiene un lock se true lock ottenuto, false non ottenuto
     * funziona solo se Zend_Cache prevede emulazione APC (come di default)
     * 
     * @param string $nome_lock codice mnemonico lock 
     * @param int $attesa_max    attesa massima in microsecondi , 0 non ha attesa 
     * @param int $timeout_naturale numero di secondi dopo di che il lock si rilascia ugualmente, se 0 non scade mai, attenzione!
     * @return boolean 
     */
    function get_lock($nome_lock,$attesa_max=0,$timeout_naturale=0) {
    	$fine=microtime(1)+$attesa_max/1000000;
		do {
		    $locked=@apc_add("{$this->prefisso}_$nome_lock",1,($timeout_naturale?$timeout_naturale:2592000));
		} while (!$locked && microtime(1)<=$fine);
		return $locked;
    }
    
    
     function release_lock($nome_lock) {@apc_delete("{$this->prefisso}_$nome_lock");}
	 function delete($k) {return @zend_shm_cache_delete($k);}
	 function flush() { }
}





/**
 * I dati vengono salvati sul file ma in RAM, quindi ancora più performante.
 * Unico vincolo (oltre alla dimensione della memoria) è che sia attiva e funzionante l'estensione wincache
 * Il salvataggio è contestuale al set/unset quindi il metodo flush() è inutile.
 * 
 * @link  http://it2.php.net/manual/en/book.wincache.php Manuale Wincache 
 * @access public
 * @package mySessions
 */
class myWincacheSessions extends MySessions {
/**#@+ @ignore */	
protected  $prefisso='MWCS';


protected function my_delete($k){return @wincache_ucache_delete($k);	  }
protected function my_get($k){	return @wincache_ucache_get($k);    }
protected function my_store($k,&$v,$ttl=0){	return @wincache_ucache_set($k,$v,$ttl);  }
/**#@-*/
	

 	/**
     * Ottiene un lock se true lock ottenuto, false non ottenuto
     * 
     * @param string $nome_lock codice mnemonico lock 
     * @param int $attesa_max    attesa massima in microsecondi , 0 non ha attesa 
     * @param int $timeout_naturale numero di secondi dopo di che il lock si rilascia ugualmente, se 0 non scade mai, attenzione!
     * @return boolean 
     */
    function get_lock($nome_lock,$attesa_max=0,$timeout_naturale=0) {
    	$fine=microtime(1)+$attesa_max/1000000;
		do {
		    $locked=@wincache_ucache_add("{$this->prefisso}_$nome_lock",1,($timeout_naturale?$timeout_naturale:2592000));
		} while (!$locked && microtime(1)<=$fine);
		return $locked;
    }
    
    
    function release_lock($nome_lock) {
    	@wincache_ucache_delete("{$this->prefisso}_$nome_lock");
    }
	
	
	function is_available(){
	 	return is_callable('wincache_ucache_info');
	 }
	 
	function get_status() {
		return wincache_ucache_info('user');
	}
	
	function flush() {}
}


/**
 * Classe astratta per la costruzione di mySession con funzionamento di storage
 * I DATI SONO CONDIVISI TRA TUTTI GLI SCRIPT E NON LEGATI ALLA SESSSIONE UTENTE COME PER LA CLASSE MADRE
 * 
 * @abstract
 * @package mySessions
 */
abstract class myStorageSessions extends mySessions{
	/**#@+ @ignore */
	protected $compress=false;
    function get_lock($nome_lock,$attesa_max=0,$timeout_naturale=0){throw new Exception ('Metodo da reimmplementare');}
    function release_lock($nome_lock){throw new Exception ('Metodo da reimmplementare');}
	function is_available(){throw new Exception ('Metodo da reimmplementare');}
	function flush(){throw new Exception ('Metodo da reimmplementare');}


	protected function my_compress(&$v) {
		$v=serialize($v);
		if(strlen($v)>512) $v=gzcompress($v,5);
	}
	
	protected function my_uncompress(&$v) {
		if($v{0}=='x') {$x=gzuncompress($v);
						if($x!==null) $v=$x;
						}
		$v=unserialize($v);
	}
	
	
	abstract protected  function my_delete($k);
	abstract protected  function my_get($k);
	abstract protected  function my_store($k,&$v,$ttl=0);
	
	function __destruct() {
		$this->compress=false;
		$this->my_store("{$this->prefisso}_{$this->prefisso}_nomi",self::$nomi);
		$this->flush();
	}
	
	/**#@-*/

	
	function __construct($procedura) {
			if (!$procedura) {return;}
			$this->procedura=$procedura;
			if(!is_array(self::$nomi) && !$this->is_available()) self::$nomi=$this->my_get("{$this->prefisso}_{$this->prefisso}_nomi");
	}
	
	function set_general($nome,$valore='',$forzaNulli=false,$timeOut=0) {
		if ($nome && ($forzaNulli || ($valore!==null && $valore!=='' && $valore!==0)))
		  {if($this->compress)  $this->my_compress($valore);
		   $esito=$this->my_store("{$this->prefisso}_$nome",$valore,(int) $timeOut);
		   return $esito;
		  }
		return false;
	}
	
	function get_general($nome) {
		$valore=$this->my_get("{$this->prefisso}_$nome");
		if($this->compress) $this->my_uncompress($valore);
		return $valore;
	}
	
	
	function del_general($nome) {
		return $this->my_delete("{$this->prefisso}_$nome");
	}
	
	function set($nome,$valore='',$forzaNulli=false,$timeOut=0) {
		if ($nome && ($forzaNulli || ($valore!==null && $valore!=='' && $valore!==0)))
			{if($this->compress)  $this->my_compress($valore);
			 $esito=$this->my_store("{$this->prefisso}_{$this->procedura}::$nome",$valore,(int) $timeOut);
			 if($esito) self::$nomi[$nome]=1;
			 return $esito;
			}
		return false;
	}
	
	function &get($nome) {
		$valore=$this->my_get("{$this->prefisso}_{$this->procedura}::$nome");
		if($this->compress) $this->my_uncompress($valore);
		
		return $valore;
	}
	
	function del($nome) {
		unset(self::$nomi[$nome]);
		return $this->MY_delete("{$this->prefisso}_{$this->procedura}::$nome");
	}
	
	
	/**
	 * Restituite lo stato compressione non ha effetto su myFileSessions
	 * @return boolean 
	 */
	function get_compress_status($status) {
		return $this->compress;
	}
	
	/**
	 * Imposta l'uso della compressione dei dati  non ha effetto su myFileSessions
	 * @param 0..9 $status se -1 i dati non vengono compressi , altrimenti indica il fattore i compressione gzcompress 
	 */
	function set_compress_status($status) {
		if(is_callable('gzcompress')) $this->compress=$status;
		return $this;
	}
}


/**
 * I dati vengono salvati sul file ma in RAM, quindi ancora più performante.
 * Unico vincolo (oltre alla dimensione della memoria) è che sia attiva e funzionante l'estensione APC
 * Il salvataggio è contestuale al set/unset quindi il metodo flush() è inutile.
 * 
 * @link  http:/http://www.php.net/manual/en/book.apc.php Manuale APC 
 * @access public
 * @package mySessions
 */
class myAPCSessions extends myStorageSessions {
/**#@+ @ignore */	
protected $prefisso='MAPCS';
	
	  protected function my_delete($k){return @apc_delete($k);	  }
	  protected function my_get($k){	return @apc_fetch($k);    }
	  protected function my_store($k,&$v,$ttl=0){	return @apc_store($k,$v,$ttl);  }
/**#@-*/	  
	  
	
 	/**
     * Ottiene un lock se true lock ottenuto, false non ottenuto
     * 
     * @param string $nome_lock codice mnemonico lock 
     * @param int $attesa_max    attesa massima in microsecondi , 0 non ha attesa 
     * @param int $timeout_naturale numero di secondi dopo di che il lock si rilascia ugualmente, se 0 non scade mai, attenzione!
     * @return boolean 
     */
    function get_lock($nome_lock,$attesa_max=0,$timeout_naturale=0) {
    	$fine=microtime(1)+$attesa_max/1000000;
		do {
		    $locked=@apc_add("{$this->prefisso}_$nome_lock",1,($timeout_naturale?$timeout_naturale:2592000));
		} while (!$locked && microtime(1)<=$fine);
		return $locked;
    }


    function is_available(){
    	return is_callable('apc_cache_info');
    }
    
    
    function release_lock($nome_lock) {
    	@apc_delete("{$this->prefisso}_$nome_lock");
    }
	 
	function get_status() {
		return apc_sma_info(true);
	}
	
	 function flush() {}
}

/**
 * Analoga alle MyFileSessions nei metodi e nel funzionamento,
 * i dati però non vengono salvati sul file ma in RAM, quindi ancora più performante.
 * Unico vincolo (oltre alla dimensione della memoria) è che sia attiva e funzionante l'estensione memcache
 * Il salvataggio è contestuale al set/unset quindi il metodo flush() è inutile.
 * 
 * @link  http://it2.php.net/manual/it/ref.memcache.php Manuale memcache
 * @access public
 * @package mySessions
 */
class myMemcacheSessions extends myStorageSessions {
/**#@+ @ignore */	
protected $prefisso='MMS',$maxSizeItem=1048000;
protected $memcache;protected static $memcaches=array();  
/**#@-*/   
 
	/**
	 * Costruttore di classe
	 *
	 * @access public
	 * @param string $procedura
	 * @param string/array $server il nome (o i nomi) nel formato ip:porta:peso (quest'ultimo nel caso siano più server) 
	 * @param object &$memcache è l'istanza di memcache creata oppure è l'eventuale istanza di memcache da utilizzare (va bene anche un'istanza di Memcached)
	 * @param boolean &$errore viene settato a true se c'è un'errore durante la connessione al server
	 */
	function __construct($procedura,$server='127.0.0.1:11211:0',&$memcache=null,&$errore=false) 
		{$k=sha1(serialize($server));
		if(is_object($memcache)) $this->memcache=self::$memcaches[$k]=$memcache;
		   elseif(is_object(self::$memcaches[$k]))  $this->memcache=self::$memcaches[$k];
			 	else{
					 if(!is_array($server)) $server=array($server);
					 if(class_exists('Memcache')) 
					 		{$memcache=new Memcache;
					 		 foreach ($server as $srv) {
					   			$srv=explode(':',$srv);
					   			$memcache->addServer($srv[0],($srv[1]?$srv[1]:11211),true,1,($srv[2]?$srv[2]:1));
					 			}
					 		}
					 if(!is_object($this->memcache) && class_exists('Memcached')) 
					 		{$memcache=new Memcached($this->prefisso);
					 		 foreach ($server as $srv) {
					   			$srv=explode(':',$srv);
					   			$memcache->addServer($srv[0],($srv[1]?$srv[1]:11211),($srv[2]?$srv[2]:0));
					 			}
					 		}
					 if (@$memcache->getVersion()) $this->memcache=self::$memcaches[$k]=$memcache;
					 }
		if(is_object($this->memcache)) parent::__construct($procedura);			 
	 }
		
		
	function is_available(){
		return is_object($this->memcache);
	}	
	
	
	/** @ignore */
	protected function my_delete($k){
		if(!is_object($this->memcache)) return false;
		if(!$this->maxSizeItem) return @$this->memcache->delete($k, 0);
		do {$deleted=@$this->memcache->delete("$k$next",0);
			$i++;
			if($i) $next="/next~$i";
		}while ($deleted);
		return true;
	}
	

	/** @ignore */
	protected function my_get($k){
		if(!is_object($this->memcache)) return false;
		if(!$this->maxSizeItem) return @$this->memcache->get($k);
		$v='';
		$keys=array();
		do {$keys[]="$k$next";
			if($i%5==1) {   $vals=$this->real_get($keys);
							$v.=implode('',$vals);
							if(!$vals[$keys[count($keys)-1]]) break;
							$keys=array();
					 	}
			$next="/next~".(++$i);
		} while (true);
		if(!$this->compress) return @unserialize($v);
		return $v;
	}
	
	
	/**
	 * @ignore
	 */
	protected function my_store($k,&$to_store,$ttl=0){
		if(!is_object($this->memcache)) return false;
		if(!$this->compress) $to_store=serialize($to_store);
		$esito=true;
		do {echo "
storing ",($i>0?"$k/next~$i":$k); $esito=$esito && $this->real_store(($i>0?"$k/next~$i":$k), substr($to_store, $i*$this->maxSizeItem,$this->maxSizeItem),$ttl); }while($esito && ++$i*$this->maxSizeItemreal_store('', $TO_STORE); return $esito; } /** @ignore */ private function &real_get(array &$k){ if($this->memcache instanceof Memcache) return @$this->memcache->get($k); if($this->memcache instanceof Memcached) return @$this->memcache->getMulti($k); } /** @ignore */ private function real_store($k,&$v,$ttl=0){ if($ttl>30*24*3600) $ttl=30*24*3600; if($this->memcache instanceof Memcached) return @$this->memcache->set($k,$v,$ttl); if($this->memcache instanceof Memcache) return @$this->memcache->set($k,$v,($this->maxSizeItem?0:MEMCACHE_COMPRESSED),$ttl); } /** * Ottiene un lock se true lock ottenuto, false non ottenuto * * @param string $nome_lock codice mnemonico lock * @param int $attesa_max attesa massima in microsecondi , 0 non ha attesa * @param int $timeout_naturale numero di secondi dopo di che il lock si rilascia ugualmente, se 0 scade dopo 30 giorni (durata max per memcache), attenzione! * @return boolean */ function get_lock($nome_lock,$attesa_max=0,$timeout_naturale=0) { $fine=microtime(1)+$attesa_max/1000000; do { $locked=@$this->memcache->add("{$this->prefisso}_$nome_lock",1,0,($timeout_naturale?$timeout_naturale:2592000)); } while (!$locked && microtime(1)<=$fine); return $locked; } function release_lock($nome_lock) { @$this->memcache->delete("{$this->prefisso}_$nome_lock"); } function get_status($type='') { if(!$type) return $this->memcache->getStats(); else return $this->memcache->getExtendedStats($type); } function flush() {@$this->memcache->flush();} } abstract class myAutoSessions { static function get_Istanza($procedura, $options=array( 'myZendSessions'=>array(), 'myAPCSessions'=>array(), 'myWincacheSessions'=>array(), 'myMemcacheSessions'=>array('127.0.0.1:11211'), 'myFileSessions'=>array() ) ){ $test_fun=array( 'myapcsessions'=>'apc_cache_info', 'myzendsessions'=>'zend_shm_cache_store', 'mywincachesessions'=>'wincache_ucache_info' ); foreach ($options as $class=>&$pars) { $class=strtolower($class); if(isset($test_fun[$class]) && !is_callable($test_fun[$class])) continue; $rc = new ReflectionClass($class); $obj=$rc->newInstanceArgs(array_merge(array($procedura) , (array) $pars)); if($obj->is_available()) return $obj; unset($obj);unset($rc); } return false; } } ?>