Atomicita operací se soubory

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
mildhouse
Člen | 27
+
0
-

Ahoj

jak je to v Nette s atomickymi operacemi?

Přečetl jsem si tento článek https://doc.nette.org/cs/safe-stream kde je příklad :

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

$counter = 1000;
while ($counter--) {
    file_put_contents('soubor', $s); // write it
    $readed = file_get_contents('soubor'); // read it
    if ($s !== $readed) { // check it
        echo 'řetězce se liší!';
    }
}

Citace textu : Může se zdát, že volání echo ‚řetězce se liší!‘ nikdy nemůže nastat. Opak je pravdou. Schválně si zkuste tento skript spustit ve dvou oknech zároveň. Chyba se dostaví prakticky okamžitě.

Podle mě ne. I kdybych to spustil v 10ti oknech zároveň, file_put_contents() vloží vždy stejný řetězec (10000 x 'Long String') a vždy stejný řetězec načte.

Tak jsem si funkci trochu upravil :

// v Nette 2.0.12 - HomepagePresenter.php

class HomepagePresenter extends BasePresenter{

	public function actionDefault(){
		$string = $this->getParameter('string');

		$s = str_repeat($string, 100000);

		$counter = 3000;
		while ($counter--) {
    			file_put_contents('soubor.txt', $s); // write it
    			$readed = file_get_contents('soubor.txt'); // read it
    			if ($s !== $readed) { // check it
        			echo 'řetězce se liší!';
    			}
		}

	}

}


// mimo Nette - index.php

$string = $_GET['string'];

$s = str_repeat($string, 100000);

$counter = 3000;
while ($counter--) {
	file_put_contents('soubor.txt', $s); // write it
	$readed = file_get_contents('soubor.txt'); // read it
	if ($s !== $readed) { // check it
		echo 'řetězce se liší!';
	}
}

A spustil, napřed mimo Nette, v prvním okně test-atomicita.cz?string=LongString a v druhém okně test-atomicita.cz?string=LooooooongerString a podle očekávání došlo k vypsání 'řetězce se liší!'

Pak jsem to spustil v Nette – v prvním okně nette-atomicita.cz?string=LongString a v druhém okně nette-atomicita.cz?string=LooooooongerString ale k vypsání 'řetězce se liší!' nedošlo

Jakto, že v Nette proběhla operace atomicky, když jsem nepoužil Nette\Utils\SafeStream? Nenašel jsem Nette\Utils\SafeStream v API takže to je deprecated a Nette automaticky provádí atomické operace se soubory?

Díky

Majkl578
Moderator | 1364
+
0
-

Zkus to s delším stringem a chyba se určitě dostaví. :)

Pro:

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

mi stačily 2 scripty paralelně.

Nenašel jsem Nette\Utils\SafeStream v API takže to je deprecated a Nette automaticky provádí atomické operace se soubory?

V API není protože je (kdovíproč) @internal.
Automaticky určitě nic neprovádí, musíš vždy použít protokol safe://.

enumag
Člen | 2118
+
0
-

Není deprected ale internal, proto se v API nezobrazuje. Že se to v Nette neprojevilo je zvláštní, mělo by. SafeStream se použije jen když bys napsal file_put_contents('safe://soubor.txt', $s);.

Jan Tvrdík
Nette guru | 2595
+
0
-

@mildhouse: Máš v tom bordel, když budeš zapisovat ve dvou různých tabech různé řetězce, tak tě ani Nette SafeStream nezachrání a stejně to vypíše, že řetězce se liší. Pokud ti to náhodou chybu nevypisuje, tak máš štěstí nebo moc rychlý disk.