Nette SafeStream

Nette SafeStream garantiert, dass jede Lese- und Schreiboperation an einer Datei isoliert abläuft. Das bedeutet, dass kein Thread beginnt, eine Datei zu lesen, die noch nicht vollständig geschrieben ist, und dass mehrere Threads dieselbe Datei nicht gegenseitig ü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 aus ihr liest:

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

$counter = 1000;
while ($counter--) {
	file_put_contents('file', $s); // schreiben
	$readed = file_get_contents('file'); // lesen
	if ($s !== $readed) { // prüfen
		echo 'strings are different!';
	}
}

Es mag scheinen, dass der Aufruf echo 'strings are different!' niemals eintreten kann. Das Gegenteil ist der Fall. Versuchen Sie, dieses Skript in zwei Browser-Tabs gleichzeitig auszuführen. Der Fehler tritt fast sofort auf.

Einer der Tabs liest die Datei in dem Moment, in dem der andere sie noch nicht vollständig zu Ende geschrieben hat, der Inhalt ist deshalb unvollständig.

Der Code ist also nicht sicher, wenn er mehrfach gleichzeitig ausgeführt wird (also in mehreren Threads). Im Internet ist das nichts Ungewöhnliches, denn Server antworten oft einer großen Zahl von Nutzern gleichzeitig. Sicherzustellen, dass Ihre Anwendung auch bei der Ausführung in mehreren Threads zuverlässig arbeitet (thread-safe), ist entscheidend. Andernfalls kann es zu Datenverlust und schwer aufzuspürenden Fehlern kommen.

Wie Sie sehen, sind die nativen Funktionen von PHP zum Lesen und Schreiben von Dateien aber weder isoliert noch atomar.

Wie verwendet man SafeStream?

SafeStream schafft ein sicheres Protokoll, über das sich Dateien mit den üblichen PHP-Funktionen isoliert lesen und schreiben lassen. Sie müssen dem Dateinamen nur nette.safe:// voranstellen:

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

SafeStream stellt sicher, dass zu einem Zeitpunkt höchstens ein Thread in die Datei schreiben kann. Die übrigen Threads warten in einer Warteschlange. Schreibt kein Thread, kann eine beliebige Zahl von Threads die Datei parallel lesen.

Mit dem Protokoll lassen sich alle gängigen PHP-Funktionen verwenden, zum Beispiel:

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

$ini = parse_ini_file('nette.safe://config.ini');

Einschränkungen

SafeStream isoliert das Lesen und Schreiben des Dateiinhalts, kann aber nicht jede Operation atomar machen. Behalten Sie diese Grenzen im Blick:

  • Informationen über Dateien sind nicht isoliert. Funktionen, die nur Metadaten abfragen, etwa file_exists(), filesize() oder is_file(), nehmen an der Sperrung nicht teil. Sie können Informationen über eine Datei zurückgeben, die ein anderer Thread gerade schreibt.
  • Löschen einer geöffneten Datei unter Windows. Anders als Unix erlaubt Windows nicht, eine Datei zu löschen, die ein anderer Thread gerade geöffnet hat, unlink('nette.safe://file') kann also fehlschlagen.
  • Automatisches Zurücksetzen unvollständiger Schreibvorgänge. Schlägt ein Schreibvorgang mittendrin fehl (etwa weil die Festplatte voll läuft), kürzt SafeStream die Datei beim Schließen auf die Größe zurück, die sie vor Beginn des Schreibens hatte, und hinterlässt so nie teilweise geschriebene Daten.

Wenn Sie auf eine neuere Version aktualisieren, sehen Sie sich die Seite Upgrade an.

Version: 3.x