SafeStream: biztonságosan a fájlokhoz

A Nette SafeStream garantálja, hogy minden fájlolvasás és -írás izoláltan történik. Ez azt jelenti, hogy egyetlen szál sem kezd el olvasni egy olyan fájlt, amely még nincs teljesen megírva, vagy több szál nem írja felül ugyanazt a fájlt.

Telepítés:

composer require nette/safe-stream

Mire jó ez?

Mire jók valójában az izolált műveletek? Kezdjük egy egyszerű példával, amely ismételten ír egy fájlba, majd ugyanazt a stringet olvassa ki belőle:

$s = str_repeat('Hosszú String', 10000);

$counter = 1000;
while ($counter--) {
	file_put_contents('fajl', $s); // írja be
	$readed = file_get_contents('fajl'); // olvassa ki
	if ($s !== $readed) { // ellenőrizze
		echo 'a stringek különböznek!';
	}
}

Úgy tűnhet, hogy az echo 'a stringek különböznek!' hívás soha nem fordulhat elő. Az ellenkezője igaz. Próbálja meg ezt a szkriptet egyszerre két böngészőfülön futtatni. A hiba gyakorlatilag azonnal bekövetkezik.

Az egyik fül ugyanis akkor olvassa be a fájlt, amikor a másik még nem fejezte be teljesen az írást, így a tartalom nem lesz teljes.

A megadott kód tehát nem biztonságos, ha egyszerre többször hajtják végre (azaz több szálon). Ami az interneten nem szokatlan, gyakran egy időben válaszol a szerver nagyszámú felhasználónak. Tehát annak biztosítása, hogy az alkalmazása megbízhatóan működjön több szálon történő végrehajtás esetén is (thread-safe), nagyon fontos. Ellenkező esetben adatvesztés és nehezen felderíthető hibák keletkeznek.

Ahogy azonban láthatja, a natív PHP fájlolvasási és -írási függvények nem izoláltak és atomiak.

Hogyan használjuk a SafeStream-et?

A SafeStream létrehoz egy biztonságos protokollt, amellyel izoláltan lehet olvasni és írni fájlokat a standard PHP függvények segítségével. Csak annyit kell tenni, hogy a nette.safe:// előtagot kell a fájlnév elé írni:

file_put_contents('nette.safe://fajl', $s);
$s = file_get_contents('nette.safe://fajl');

A SafeStream biztosítja, hogy egyszerre legfeljebb egy szál írhat a fájlba. A többi szál sorban várakozik. Ha egyetlen szál sem ír, akkor tetszőleges számú szál olvashatja párhuzamosan a fájlt.

A protokollal minden szokásos PHP függvény használható, például:

// 'r' azt jelenti, hogy csak olvasásra nyissa meg
$handle = fopen('nette.safe://file.txt', 'r');

$ini = parse_ini_file('nette.safe://translations.neon');
verzió: 3.0