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

před 7 lety

David Grudl
founder | 6753
+
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).

před 7 lety

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);
    }
}
//...
?>

před 7 lety

David Grudl
founder | 6753
+
0
-

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

před 7 lety

viktorc
Člen | 21
+
0
-

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

před 7 lety

David Grudl
founder | 6753
+
0
-

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