Nette SafeStream
Nette SafeStream garantisce che ogni operazione di lettura e scrittura di file avvenga in isolamento. Questo significa che nessun thread comincerà a leggere un file che non è ancora stato scritto per intero, né più thread sovrascriveranno lo stesso file.
Installazione:
composer require nette/safe-stream
A che cosa serve?
A che cosa servono davvero le operazioni isolate? Cominciamo da un semplice esempio che scrive ripetutamente in un file e poi ne rilegge la stessa stringa:
$s = str_repeat('Long String', 10000);
$counter = 1000;
while ($counter--) {
file_put_contents('file', $s); // scriviamo
$readed = file_get_contents('file'); // leggiamo
if ($s !== $readed) { // controlliamo
echo 'le stringhe sono diverse!';
}
}
Potrebbe sembrare che la chiamata echo 'le stringhe sono diverse!' non possa mai verificarsi. È vero il
contrario. Provate a lanciare questo script in due schede del browser contemporaneamente. L'errore si verificherà quasi
subito.
Una delle schede leggerà il file in un momento in cui l'altra non ha ancora finito di scriverlo del tutto, quindi il contenuto sarà incompleto.
Il codice non è perciò sicuro se viene eseguito più volte contemporaneamente (cioè in più thread). Su internet non è una cosa insolita, perché i server rispondono spesso a un gran numero di utenti contemporaneamente. Garantire che la vostra applicazione funzioni in modo affidabile anche eseguita in più thread (thread-safe) è fondamentale. Altrimenti si può arrivare alla perdita di dati e a errori difficili da individuare.
Come vedete, però, le funzioni native di PHP per leggere e scrivere i file non sono isolate né atomiche.
Come si usa SafeStream?
SafeStream crea un protocollo sicuro tramite il quale i file si possono leggere e scrivere in isolamento usando le normali
funzioni di PHP. Basta anteporre al nome del file nette.safe://:
file_put_contents('nette.safe://file', $s);
$s = file_get_contents('nette.safe://file');
SafeStream garantisce che al massimo un thread alla volta possa scrivere nel file. Gli altri thread aspettano in coda. Se nessun thread sta scrivendo, un numero qualsiasi di thread può leggere il file in parallelo.
Con il protocollo si possono usare tutte le comuni funzioni di PHP, per esempio:
// 'r' significa aprire solo in lettura
$handle = fopen('nette.safe://file.txt', 'r');
$ini = parse_ini_file('nette.safe://config.ini');
Limitazioni
SafeStream isola la lettura e la scrittura del contenuto dei file, ma non può rendere atomica ogni operazione. Tenete presenti questi limiti:
- Le informazioni sui file non sono isolate. Le funzioni che interrogano solo i metadati, come
file_exists(),filesize()oppureis_file(), non partecipano al lock. Possono restituire informazioni su un file che un altro thread sta scrivendo in quel momento. - Cancellare un file aperto su Windows. A differenza di Unix, Windows non vi lascia cancellare un file che un altro
thread ha aperto in quel momento, quindi
unlink('nette.safe://file')può fallire. - Rollback automatico delle scritture incomplete. Se una scrittura fallisce a metà (per esempio il disco si riempie), alla chiusura del file SafeStream lo tronca alla dimensione che aveva prima dell'inizio della scrittura, così non lascia mai dietro di sé dati scritti solo in parte.
Se state aggiornando a una versione più recente, guardate la pagina aggiornamento.