SafeStream: Sicherer Dateizugriff

Nette SafeStream garantiert, dass jedes Lesen und Schreiben in eine Datei isoliert erfolgt. Das bedeutet, dass kein Thread beginnt, eine Datei zu lesen, die noch nicht vollständig geschrieben ist, oder dass mehrere Threads nicht dieselbe Datei überschreiben.

Installation:

composer require nette/safe-stream

Wozu ist das gut?

Wozu sind isolierte Operationen eigentlich gut? Beginnen wir mit einem einfachen Beispiel, das wiederholt in eine Datei schreibt und anschließend denselben String daraus liest:

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

$counter = 1000;
while ($counter--) {
	file_put_contents('datei', $s); // schreiben
	$readed = file_get_contents('datei'); // lesen
	if ($s !== $readed) { // prüfen
		echo 'Die Zeichenketten unterscheiden sich!';
	}
}

Es mag scheinen, dass der Aufruf echo 'Die Zeichenketten unterscheiden sich!' niemals erfolgen kann. Das Gegenteil ist der Fall. Versuchen Sie, dieses Skript gleichzeitig in zwei Browser-Tabs auszuführen. Der Fehler tritt praktisch sofort auf.

Einer der Tabs liest nämlich die Datei zu einem Zeitpunkt, zu dem der andere sie noch nicht vollständig geschrieben hat, sodass der Inhalt unvollständig ist.

Der angegebene Code ist also nicht sicher, wenn er mehrmals gleichzeitig ausgeführt wird (also in mehreren Threads). Was im Internet nichts Ungewöhnliches ist, oft bedient ein Server gleichzeitig eine große Anzahl von Benutzern. Daher ist es sehr wichtig sicherzustellen, dass Ihre Anwendung auch bei Ausführung in mehreren Threads zuverlässig funktioniert (thread-safe). Andernfalls kommt es zu Datenverlust und schwer zu entdeckenden Fehlern.

Wie Sie jedoch sehen, sind die nativen PHP-Funktionen zum Lesen und Schreiben von Dateien nicht isoliert und atomar.

Wie verwendet man SafeStream?

SafeStream erstellt ein sicheres Protokoll, mit dem Dateien über Standard-PHP-Funktionen isoliert gelesen und geschrieben werden können. Es genügt, nette.safe:// vor dem Dateinamen anzugeben:

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

SafeStream stellt sicher, dass zu einem Zeitpunkt maximal ein Thread in die Datei schreiben kann. Andere Threads warten in der Warteschlange. Wenn kein Thread schreibt, kann eine beliebige Anzahl von Threads die Datei parallel lesen.

Mit dem Protokoll können alle gängigen PHP-Funktionen verwendet werden, zum Beispiel:

// 'r' bedeutet nur zum Lesen öffnen
$handle = fopen('nette.safe://file.txt', 'r');

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