Autor Zpráva
klus.
Profil *
Ahoj. Zajímám se o problematiku zápisu do stejného textového souboru. Vytvářím logování do souboru, ale bojím se, že kdyby 2 procesy měly otevřený stejný soubor, budou si navzájem přepisovat data. Teoretické řešení nabízí funkce flock, ale ta podle ohlasů také nebude dokonalá. Pokud budu chtít otevřít (fopen) zamknutý soubor - co se stane? Selže otevření nebo selže až případné čtení / zápis? A pokud bude soubor už zamčený, jak se chovat? Čekat ve smyčce dokud se neuvolní zámek?
Majkl578
Profil
Můžeš se atomickými operacemi v Nette (třídou Nette\Utils\SafeStream), případně ji rovnou použít, neměla by mít žádné závislosti na zbytku Nette. Použití je snadné, je vidět v dokumentaci. Sama flock využívá. Jediné co musíš sám udělat je manuální registrace:
Nette\Utils\SafeStream::register();
Pak už můžeš safe:// používat.
klus.
Profil *
Prostudoval jsem tu třídu a tímto způsobem do souborů standardně zapisuji, jen si neregistruji vlastní stream. Když použiju fopen('nejakyprotokol://stream.str') a poté znovu fopen('nejakyprotokol://stream.str') - odstartuje nový stream resp. v případě SafeStream pokus o nové otevření souboru nebo se to připojí k již existujícímu streamu - jen abych pochopil jak streamy v php fungují - z manuálů moc moudrý nejsem.
Majkl578
Profil
klus.:
a poté znovu
Přemýšlím, proč bys tohle úmyslně dělal. Cílem je přece otevřít soubor, přečíst/zapsat bezpečně data a pak soubor uvolnit. Ve chvíli, kdy je soubor aktuálně otevřen, ostatní připojení čekají až do odemčení (jakoby zamrznou). V tvém vlastním zájmu přeci není blokovat spojení, ale jen přečíst/zapsat a hned zas uvolnit.
Otevírat 1 soubor 2× v jednom scriptu přes safe stream způsobí zamrznutí, protože 2. otevření bude čekat do uzavření prvního.
Jak to funguje ve více vláknech si můžeš zkusit jednoduše sám. Otevři script obsahující následující kód ve více oknech prohlížeče (s prodlevou pár vteřin):
require '/www/.../Nette/Utils/SafeStream.php';

Nette\Utils\SafeStream::register();

$a = fopen('safe:///tmp/test', 'w+');
sleep(5);
fclose($a);
1. vlákno soubor uzamkne a za pět sekund odemkne. Mezitím druhé vlákno čeká do odemčení a ve chvíli odemčení ho uzamkne pro sebe (a přesně za 5 sekund skončí - viz sleep).
Davex
Profil
klus.:
Pro účely logování bys mohl využít toho, že je zápis do souboru otevřeného v módu append (fopen('soubor', 'a') nebo file_put_contents('soubor', $data, FILE_APPEND)) atomický (minimálně na Linuxu) a není nutné používat flock(). Pokud ho nebudeš paralelně otevírat v jiném módu, tak by s tím neměl být problém.
klus.
Profil *
Ano, to je vlastnost flocku. Toto také čeká v případě použití zámku jedním procesem:
while(true) {

$fp = fopen("/tmp/lock.txt", "w+");

echo "oteviram\n";
if (flock($fp, LOCK_EX)) { // do an exclusive lock
    echo "otevreno\n";
    sleep(5);
    ftruncate($fp, 0); // truncate file
    fwrite($fp, "Write something here\n");
    flock($fp, LOCK_UN); // release the lock
} else {
    echo "selhalo\n";
    echo "Couldn't get the lock!";
}

fclose($fp);
echo "zavreno\n\n";

sleep(1);

Mě by zajímalo, zda pokud mám otevřený stream a otevřu ho znovu (třeba v jiném php procesu), zda se připojí na již otevřený stream nebo zda vytvoří nový a fopen vrátí handler nového streamu - v takovém případě nemá přístup k souboru přes stream jiný význam než ušetření pár řádek kódu. Jenom mě zajímají vlastnosti streamu v php.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0