SafeStream: Защита на файловете

Nette\Utils\SafeStream гарантира, че всяко четене и запис в даден файл е изолирано. Това означава, че никоя нишка няма да започне да чете файл, който все още не е напълно записан, или че няколко нишки ще презапишат един и същ файл.

Монтаж:

composer require nette/safe-stream

За какво е полезен?

Каква е действителната полезност на изолираните операции? Нека започнем с прост пример, който многократно записва във файл и след това прочита от него същия низ:

$s = str_repeat('Дълъг низ', 10000);

$counter = 1000;
while ($counter--) {
	file_put_contents('file', $s); // пишем
	$readed = file_get_contents('file'); // читаем
	if ($s !== $readed) { // check it
		echo 'низовете са различни!';
	}
}

Може да изглежда, че echo 'strings differ!' никога не може да се появи. Обратното също е вярно. Опитайте да стартирате този скрипт в два раздела на браузъра едновременно. Грешката ще се появи почти веднага.

Единият от разделите ще прочете файла, докато другият все още не е имал време да запише всичко, така че съдържанието ще бъде непълно.

Следователно кодът не е безопасен, ако се изпълнява многократно едновременно (т.е. в няколко нишки). Това не е рядкост в интернет, тъй като често сървърът отговаря на голям брой потребители едновременно. Ето защо е много важно да се гарантира, че приложението работи надеждно дори когато се изпълнява в няколко нишки (thread-safe). В противен случай ще бъдат загубени данни и ще се появят трудно откриваеми грешки.

Но както виждате, вградените функции на PHP за четене и запис на файлове не са изолирани и атомарни.

Как да използвам SafeStream?

SafeStream създава защитен протокол за изолирано четене и писане на файлове с помощта на стандартни функции на PHP. Всичко, което трябва да направите, е да посочите nette.safe:// преди името на файла:

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

SafeStream гарантира, че не повече от една нишка може да записва във файла едновременно. Другите нишки чакат в опашката. Ако никоя нишка не пише, произволен брой нишки могат да четат файла паралелно.

Всички нормални функции на PHP могат да се използват с протокола, напр:

// 'r' означава отворен само за четене
$handle = fopen('nette.safe://file.txt', 'r');

$ini = parse_ini_file('nette.safe://translations.neon');
версия: 3.0