SafeStream: Varnost za datoteke

Nette SafeStream zagotavlja, da je vsako branje in pisanje v datoteko izolirano. To pomeni, da nobena nit ne bo začela brati datoteke, ki še ni v celoti zapisana, ali da več niti ne bo prepisalo iste datoteke.

Namestitev:

composer require nette/safe-stream

Za kaj je dobra?

Za kaj so pravzaprav dobre izolirane operacije? Začnimo s preprostim primerom, ki večkrat zapiše v datoteko in nato iz nje prebere isti niz:

$s = str_repeat('Long String', 10000);

$counter = 1000;
while ($counter--) {
	file_put_contents('file', $s); // napišite ga.
	$readed = file_get_contents('file'); // ga preberite.
	if ($s !== $readed) { // ga preveri.
		echo 'strings are different!';
	}
}

Morda se zdi, da se echo 'strings differ!' ne more nikoli pojaviti. Res je ravno nasprotno. Poskusite zagnati to skripto v dveh zavihkih brskalnika hkrati. Napaka se bo pojavila skoraj takoj.

Eden od zavihkov bo prebral datoteko v času, ko drugi še ni imel priložnosti zapisati vsega, zato vsebina ne bo popolna.

Zato koda ni varna, če se izvaja večkrat hkrati (tj. v več niti). Kar v internetu ni redkost, saj se strežnik pogosto odziva na večje število uporabnikov naenkrat. Zato je zelo pomembno zagotoviti, da vaša aplikacija zanesljivo deluje tudi pri izvajanju v več niti (thread-safe). V nasprotnem primeru se bodo izgubili podatki in pojavile se bodo težko zaznavne napake.

Toda kot lahko vidite, nativni funkciji PHP za branje in pisanje datotek nista izolirani in atomični.

Kako uporabljati SafeStream?

SafeStream ustvari varen protokol za izolirano branje in pisanje datotek z uporabo standardnih funkcij PHP. Vse, kar morate storiti, je, da pred imenom datoteke navedete nette.safe://:

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

SafeStream zagotavlja, da lahko v datoteko hkrati piše največ ena nit. Druge niti čakajo v čakalni vrsti. Če nobena nit ne piše, lahko datoteko vzporedno bere poljubno število niti.

S protokolom je mogoče uporabljati vse običajne funkcije PHP, npr:

// 'r' pomeni odprto samo za branje
$handle = fopen('nette.safe://file.txt', 'r');

$ini = parse_ini_file('nette.safe://translations.neon');
različica: 3.0