[2011–02–17] Přepsán SafeStream

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
David Grudl
Nette Core | 8107
+
0
-

Na základě komentáře jsem upravil třídu SafeStream tak, aby lépe zajišťovala atomicitu a konzistenci zápisů dle pravidla vše nebo nic.

SafeStream dosud poskytoval jednotlivým procesům izolaci, tj. pokud někdo soubor zapisoval, ostatní museli počkat, než to dokončí (a obráceně). Plně atomický byl zápis do nového (tj. neexistujícího) souboru, neboť se zapisovalo do dočasného souboru a ten se nakonec, nedošlo-li k žádné chybě, přejmenoval.

Nová implementace navíc zachovává konzistenci i při zápisu do existujících souborů a to tak, že vytvoří jejich kopii se kterou pracuje a teprve na konci, nedošlo-li k žádné chybě, soubor zpátky přejmenuje. Týká se to režimů r+, a a a+, které jsou nyní pomalejší právě o čas potřebný ke zkopírování souboru.

Byl bych rád, kdybyste mohli vyzkoušet, že upravený SafeStream funguje dobře. (SafeStream je obecně určen spíš pro Linux než NTFS).

viktorc
Člen | 21
+
0
-

Je tam mucha, ktorá sa prejavuje pod Windows (na Linux-e nie) a to v stream_close, keď sa nepodarí premenovať tempFile na file, lebo cieľový subor už existuje:

PHP Warning: rename(xxxx5ad7.css~~0,88915009612421.tmp,xxxx5ad7.css): File exists in …\app\libs\Nette\tools\SafeStream.php:189

Následne sa oba súbory vymažú.

Navrhujem napr:

<?php
//...
flock($this->handle, LOCK_UN);
fclose($this->handle);
unlink($this->file);		// <-- doplnené
fclose($this->tempHandle);

if ($this->writeError || !rename($this->tempFile, $this->file)) { // try to rename temp file
	unlink($this->tempFile); // otherwise delete temp file
	if ($this->deleteFile) {
		unlink($this->file);
	}
}
//...
?>
David Grudl
Nette Core | 8107
+
0
-

Pokud cílový soubor existuje, rename() by ho měl přepsat. Jakou máš verzi PHP?

viktorc
Člen | 21
+
0
-

Na Windows je to PHP 5.2.14, na Linuxe (kde to funguje) 5.2.6.

David Grudl
Nette Core | 8107
+
0
-

Aha, tak to vypadá, že chování rename na Windows se změnilo od PHP 5.3. Fixed.