[2011–02–17] Přepsán SafeStream
- David Grudl
- Nette Core | 8227
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
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 | 8227
Pokud cílový soubor existuje, rename() by ho měl přepsat. Jakou máš verzi PHP?
- David Grudl
- Nette Core | 8227
Aha, tak to vypadá, že chování rename na Windows se změnilo od PHP 5.3. Fixed.