Newsgroup: it.comp.www.php
Titolo: Numero progressivo univoco

Ciao a tutti
avendo bisogno di un numero progressivo univoco ho creato un file di testo 
che contiene il numero
Il file viene aperto, letto e richiuso poi riaperto e scritto con il numero 
a cui è stato aggiunta un'unità
Purtroppo pur in casi rareissimi accade che ogni tanto i numeri siano uguali 
per il fatrto forse che è stato aperto da due persone contemporaneamente
Il file infatti non viene apoerto in modo esclusivo e io non saprei come 
fare ad aprire in modo esclusivo.
Poi non saprei come fare a gestire l'esclusività per il secondo arrivato che 
deve aspettre il sipo tutmo
Potete aoiitarmi?
Grazie

 numero a cui  stato aggiunta un'unit
E` qui che sbagli.
Devi aprire il file in lettura/scrittura una volta sola, leggere il 
valore, tornare all'inizio e scrivere il nuovo valore.
Quando apri un file in scrittura dovrebbe essere automaticamente bloccato 
in lettura per tutti gli altri, ma per alcuni filesystem e S.O. questo 
puo` non essere vero, quindi guardati le funzioni di lock (tipo flock() )
Bye.

 Potete aoiitarmi?
Prova ad utilizzare la funzione flock:
http://it.php.net/manual/it/function.flock.php
=== 
http://www.negusweb.it
 ===

per il fatrto forse che è stato aperto da due persone contemporaneamente
Se il file e' locale (UN server - UN disco), usa flock() e vai tranquillo.
In altri casi, puo' darsi (non e' detto - a Cthulhu piacendo) che tu debba
ricorrere a un trucco: all'incirca:
	unset($id);
	$newname = uniqid('') . '.tmp';
	for ($try = 0; $try < 5; $try++)
	{
		// Sposto il file sotto un altro nome
		@rename($file, $newname);
		// Controllo di essere io ad essere riuscito nell'intento
		// (magari eravamo in due a cercare di fare il rename)
		if (!file_exists($newname))
		{
			sleep(1);
			continue;
		}
		// Ora nessuno sa che il file si chiama $newname - tranne
		// me. Posso usare $newname in sicurezza
		$id = file_get_contents($newname)+1;
		$fp = fopen($newname, 'w');
		fwrite($fp, $id);
		fclose($fp);
		// Quando ho finito, faccio ricomparire il file.
		rename($newname, $file);
		break;
	}
	if (!isset($id))
	{
		// Qualcosa di brutto
	}
...cosi', ogni processo ha un "proprio" file, e il filesystem deve fare in
modo che i filesystem mostrati ai vari processi siano sincronizzati. In un
caso (server web in parallelo, file su un NAS), non c'e' stato altro verso
di far funzionare le cose - flock() e compagnia giuravano di funzionare, e
non era vero.
Leonardo
-- 
 What do you make, so fair and bright;
 What do you build with sails for flight;
 What do you weave with wool so white?

 Bye.
il mio script era:
<?PHP
$cont=fopen('cont.txt','r');
$incr=fgets($cont);
$incr++;
fclose($cont);
$cont=fopen('cont.txt','w');
fwrite($cont,$incr);
fclose($cont);
?> 

Ho cercato di applicare qualche vostro consiglio e ho scritto questo 
sorgente
<?PHP
$file="protocollo.txt";
for ($try = 0; $try < 5; $try++)
{
$id = file_get_contents($file)+1;
$fp = fopen($file, 'w');
if (flock($fp, LOCK_EX))
{
fwrite($fp, $id);
flock($fp, LOCK_UN);
break;
}
else
{sleep(1);
continue;}}
fclose($fp);
echo $id;
?>
a casa lavora ma a casa ci sono solo io e non so come testarlo.
Cosa succede secondo voi se due persone cercano di entrare insieme?
Grazie

 $fp = fopen($file, 'w');
Uhm, no.
Qui hai un problema di concorrenza. Tra un'istruzione e l'altra un altro 
utente potrebbe leggere il file.
Usa qualcosa tipo (metacodice non testato, in parte copiato dal manuale 
online):
<?php
$fp = fopen($file, "a+");
if (flock($fp, LOCK_EX)) { // do an exclusive lock
    fseek($fp, 0);
    $id = fread($fp, 1024);
    $id++;
    ftruncate($fp, 0);
    fwrite($fp, strval($id));
    flock($fp, LOCK_UN); // release the lock
} else {
    echo "Couldn't lock the file !";
}
fclose($fp);
?> 

 ?>
Ho capito
Ma se due utenti usano MALAUGURATAMENTE mello stesso medesimo istante la 
procedura che assegna il protocollo cosa succede?

 
Il secondo trova il file bloccato e esce con il mex "Couldn't lock the 
file !";
Nel caso trovi il file bloccato, potresti fare un ciclo di attesa con 
uno sleep ma, visto che ti preoccupi tanto della concorrenza, perchè non 
passi la palla al database, e utilizzi un bel campo autoincrement? 
Inoltre il corretto funzionamento dipende da troppe variabili (OS, file 
system, ...)
	Francesco

 procedura che assegna il protocollo cosa succede?
Non ho mai provato, e il manuale non e` chiarissimo, ma mettendo il terzo 
parametro di flock a TRUE, il secondo processo dovrebbe rimanere in attesa 
finche` il lock non viene liberato dal primo processo.
Bye.

 procedura che assegna il protocollo cosa succede?
uno dei due non otterra' il lock e finira' nella "spazzatura" :-)
e' un problema classico quello che hai.. e le soluzioni sono molte e tutte
con qualche svantaggio..
prova a cercare con google race condition o meglio mutual exclusion..
http://en.wikipedia.org/wiki/Mutual_exclusion
 da qui probabilmente puoi
raggiungere qualche algoritmo valido..
ma comunque ricorda che puoi sempre appoggiarti su un db che di solito
risolve gia' da solo questi problemi garantendo atomicita' per ogni query o
transazione..
-- 
www.iuz-lab.info
 - 
www.php-faq.org