SafeStream: Dosyalar için Güvenlik

Nette SafeStream, bir dosyaya yapılan her okuma ve yazmanın izole edilmesini garanti eder. Bu, hiçbir iş parçacığının henüz tam olarak yazılmamış bir dosyayı okumaya başlamayacağı veya birden fazla iş parçacığının aynı dosyanın üzerine yazmayacağı anlamına gelir.

Kurulum:

composer require nette/safe-stream

Ne İşe Yarar?

Yalıtılmış işlemler aslında ne işe yarar? Bir dosyaya tekrar tekrar yazan ve ardından aynı dizeyi dosyadan okuyan basit bir örnekle başlayalım:

$s = str_repeat('Uzun Dize', 10000);

$counter = 1000;
while ($counter--) {
	file_put_contents('file', $s); // yaz
	$readed = file_get_contents('file'); // oku
	if ($s !== $readed) { // kontrol et
		echo 'dizeler farklı!';
	}
}

echo 'strings differ!' asla gerçekleşemeyecek gibi görünebilir. Tam tersi doğrudur. Bu betiği aynı anda iki tarayıcı sekmesinde çalıştırmayı deneyin. Hata neredeyse anında ortaya çıkacaktır.

Sekmelerden biri dosyayı, diğerinin henüz tamamını yazmaya fırsat bulamadığı bir zamanda okuyacağından içerik tam olmayacaktır.

Bu nedenle, kod aynı anda birden fazla kez çalıştırılırsa (yani birden fazla iş parçacığında) güvenli değildir. İnternette sık rastlanan bir durumdur, genellikle bir sunucu aynı anda çok sayıda kullanıcıya yanıt verir. Bu nedenle uygulamanızın birden fazla iş parçacığında çalıştırıldığında bile güvenilir bir şekilde çalışmasını sağlamak (thread-safe) çok önemlidir. Aksi takdirde veriler kaybolur ve tespit edilmesi zor hatalar ortaya çıkar.

Ancak görebileceğiniz gibi, PHP'nin yerel dosya okuma ve yazma işlevleri izole ve atomik değildir.

SafeStream Nasıl Kullanılır?

SafeStream, standart PHP fonksiyonlarını kullanarak dosyaları izole bir şekilde okumak ve yazmak için güvenli bir protokol oluşturur. Tek yapmanız gereken dosya adından önce nette.safe:// adresini belirtmektir:

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

SafeStream, bir seferde en fazla bir iş parçacığının dosyaya yazabilmesini sağlar. Diğer iş parçacıkları kuyrukta bekler. Hiçbir iş parçacığı yazmıyorsa, herhangi bir sayıda iş parçacığı dosyayı paralel olarak okuyabilir.

Tüm yaygın PHP fonksiyonları protokol ile kullanılabilir, örneğin:

// 'r' salt okunur olarak aç anlamına gelir
$handle = fopen('nette.safe://file.txt', 'r');

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