Ahoj.
Načítám celkem velký objem dat (několik giga) po kouskách o velikosti typicky 2096 bajtů. A následně ho zapisuju do souboru v tempu:
$tmpdir = sys_get_temp_dir();
$tmpname = tempnam($tmpdir, 'app-');
$handle = fopen($tmpname, 'a');
// velikost $s je obvykle 2096 bajtů
function write($s)
{
$len = strlen($s);
$wrote = fwrite($handle, $s);
if ($len !== $wrote) {
echo "\n\nERROR: Nesedí počet zapsaných bytů. C1 {$wrote} ~ {$len}\n\n"; // "419 ~ 2096"
var_dump(error_get_last()); // nic
$wrote2 = fwrite($handle, substr($s, $wrote));
if ($wrote2 !== ($len - $wrote)) {
echo "\n\n{$s}\n\n"; // zde vidím, že to není poslední záznam. Je to uřízlé uprostřed textu.
throw new RuntimeException('Nesedí počet zapsaných bytů. C2 ' . "{$wrote2} ~ " . ($len - $wrote) ); // "0 ~ 1677"
}
}
}
Celé mi to chcípne na tom, že nesedí počet zapsaných bajtů. Je možné, že mi třeba došlo místo v tempu, nebo tak něco. Ale vadí mi, že mi to nevypíše žádnou chybu.
Otázka tedy zní, jak zjistím, co se stalo?
Děkuji za odpověď.
Nevládnu PHP, ale nepomohlo by tohle?
https://stackoverflow.com/questions/9473474/php-fwrite-doesnt-finish-writing-string-data-to-file-why#9473840
sice se člověk nedozví, kde to zkrachovalo, ale funkce, zmíněná v odkazu údajně garantuje přepis celého řetězce.
Funkce fwrite negarantuje, že zapíše všechny znaky. Musíte si posouvat ukazatel v řetězci a opakovat funkci tak dlouho, dokud nezapíše vše. Pokud by došlo k chybě, vrací fwrite FALSE.
$len = strlen($s);
$wrote = fwrite($handle, $s, $len);
Citace od: Filip Jirsák kdy 30. 06. 2018, 15:45:53
Funkce fwrite negarantuje, že zapíše všechny znaky. Musíte si posouvat ukazatel v řetězci a opakovat funkci tak dlouho, dokud nezapíše vše. Pokud by došlo k chybě, vrací fwrite FALSE.
Nechápu, jak to souvisí s mojí otázkou?
Citace od: andreaw.fean kdy 30. 06. 2018, 16:38:19
Nechápu, jak to souvisí s mojí otázkou?
Máte ten kód špatně. Porovnáváte počet zapsaných bajtů s počtem bajtů k zapsání, a když nesouhlasí, považujete to za chybu. Ale ona to chyba není, počet zapsaných bajtů může být v rozmezí 0 až počet bajtů k zapsání.
fwrite prostě zapíše tolik bajtů, kolik zrovna zapsat může, a vy si musíte zkontrolovat, zda už zapsal všechno, a když ne, tak to otočit v cyklu a zapsat další část. Podívejte se na dokumentaci fwrite (http://php.net/manual/en/function.fwrite.php), tammáte hned v první poznámce příklad, jak má zápis do souboru vypadat správně.
Citace od: Filip Jirsák kdy 30. 06. 2018, 16:42:54
Citace od: andreaw.fean kdy 30. 06. 2018, 16:38:19
Nechápu, jak to souvisí s mojí otázkou?
Máte ten kód špatně. Porovnáváte počet zapsaných bajtů s počtem bajtů k zapsání, a když nesouhlasí, považujete to za chybu. Ale ona to chyba není, počet zapsaných bajtů může být v rozmezí 0 až počet bajtů k zapsání. fwrite prostě zapíše tolik bajtů, kolik zrovna zapsat může, a vy si musíte zkontrolovat, zda už zapsal všechno, a když ne, tak to otočit v cyklu a zapsat další část. Podívejte se na dokumentaci fwrite (http://php.net/manual/en/function.fwrite.php), tammáte hned v první poznámce příklad, jak má zápis do souboru vypadat správně.
Přečtěte si prosím nejdříve ten kód, dobře?
Citace od: Kit kdy 30. 06. 2018, 16:27:31
$len = strlen($s);
$wrote = fwrite($handle, $s, $len);
To by bylo hloupé, ale zkusím to.
Citace od: BoneFlute kdy 30. 06. 2018, 16:47:18
Přečtěte si prosím nejdříve ten kód, dobře?
Nejprve si vy velmi pomalu přečtěte, co jsem vám napsal ve svém prvním komentáři. Máte tam vysvětlené, jak funguje funkce
fwrite a proč máte ten kód špatně. Pak si přečtěte dokumentaci funkce
fwrite, abyste to lépe chápal, odkaz jsem vám dával.
$len = strlen($s);
$wrote = fwrite($handle, $s);
if ($len !== $wrote) {
echo "\n\nERROR: Nesedí počet zapsaných bytů. C1 {$wrote} ~ {$len}\n\n"; // "419 ~ 2096"
Konkrétně tady jsou špatně ty poslední dva řádky, protože to, že se zapsalo méně bajtů, než kolik jich bylo k dispozici, není chyba, je to standardní chování funkce
fwrite.
Citace od: andreaw.fean kdy 30. 06. 2018, 16:50:39
Citace od: Kit kdy 30. 06. 2018, 16:27:31
$len = strlen($s);
$wrote = fwrite($handle, $s, $len);
To by bylo hloupé, ale zkusím to.
Klidně to zkuste, ale ničemu to nepomůže, protože třetí parametr funkce fwrite je nepovinný, a pokud není uveden, zapisuje se celý řetězec. Tedy uvedený kód je ekvivaletní s tímhle:
$wrote = fwrite($handle, $s);Nebývá špatné přečíst si dokumentaci, pak se nemusíte ptát na věci, které jsou tam napsané.
Citace od: Filip Jirsák kdy 30. 06. 2018, 16:55:19
Nebývá špatné přečíst si dokumentaci, pak se nemusíte ptát na věci, které jsou tam napsané.
V dokumentaci je napsáno přesně to, co jsem psal, tedy že třetí parametr je v takových případech nutný.
Citace od: Filip Jirsák kdy 30. 06. 2018, 16:55:19
Citace od: andreaw.fean kdy 30. 06. 2018, 16:50:39
Citace od: Kit kdy 30. 06. 2018, 16:27:31
$len = strlen($s);
$wrote = fwrite($handle, $s, $len);
To by bylo hloupé, ale zkusím to.
Klidně to zkuste, ale ničemu to nepomůže, protože třetí parametr funkce fwrite je nepovinný, a pokud není uveden, zapisuje se celý řetězec. Tedy uvedený kód je ekvivaletní s tímhle:
$wrote = fwrite($handle, $s);
Nebývá špatné přečíst si dokumentaci, pak se nemusíte ptát na věci, které jsou tam napsané.
Děkuji za příspěvek. Stále nechápu jak by mi mohl alespoň vzdáleně pomoci s mým problémem. Opakování zápisu je použito už v tom kódu, nevím tedy proč mi to doporučujete. Cožpak jste ten kód nečetl, než jste psal svou radu?
Citace od: Kit kdy 30. 06. 2018, 17:22:20
V dokumentaci je napsáno přesně to, co jsem psal, tedy že třetí parametr je v takových případech nutný.
Vy jste napsal jenom kus kódu, žádné vysvětlení, natož něco o ,,takových případech". Ty hranaté závorky kolem parametru
$length v definici funkce označují, že je parametr nepovinný, pak je to ještě zopakované u samotného parametru: ,,If the length argument is given...". Pokud narážíte na to, že přítomnost parametru $length zároveň znamená,že s ebude ignorovat volba
magic_quotes_runtime, my nevíme ani co chce zapisovat ani jak má tuto volbu nastavenou.
Citace od: andreaw.fean kdy 30. 06. 2018, 17:32:11
Stále nechápu jak by mi mohl alespoň vzdáleně pomoci s mým problémem.
Váš problém je, že si myslíte, že došlo k chybě, ve skutečnosti k žádné chybě nejspíš nedošlo. Zda došlo k chybě otestujete tak, že návratovou hodnotu funkce
fwrite() porovnáte s hodnotou
FALSE.
Citace od: andreaw.fean kdy 30. 06. 2018, 17:32:11
Opakování zápisu je použito už v tom kódu
Ne, není. Jak jste přišel na to, že při druhém volání se zapíše vše? Volání se musí opakovat tak dlouho, dokud nejsou zapsaná všechna data. Používají se k tomu cykly.
Citace od: andreaw.fean kdy 30. 06. 2018, 17:32:11
Cožpak jste ten kód nečetl, než jste psal svou radu?
Přestaňte pořád hledat chyby u jiných, když je ta chyba jenom ve vašem kódu. Četl jste tu poznámku s příkladem v dokumentaci
fwrite(), kterou jsem odkazoval? Vidíte tam ten cyklus? Připadá vám, že takový cyklus máte ve svém kódu?
Je mi líto, ale žádné úžasné řešení asi neexistuje.
Funkce fwrite() je jen alias na php_stream_write() a ten nijak zvlášť neřeší důvod nezápisu.
Funkce file_put_contents() sice zařve, že se nepovedlo zapsat ale přičinu, "possibly out of free disk space" si bohapustě vycucá z prstu. Je fakt, že to bude nejčastější příčina, protože práva etc si zjistíš už při fopen().
Citace od: Filip Jirsák kdy 30. 06. 2018, 17:38:23
Citace od: andreaw.fean kdy 30. 06. 2018, 17:32:11
Opakování zápisu je použito už v tom kódu
Ne, není. Jak jste přišel na to, že při druhém volání se zapíše vše? Volání se musí opakovat tak dlouho, dokud nejsou zapsaná všechna data. Používají se k tomu cykly.
Doufám @andreaw.fean, že tě nenapadne se jeho radou řídit :-)
Citace od: Filip Jirsák kdy 30. 06. 2018, 17:38:23
<heap of sh*t snipped>
Poslechni Jirsáku, tady maj něco pro tebe (https://ona.idnes.cz/foto.aspx?r=modni-trendy&c=A180627_104815_modni-trendy_kace&foto=KAC744567_profimedia_0279978734.jpg) - možná bys mohl být ohleduplný k ostatním a taky na svůj hormonální cyklus upozornit... Ono je to nesnesitelné i normálně, ale dneska už jseš opravdu zralej na ránu bazukou.
:o ??? ::)
Citace od: BoneFlute kdy 30. 06. 2018, 18:33:33
Je mi líto, ale žádné úžasné řešení asi neexistuje.
Funkce fwrite() je jen alias na php_stream_write() a ten nijak zvlášť neřeší důvod nezápisu.
Funkce file_put_contents() sice zařve, že se nepovedlo zapsat ale přičinu, "possibly out of free disk space" si bohapustě vycucá z prstu. Je fakt, že to bude nejčastější příčina, protože práva etc si zjistíš už při fopen().
Pokud skutečně dojde k chybě (což zjistíte testem, zda hodnota vrácená funkci
fwrite() je
FALSE), bude nejspíš kód chyby v
posix_get_last_error(). PHPčkové
fwrite je jenom obálka nad libc
fwrite(), která vrací chybu v
errno, a tuhle hodnotu vrací právě
posix_get_last_error().
Citace od: BoneFlute kdy 30. 06. 2018, 18:36:01
Doufám @andreaw.fean, že tě nenapadne se jeho radou řídit :-)
Bacha na to, povídat si sám se sebou, to už je nemoc...
Citace od: Filip Jirsák kdy 30. 06. 2018, 18:52:52
Citace od: BoneFlute kdy 30. 06. 2018, 18:33:33
Je mi líto, ale žádné úžasné řešení asi neexistuje.
Funkce fwrite() je jen alias na php_stream_write() a ten nijak zvlášť neřeší důvod nezápisu.
Funkce file_put_contents() sice zařve, že se nepovedlo zapsat ale přičinu, "possibly out of free disk space" si bohapustě vycucá z prstu. Je fakt, že to bude nejčastější příčina, protože práva etc si zjistíš už při fopen().
Pokud skutečně dojde k chybě (což zjistíte testem, zda hodnota vrácená funkci fwrite() je FALSE), bude nejspíš kód chyby v posix_get_last_error(). PHPčkové fwrite je jenom obálka nad libc fwrite(), která vrací chybu v errno, a tuhle hodnotu vrací právě posix_get_last_error().
Není. Nezjistíš.
Citace od: BoneFlute kdy 30. 06. 2018, 18:36:01
Citace od: Filip Jirsák kdy 30. 06. 2018, 17:38:23
Citace od: andreaw.fean kdy 30. 06. 2018, 17:32:11
Opakování zápisu je použito už v tom kódu
Ne, není. Jak jste přišel na to, že při druhém volání se zapíše vše? Volání se musí opakovat tak dlouho, dokud nejsou zapsaná všechna data. Používají se k tomu cykly.
Doufám @andreaw.fean, že tě nenapadne se jeho radou řídit :-)
Udělat si tam cyklus? Nejsem blbej.
Problém skutečně byl v tom nedostatku místa.
Přidal jsem si tam test pomocí funkce disk_free_space. Problém to nevyřeší, ale budu vědět co je to za problém.
fwrite() return values jsou docela zmatené, obojí false a 0 znamenají chybu. false je chyba v parametrech, zatímco 0 je chyba provádění (typicky chyba vrácená OS - out of space apod.). Více detailů první komentář v dokumentaci. 0 jako korektní hodnota je nesmysl, protože vždycky se musí něco zapsat. V případě, že by došlo k blokování a je nastaven NONBLOCK, vrací se chyba EAGAIN. Předpokládám, že v rámci "kompatibility" je dobré ošetřít false a 0 stejně :-)
V tom kódu je třeba zpracovat error_get_last na místě, kde se vyhazuje výjimka, tam se vrátí asi finální chyba. Kromě toho jsou tam k opravě následující:
- loop while writte != 0 místo jednoho if (i když technicky vzato běžné OS zapíšou všechno co jde, pokud jde o normální soubor, jinak je to u pipe, socket apod)/li]
- nevím, jak je to u php s konverzí znakových sad a DOS/UNIX konverzí, soubor musí být v každém případě otevřen jako binary.
- ... a podobně jako v předchozím - viz poslední argument, který vypíná magic chování, které rovněž může ovlivnit délku zápisu.
Citace od: kvr kvr kdy 30. 06. 2018, 19:05:06
fwrite() return values jsou docela zmatené, obojí false a 0 znamenají chybu. false je chyba v parametrech, zatímco 0 je chyba provádění (typicky chyba vrácená OS - out of space apod.). Více detailů první komentář v dokumentaci.
Ten komentář je 8 let starý, chování se mohlo změnit. Připadá mi divné, že by se za 8 let tak zásadní chyba v dokumentaci neopravila. Ale neověřoval jsem to.
Citace od: kvr kvr kdy 30. 06. 2018, 19:05:06
0 jako korektní hodnota je nesmysl, protože vždycky se musí něco zapsat.
Je možné, že nadstavba PHP chování mění, ale standardní POSIXový
write může vrátit i nulu jako normální hodnotu – zapsat se nic nemusí. Při nedostatku místa OS vrátí
-1 a v
errno bude
ENOSPC.
Při zápisu do souboru se bude OS snažit zapsat vše, ale nemusí se mu to podařit. O to je to horší, že to bude skoro vždy fungovat, ale pak se někdy ,,nepochopitelně" zapíše jen část.
Citace od: Filip Jirsák kdy 30. 06. 2018, 19:37:47
Citace od: kvr kvr kdy 30. 06. 2018, 19:05:06
fwrite() return values jsou docela zmatené, obojí false a 0 znamenají chybu. false je chyba v parametrech, zatímco 0 je chyba provádění (typicky chyba vrácená OS - out of space apod.). Více detailů první komentář v dokumentaci.
Ten komentář je 8 let starý, chování se mohlo změnit. Připadá mi divné, že by se za 8 let tak zásadní chyba v dokumentaci neopravila. Ale neověřoval jsem to.
Citace od: kvr kvr kdy 30. 06. 2018, 19:05:06
0 jako korektní hodnota je nesmysl, protože vždycky se musí něco zapsat.
Je možné, že nadstavba PHP chování mění, ale standardní POSIXový write může vrátit i nulu jako normální hodnotu – zapsat se nic nemusí. Při nedostatku místa OS vrátí -1 a v errno bude ENOSPC.
Při zápisu do souboru se bude OS snažit zapsat vše, ale nemusí se mu to podařit. O to je to horší, že to bude skoro vždy fungovat, ale pak se někdy ,,nepochopitelně" zapíše jen část.
Nemůžeš tu podmínku hodit do cyklu. Musíš testovat, zda návratová hodnota je větší jak 0 - jak píše @kvr kvr, pak teprve můžeš zkusit zapsat znova. @andreaw.fean zvolil opačnou strategii, a při neúspěchu prostě končí - což je v pořádku.
Ty posixový funkce nefungují.
fwrite() není wrapper nad posixovým fwrite...
Sečteno a podtrženo problém je v tom, že tvá rada byla úplně špatná.
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
Nemůžeš tu podmínku hodit do cyklu.
Nízkoúrovňové čtení nebo zápis z/do streamnů (soubory, sokety apod.) vždy může zpracovat menší množství dat, než bylo požadováno, proto se musí opakovat v cyklu. To snad vědí programátoři už ve školce.
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
Musíš testovat, zda návratová hodnota je větší jak 0 - jak píše @kvr kvr, pak teprve můžeš zkusit zapsat znova.
U toho nízkoúrovňového zápisu představuje chybu jen záporná hodnota. Je možné, že PHP to má zařízené tak, aby se vždy zapsal alespoň jeden bajt, a nula také znamená chybu, ale pak je vážná chyba v dokumentaci, že to tam není napsané.
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
@andreaw.fean zvolil opačnou strategii, a při neúspěchu prostě končí - což je v pořádku.
V pořádku ovšem není, že končí chybou i v případě úspěšného (částečného) zápisu.
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
Ty posixový funkce nefungují.
Jasně, vy jste expert na všechno a chyba je v Linuxu nebo jakou implementaci POSIXu myslíte. To sedí od někoho, kdo ani neví, jak zkopírovat data z jednoho souboru do druhého.
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
Sečteno a podtrženo problém je v tom, že tvá rada byla úplně špatná.
Že vám programování moc nejde jsem pochopil už v sousední diskusi. Že nezvládnete ani takovéhle základy a nechápete, v čem je problém, to mne překvapilo. Vaše hodnocení mých rad je mi tím pádem úplně jedno.
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:02:02
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
Nemůžeš tu podmínku hodit do cyklu.
Nízkoúrovňové čtení nebo zápis z/do streamnů (soubory, sokety apod.) vždy může zpracovat menší množství dat, než bylo požadováno, proto se musí opakovat v cyklu. To snad vědí programátoři už ve školce.
Děti ve školce znají věc jako zacyklení. Ty ne?
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:02:02
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
Musíš testovat, zda návratová hodnota je větší jak 0 - jak píše @kvr kvr, pak teprve můžeš zkusit zapsat znova.
U toho nízkoúrovňového zápisu představuje chybu jen záporná hodnota. Je možné, že PHP to má zařízené tak, aby se vždy zapsal alespoň jeden bajt, a nula také znamená chybu, ale pak je vážná chyba v dokumentaci, že to tam není napsané.
Takže doporučuješ kód, který v případě, že dojde místo na disku, tak se zacyklí?
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:02:02
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
@andreaw.fean zvolil opačnou strategii, a při neúspěchu prostě končí - což je v pořádku.
V pořádku ovšem není, že končí chybou i v případě úspěšného (částečného) zápisu.
Furt lepší, než co navrhuješ ty.
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:02:02
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
Ty posixový funkce nefungují.
Jasně, vy jste expert na všechno a chyba je v Linuxu nebo jakou implementaci POSIXu myslíte. To sedí od někoho, kdo ani neví, jak zkopírovat data z jednoho souboru do druhého.
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
Sečteno a podtrženo problém je v tom, že tvá rada byla úplně špatná.
Že vám programování moc nejde jsem pochopil už v sousední diskusi. Že nezvládnete ani takovéhle základy a nechápete, v čem je problém, to mne překvapilo. Vaše hodnocení mých rad je mi tím pádem úplně jedno.
Když to říkáš.
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
Nemůžeš tu podmínku hodit do cyklu. Musíš testovat, zda návratová hodnota je větší jak 0 - jak píše @kvr kvr, pak teprve můžeš zkusit zapsat znova
Pokus o zápis nemusí zapsat všechna data, takže bežné a správné řešení je v cyklu zapisovat to, co zbývá zapsat, dokud není zapsáno všechno a pokud při zápisu aktuálního "kousku" dojde k chybě, tak cyklus přerušit. Co je na tom k nepochopení?
Mimo špatného "algoritmu", je $handle globalní proměnná, která v té funkci write není vidět, takže by to nemělo fungovat vůbec a případně ještě řvát.
Jinak je v PHP taky funkce file_put_contents, která tě takového šaškování zbaví.
Citace od: . kdy 30. 06. 2018, 21:14:07
Citace od: BoneFlute kdy 30. 06. 2018, 20:31:16
Nemůžeš tu podmínku hodit do cyklu. Musíš testovat, zda návratová hodnota je větší jak 0 - jak píše @kvr kvr, pak teprve můžeš zkusit zapsat znova
Pokus o zápis nemusí zapsat všechna data, takže bežné a správné řešení je v cyklu zapisovat to, co zbývá zapsat, dokud není zapsáno všechno a pokud při zápisu aktuálního "kousku" dojde k chybě, tak cyklus přerušit. Co je na tom k nepochopení?
Nekonečný cyklus.
...dojde k chybě, tak cyklus přerušit.
Citace od: . kdy 30. 06. 2018, 21:18:41
Mimo špatného "algoritmu", je $handle globalní proměnná, která v té funkci write není vidět, takže by to nemělo fungovat vůbec a případně ještě řvát.
Jinak je v PHP taky funkce file_put_contents, která tě takového šaškování zbaví.
To jsem to jen špatně přepsal.
file_put_contents se mi nehodí, protože pracuji s tím handle. A pokud je to tak jak píše BoneFlute, že stejně jen vypíše chybovku na výstup, tak se mi to nehodí už vůbec a nebudu to tedy přepisovat.
Citace od: BoneFlute kdy 30. 06. 2018, 21:12:27
Děti ve školce znají věc jako zacyklení. Ty ne?
K zacyklení dojde jedině tehdy, pokud v cyklu není nikdy splněna podmínka, která by cyklus ukončila.
Teda ,,programátor", který se bojí používat cykly, protože neumí napsat ukončovací podmínku, to je fakt něco.
Citace od: BoneFlute kdy 30. 06. 2018, 21:12:27
Takže doporučuješ kód, který v případě, že dojde místo na disku, tak se zacyklí?
Z mých komentářů nic takového neplyne. Pokud funkce
fwrite() v PHP je implementovaná tak, jak je popsaná v dokumentaci, vrátí v případě zaplnění disku
FALSE. I kdyby fungovala jinak a v případě chyby mohla vracet i nulu, pořád se akorát ten test na úspěch funkce upraví tak, zda vrátila hodnotu větší než nula.
Citace od: BoneFlute kdy 30. 06. 2018, 21:12:27
Furt lepší, než co navrhuješ ty.
Ne, kód, který občas náhodně nefunguje, není lepší.
Citace od: . kdy 30. 06. 2018, 21:25:30
...dojde k chybě, tak cyklus přerušit.
Pokud je plnej disk, tak to
fwrite() neeviduje jako chybu.
A jako vůbec, von se tu dotyčný táže, jak zjistit že je nějaká chyba, a vy mu radíte, že má blbě algoritmus, kterej nakonec opravíte do ještě horšího stavu. To myslíte vážně?
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:26:48
Citace od: BoneFlute kdy 30. 06. 2018, 21:12:27
Děti ve školce znají věc jako zacyklení. Ty ne?
K zacyklení dojde jedině tehdy, pokud v cyklu není nikdy splněna podmínka, která by cyklus ukončila.
Teda ,,programátor", který se bojí používat cykly, protože neumí napsat ukončovací podmínku, to je fakt něco.
To jsi jako sebral kde?
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:26:48
Citace od: BoneFlute kdy 30. 06. 2018, 21:12:27
Takže doporučuješ kód, který v případě, že dojde místo na disku, tak se zacyklí?
Z mých komentářů nic takového neplyne. Pokud funkce fwrite() v PHP je implementovaná tak, jak je popsaná v dokumentaci, vrátí v případě zaplnění disku FALSE. I kdyby fungovala jinak a v případě chyby mohla vracet i nulu, pořád se akorát ten test na úspěch funkce upraví tak, zda vrátila hodnotu větší než nula.
No konečně to chápeš. Že se vůbec pouštíš do něčeho, čemu nerozumíš.
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:26:48
Citace od: BoneFlute kdy 30. 06. 2018, 21:12:27
Furt lepší, než co navrhuješ ty.
Ne, kód, který občas náhodně nefunguje, není lepší.
Beru na vědomí. Zacyklení je lepší.
Citace od: BoneFlute kdy 30. 06. 2018, 21:30:45
Pokud je plnej disk, tak to fwrite() neeviduje jako chybu.
Takže pokračuje v zápisu za konec disku? Nebo co přesně
fwrite() vrátí, když je plnýdisk?
Citace od: BoneFlute kdy 30. 06. 2018, 21:30:45
A jako vůbec, von se tu dotyčný táže, jak zjistit že je nějaká chyba, a vy mu radíte, že má blbě algoritmus, kterej nakonec opravíte do ještě horšího stavu. To myslíte vážně?
Ne, ten algoritmus byl špatně a tvrdil, že došlo k chybě, i když to není pravda. Když se bude volat
fwrite() v cyklu a testovat, zda se něco zapsalo nebo došlo k chybě, bude to fungovat správně.
Vy už byste se k tomu měl přestat vyjadřovat, když je pro vás nepochopitelný i obyčejný cyklus, nemáte k tomu co říci.
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:35:04
Citace od: BoneFlute kdy 30. 06. 2018, 21:30:45
Pokud je plnej disk, tak to fwrite() neeviduje jako chybu.
Takže pokračuje v zápisu za konec disku? Nebo co přesně fwrite() vrátí, když je plnýdisk?
[facepalm]
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:35:04
Citace od: BoneFlute kdy 30. 06. 2018, 21:30:45
A jako vůbec, von se tu dotyčný táže, jak zjistit že je nějaká chyba, a vy mu radíte, že má blbě algoritmus, kterej nakonec opravíte do ještě horšího stavu. To myslíte vážně?
Ne, ten algoritmus byl špatně a tvrdil, že došlo k chybě, i když to není pravda. Když se bude volat fwrite() v cyklu a testovat, zda se něco zapsalo nebo došlo k chybě, bude to fungovat správně.
Vy už byste se k tomu měl přestat vyjadřovat, když je pro vás nepochopitelný i obyčejný cyklus, nemáte k tomu co říci.
Fakt žeru tyhle lidi s bujnou fantazií.
Citace od: Filip Jirsák kdy 30. 06. 2018, 19:37:47
Citace od: kvr kvr kdy 30. 06. 2018, 19:05:06
0 jako korektní hodnota je nesmysl, protože vždycky se musí něco zapsat.
Je možné, že nadstavba PHP chování mění, ale standardní POSIXový write může vrátit i nulu jako normální hodnotu – zapsat se nic nemusí. Při nedostatku místa OS vrátí -1 a v errno bude ENOSPC.
Při zápisu do souboru se bude OS snažit zapsat vše, ale nemusí se mu to podařit. O to je to horší, že to bude skoro vždy fungovat, ale pak se někdy ,,nepochopitelně" zapíše jen část.
POSIXový
write() může vrátit
0 v případě, že velikost zapisovaných dat byla
0. Pokud OS nemůže nic zapsat v případě neprázdných argumentů, má vrátit chybu
EAGAIN, aby program mohl počkat přes
select() (nebo podobnou funkci) na to, až zápis bude možný. Kdyby vracel
0, tak by to skončilo bez kontroly v busy loop.
To, že PHP si překládá chybu na
0, je jiná věc (nejspíš, aby se dalo snadno testovat v podmínce), ale v zásadě to na věci nic nemění - zapisovat prázdné data je stejně nesmysl.
Citace od: kvr kvr kdy 30. 06. 2018, 21:44:06
POSIXový write() může vrátit 0 v případě, že velikost zapisovaných dat byla 0. Pokud OS nemůže nic zapsat v případě neprázdných argumentů, má vrátit chybu EAGAIN, aby program mohl počkat přes select() (nebo podobnou funkci) na to, až zápis bude možný. Kdyby vracel 0, tak by to skončilo bez kontroly v busy loop.
POSIXový
write může vrátit 0 i v případě, že je požadován zápis nenulového počtu bajtů. A znamená to jen, že bylo zapsáno nula bajtů – není to chyba.
Citace
On success, the number of bytes written is returned (zero indicates nothing was written). It is not an error if this number is smaller than the number of bytes requested; this may happen for example because the disk device was filled. See also NOTES.
On error, -1 is returned, and errno is set appropriately.
Vrácení 0 by měl být výjimečný případ, ale počítá se mezi úspěšné výsledky volání. Nekonečnému cyklu zabrání to, že takový stav by byl jen dočasný, a v některém z příštích cyklů by write mělo něco zapsat nebo skončit chybou.
Citace od: BoneFlute kdy 30. 06. 2018, 21:30:45
Pokud je plnej disk, tak to fwrite() neeviduje jako chybu.
Tak vrátí nulu, kterou vyhodnotíš jako chybu! Jo, ten příklad v dokumentaci je na hovno.
Citace od: BoneFlute kdy 30. 06. 2018, 21:30:45
A jako vůbec, von se tu dotyčný táže, jak zjistit že je nějaká chyba, a vy mu radíte, že má blbě algoritmus, kterej nakonec opravíte do ještě horšího stavu. To myslíte vážně?
Protože v první řadě to má tak blbě, že to co vidí jako chybu, nemusí být chyba.
Když jsi tak vykulenej z trviálních věcí, tak se k tomu prostě nevyjadřuj, protože o tom víš kulový a jen se ztrapňuješ.
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:58:53
Vrácení 0 by měl být výjimečný případ, ale počítá se mezi úspěšné výsledky volání.
fwrite v PHP při záporné návratovce write vrací nulu. Šlo by si s tím hrát, ale prakticky nemá smysl to hned vyhodnodit jako konečnou chybu.
Citace od: . kdy 30. 06. 2018, 22:08:41
vyhodnodit jako konečnou chybu.
nevyhodnotit
Citace od: kvr kvr kdy 30. 06. 2018, 21:44:06
Citace od: Filip Jirsák kdy 30. 06. 2018, 19:37:47
Citace od: kvr kvr kdy 30. 06. 2018, 19:05:06
0 jako korektní hodnota je nesmysl, protože vždycky se musí něco zapsat.
Je možné, že nadstavba PHP chování mění, ale standardní POSIXový write může vrátit i nulu jako normální hodnotu – zapsat se nic nemusí. Při nedostatku místa OS vrátí -1 a v errno bude ENOSPC.
Při zápisu do souboru se bude OS snažit zapsat vše, ale nemusí se mu to podařit. O to je to horší, že to bude skoro vždy fungovat, ale pak se někdy ,,nepochopitelně" zapíše jen část.
POSIXový write() může vrátit 0 v případě, že velikost zapisovaných dat byla 0. Pokud OS nemůže nic zapsat v případě neprázdných argumentů, má vrátit chybu EAGAIN, aby program mohl počkat přes select() (nebo podobnou funkci) na to, až zápis bude možný. Kdyby vracel 0, tak by to skončilo bez kontroly v busy loop.
To, že PHP si překládá chybu na 0, je jiná věc (nejspíš, aby se dalo snadno testovat v podmínce), ale v zásadě to na věci nic nemění - zapisovat prázdné data je stejně nesmysl.
Jen doplním - Pokud zapíšu alespoň jeden bajt, tak je to v pořádku a můžu zkusit znova. Ale pokud se nepovede zápis ani jednoho, není důvod k optimismu si myslet že v příštím kole to bude lepší. Takže dávám tak dva tři pokusy maximálně.
Citace od: . kdy 30. 06. 2018, 22:08:41
fwrite v PHP při záporné návratovce write vrací nulu. Šlo by si s tím hrát, ale prakticky nemá smysl to hned vyhodnodit jako konečnou chybu.
Díky, konečně někdo napsal, jak to je, ne jen nějaké dohady.
Předpokládám, že to byl překlep, a že jste chtěl napsat, že 0 jako návratová hodnota PHP fwrite() by měla být hned vyhodnocena jako chyba.
Každopádně mi to teda připadá jako dost zásadní chyba v dokumentaci PHP. Jednoduché porovnání
fwrite() == FALSE sice bude fungovat díky automatickému přetypování, ale třeba už to, co je tam uvedené jako příklad, kvůli
=== fungovat nebude.
Citace od: kvr kvr kdy 30. 06. 2018, 19:05:06
fwrite() return values jsou docela zmatené, obojí false a 0 znamenají chybu. false je chyba v parametrech, zatímco 0 je chyba provádění (typicky chyba vrácená OS - out of space apod.). Více detailů první komentář v dokumentaci. 0 jako korektní hodnota je nesmysl, protože vždycky se musí něco zapsat. V případě, že by došlo k blokování a je nastaven NONBLOCK, vrací se chyba EAGAIN. Předpokládám, že v rámci "kompatibility" je dobré ošetřít false a 0 stejně :-)
V tom kódu je třeba zpracovat error_get_last na místě, kde se vyhazuje výjimka, tam se vrátí asi finální chyba. Kromě toho jsou tam k opravě následující:
- loop while writte != 0 místo jednoho if (i když technicky vzato běžné OS zapíšou všechno co jde, pokud jde o normální soubor, jinak je to u pipe, socket apod)/li]
- nevím, jak je to u php s konverzí znakových sad a DOS/UNIX konverzí, soubor musí být v každém případě otevřen jako binary.
- ... a podobně jako v předchozím - viz poslední argument, který vypíná magic chování, které rovněž může ovlivnit délku zápisu.
Tak v mém případě se jedná o normální soubor, takže předpokládám, že netřeba to prožívat.
A já mám právě problém v tom, že mi to žádnou chybu nevrátí. To je to co řeším.[/list]
Citace od: andreaw.fean kdy 30. 06. 2018, 22:27:16
A já mám právě problém v tom, že mi to žádnou chybu nevrátí. To je to co řeším.
Že došlo k chybě zjistíte tak, že otestujete výsledek volání
fwrite(), zda je to
FALSE nebo
0. Když funkce vrátí hodnotu větší než nula, opakujete její volání v cyklu a zapíšete další část.
Citace od: Filip Jirsák kdy 30. 06. 2018, 22:36:13
Citace od: andreaw.fean kdy 30. 06. 2018, 22:27:16
A já mám právě problém v tom, že mi to žádnou chybu nevrátí. To je to co řeším.
Že došlo k chybě zjistíte tak, že otestujete výsledek volání fwrite(), zda je to FALSE nebo 0. Když funkce vrátí hodnotu větší než nula, opakujete její volání v cyklu a zapíšete další část.
A jak zjistím, jaká je to chyba?
Citace od: andreaw.fean kdy 30. 06. 2018, 22:39:28
A jak zjistím, jaká je to chyba?
Zkusil bych
error_get_last() nebo
posix_get_last_error().
Citace od: Filip Jirsák kdy 30. 06. 2018, 22:48:23
Citace od: andreaw.fean kdy 30. 06. 2018, 22:39:28
A jak zjistím, jaká je to chyba?
Zkusil bych error_get_last() nebo posix_get_last_error().
To jsem zkoušel. To mi vrací success.
Citace od: andreaw.fean kdy 30. 06. 2018, 22:51:35
To jsem zkoušel. To mi vrací success.
Obě dvě? Voláte je až po té, co vám
fwrite() vrátí
false nebo
0? Bylo by lepší, kdybyste sem dal kód, který zkoušíte.
Citace od: Filip Jirsák kdy 30. 06. 2018, 22:48:23
Citace od: andreaw.fean kdy 30. 06. 2018, 22:39:28
A jak zjistím, jaká je to chyba?
Zkusil bych error_get_last() nebo posix_get_last_error().
Už ti tady asi 5x psali, že to nefunguje. Vyměň si tampón. ;D ::)
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:58:53
POSIXový write může vrátit 0 i v případě, že je požadován zápis nenulového počtu bajtů. A znamená to jen, že bylo zapsáno nula bajtů – není to chyba.
A ve kterém případě by se to mělo stát? POSIX také specifikuje, za jakých okolností je možné zapsat méně než požadovaný počet bajtů, a všechny při nezapsaní ani jednoho bajtu vrací -1 a nastavují
errno.
Citace od: Filip Jirsák kdy 30. 06. 2018, 22:56:16
Citace od: andreaw.fean kdy 30. 06. 2018, 22:51:35
To jsem zkoušel. To mi vrací success.
Obě dvě? Voláte je až po té, co vám fwrite() vrátí false nebo 0? Bylo by lepší, kdybyste sem dal kód, který zkoušíte.
Máte ho hned v mém prvním příspěvku.
Citace od: Sten kdy 30. 06. 2018, 22:59:20
POSIX také specifikuje, za jakých okolností je možné zapsat méně než požadovaný počet bajtů
Kde to specifikuje?
Citace od: andreaw.fean kdy 30. 06. 2018, 23:01:00
Máte ho hned v mém prvním příspěvku.
Ano, ale ten kód je špatně, tam netestujete, zda došlo k chybě. A nevolá se tam ani
error_get_last() nebo
posix_get_last_error().
Radši vám ten opravený kód napíšu, jinak to bude na dlouho...
$tmpdir = sys_get_temp_dir();
$tmpname = tempnam($tmpdir, 'app-');
$handle = fopen($tmpname, 'a');
// velikost $s je obvykle 2096 bajtů
function write($handle, $s)
{
$len = strlen($s);
while ( $len > 0 )
{
$wrote = fwrite($handle, $s);
if ( $wrote === false || $wrote == 0 )
{
var_dump(error_get_last());
var_dump(posix_get_last_error());
throw new RuntimeException('Zápis do souboru skončil chybou.');
}
$s = substr($s, $wrote)
$len = strlen($s);
}
}
Citace od: Filip Jirsák kdy 30. 06. 2018, 23:26:03
Radši vám ten opravený kód napíšu, jinak to bude na dlouho...
Výsledek je stejný.
:)
;) ;)
:D :D :D
;D ;D ;D ;D
:P :P :P
:-* :-*
8)
Kouknul jsem do zdrojáku PHP a fwrite nakonec vede na
int bytes_written = write(data->fd, buf, count);
if (bytes_written < 0) return 0;
return (size_t) bytes_written;
tj. na https://linux.die.net/man/2/write (https://linux.die.net/man/2/write)
Když se koukneš na https://linux.die.net/man/3/explain_write (https://linux.die.net/man/3/explain_write) tak bys asi rád znal hodnotu errno (errno.h), což by právě měla dělat posix_get_last_error() , jestli ta ale nevrací chybový kód, tak možná nezbyde než se smířit s "těžký život ve světě PHP". ;)
Ještě bych dodal, že errno mění kdejaká funkce z libc a i PHP samotné, takže hodnotu vrácenou z posix_get_last_error() bych si pro jistotu zapamatoval ihned po volání fwrite().
Citace od: Filip Jirsák kdy 30. 06. 2018, 21:58:53
POSIXový write může vrátit 0 i v případě, že je požadován zápis nenulového počtu bajtů. A znamená to jen, že bylo zapsáno nula bajtů – není to chyba.
Citace
On success, the number of bytes written is returned (zero indicates nothing was written). It is not an error if this number is smaller than the number of bytes requested; this may happen for example because the disk device was filled. See also NOTES.
On error, -1 is returned, and errno is set appropriately.
Vrácení 0 by měl být výjimečný případ, ale počítá se mezi úspěšné výsledky volání. Nekonečnému cyklu zabrání to, že takový stav by byl jen dočasný, a v některém z příštích cyklů by write mělo něco zapsat nebo skončit chybou.
Zapsání nula bytes chyba je a OS by měl vrátit důvod, proč k tomu došlo. Podobné je to u interrupted by signal - pokud se aspoň jeden byte zapsal, vrací délku zapsaných dat, v opačném případě vrátí chybu EINTR. Návratová hodnota "nic se nepovedlo, ale neřeknu proč" není hodna implementace slušného OS. Jak jsem psal výše, něco takového by vedlo k busy loop a nesmyslnému aplikačnímu kódu.
write() může skončit úspěšně i v případě předchozí chyby, proto tam ty chybové kódy jsou, aby se aplikace mohla rozhodnout, co má zkusit znovu a jak (EAGAIN, EINTR, ENOSPC).
Na druhé straně je třeba říct, že dokumentace (citace je z Linux man page, nikoliv POSIX specifikace) by mohla být napsaná jasněji, že jde o speciální případ prázdných dat (které můžou mít u speciálních file descriptors zvláštní význam - například EOF).
Citace od: andreaw.fean kdy 30. 06. 2018, 23:36:16
Výsledek je stejný.
V tom případě jste nezkoušel tu variantu s
posix_get_last_error(), protože ta funkce vrací číslo, takže nemůže být výsledek stejný, jako když zavoláte variantu s funkcí
error_get_last(), která vrací pole.
Pokud by vám i
posix_get_last_error() vracela, že k žádné chybě nedošlo, máte smůlu, protože PHP mezitím zavolalo nějakou jinou POSIXovou funkci, která výsledek volání
write() překryla.
Citace od: kvr kvr kdy 01. 07. 2018, 05:30:18
Zapsání nula bytes chyba je
To je napsané kde?
Když se podíváte na ty příklady v manuálové stránce
explain_write, neúspěšný zápise se tam rozpoznává tak, že návratový kód je menší než nula. Myslíte, že to v té manuálové stránce je špatně?
Citace od: kvr kvr kdy 01. 07. 2018, 05:30:18
Jak jsem psal výše, něco takového by vedlo k busy loop a nesmyslnému aplikačnímu kódu.
Ne nutně. Nikdo netvrdí, že když
write() vrátí nulu, musí ji vrátit i v příštím cyklu – v příštím cyklu už může být zápis úspěšnější a zapíše alespoň něco, nebo už se alespoň bude vědět příčina chyby a
write() vrátí chybu plus třeba
EAGAIN.
write() může skončit úspěšně i v případě předchozí chyby, proto tam ty chybové kódy jsou, aby se aplikace mohla rozhodnout, co má zkusit znovu a jak (EAGAIN, EINTR, ENOSPC).
Citace od: kvr kvr kdy 01. 07. 2018, 05:30:18
Na druhé straně je třeba říct, že dokumentace (citace je z Linux man page, nikoliv POSIX specifikace) by mohla být napsaná jasněji
V té manuálové stránce je jasně napsáno, že i při úspěšném volání se může vrátit nula. Ale mohlo by tam být explicitně napsáno, že se pak má volání opakovat, stejně jako pro jiné případy,když nebylo zapsáno vše. Dokumentace k jiným knihovnám tu nulu často neřeší vůbec.
V POSIX specifikaci jsem také nenašel nic o tom, že by nula byla chyba.
........... (https://www.youtube.com/watch?v=j4UpBVN-qE8&feature=youtu.be&t=10s)
;D ;D ;D ;D ;D
:D :D :D :D :D
:P :P :P :P :P
Citace od: Filip Jirsák kdy 01. 07. 2018, 07:43:01
Citace od: andreaw.fean kdy 30. 06. 2018, 23:36:16
Výsledek je stejný.
V tom případě jste nezkoušel tu variantu s posix_get_last_error()...
Jestli on tazatel nemyslí, že výsledek je stejný, tedy i s touto implementací mu došlo na disku místo ;-)
Citace od: Ladislav Michl kdy 02. 07. 2018, 12:55:29
Citace od: Filip Jirsák kdy 01. 07. 2018, 07:43:01
Citace od: andreaw.fean kdy 30. 06. 2018, 23:36:16
Výsledek je stejný.
V tom případě jste nezkoušel tu variantu s posix_get_last_error()...
Jestli on tazatel nemyslí, že výsledek je stejný, tedy i s touto implementací mu došlo na disku místo ;-)
Tak já myslím, že se od Filipa Jirsáka kromě siláckých řečí nic zajímavého nedozvím. Všechno mu to musím vysvětlovat po lopatě a nic z toho.
Tak jsem tam zatím jen upravil hlášku, kontroluju místo na disku pomocí disk_free_space(). Nic lepšího asi nevymyslíme.
Kdyby někoho ještě napadl nějaký způsob, třeba nějaká zahrabaná globální proměnná, nebo tak něco.
Citace od: andreaw.fean kdy 02. 07. 2018, 13:26:46
Tak já myslím, že se od Filipa Jirsáka kromě siláckých řečí nic zajímavého nedozvím. Všechno mu to musím vysvětlovat po lopatě a nic z toho.
Dozvěděl jste se, kde máte v kódu chybu, proč je to chyba a jak jí opravit. Vysvětlovat jste nic nemusel, naopak jste na mnohé dotazy odpovídal až na několikátý pokus, případně vůbec. Vaše ,,výsledek stejný" má k vyčerpávajícímu popisu chyby opravdu velmi daleko – i mnozí uživatelé chápou, že musí napsat, co přesně dělali a jaký byl výsledek. Pro programátora by to měla být úplná samozřejmost.
Já teda obdivuju trpělivost pana Jirsáka s tazatelem a několika individui jako Lol Phirae a BoneFlute. Já osobně bych se už na jakoukoliv pomoc vy..., protože tazatel není schopen přečíst a porozumět psanému textu, nápodobně BoneFlute, který nepřinese jediný faktický argument, který by dokázal, že pan Jirsák nemá pravdu a jen tu sprostě uráží. Pánové, fakt nechápu smysl Vašeho počínání, tohle fórum má sloužit k výměně zkušeností a Vy informace a rady ignorujete.
Citace od: andreaw.fean kdy 02. 07. 2018, 13:26:46
Kdyby někoho ještě napadl nějaký způsob, třeba nějaká zahrabaná globální proměnná, nebo tak něco.
Zahrabaná globální proměnná se jmenuje errno, kód tady máte, někteří si dokonce dali práci a našli, jak je implementované fwrite() a Vy se omezíte na "výsledek je stejný". To mi nepřijde příliš motivující. Obtěžovalo by Vás napsat, co vrací fwrite() poté, co dojde místo a co obsahuje errno?
To je zas diskuse. Připomíná mi to jistou scénu ze Ztráty třídní knihy... Jeden se zeptá a pak nadává lidem, co se mu snaží poradit. Druhý sofistikovaně teoretizuje z manuálu, zdrojáku, ale že by ho napadlo si svoji radu prakticky vyzkoušet, to ne. Udělal jsem to tedy za vás. Kód:
<?php
echo "PHP VERSION: ".phpversion()."\n";
$FILE_NAME = '/my_small_partition/test';
$s = '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789';
$len = strlen($s);
$file = fopen($FILE_NAME , 'w');
for(;;) {
$wrote = fwrite($file, $s);
if ($wrote <= 0) {
$stored_posix_get_last_error = posix_get_last_error();
$stored_error_get_last = error_get_last();
$stored_errno = $errno;
echo "wrote: ";
var_dump($wrote);
echo "errno: ";
var_dump($stored_errno);
echo "posix_get_last_error: ";
var_dump($stored_posix_get_last_error);
echo "error_get_last: ";
var_dump($stored_error_get_last);
break;
}
}
fclose($file);
unlink($FILE_NAME);
?>
Výsledek:
PHP VERSION: 7.0.18-0ubuntu0.16.04.1
PHP Notice: Undefined variable: errno in test.php on line 15
wrote: int(0)
errno: NULL
posix_get_last_error: int(0)
error_get_last: NULL
(Padá to opravdu na zaplnění disku. Chyby si nejdřív uložím do proměnných aby nedošlo k volání knihovny při echo.)
No a včil mudrujte.
Já myslim že tam máš málo cyklů...
;D
;D ;D
;D ;D ;D
;D ;D
;D
Citace od: L. kdy 02. 07. 2018, 15:38:44
Druhý sofistikovaně teoretizuje z manuálu, zdrojáku, ale že by ho napadlo si svoji radu prakticky vyzkoušet, to ne. Udělal jsem to tedy za vás.
Udělal jste to za tazatele. Když má spoustu blbých keců a ani neumí napsat, co vyzkoušel, nemíním si kvůli němu ještě instalovat PHP a něco zkoušet.
Citace od: Filip Jirsák kdy 02. 07. 2018, 16:55:02
Udělal jste to za tazatele. Když má spoustu blbých keců a ani neumí napsat, co vyzkoušel, nemíním si kvůli němu ještě instalovat PHP a něco zkoušet.
Být tebou Jirsák, tak mlčím a šoupu nohama, protože se právě ukázalo, že jsi tu celou dobu velkohubě radil hovadiny.
Citace od: L. kdy 02. 07. 2018, 17:12:46
Být tebou Jirsák, tak mlčím a šoupu nohama, protože se právě ukázalo, že jsi tu celou dobu velkohubě radil hovadiny.
Mohl byste být přesnější, co z toho, co jsem radil, byla hovadina? Tazatel měl špatně napsaný zápis do souboru, to jsem mu poradil, jak opravit – ten původní kód by fungoval jedině tehdy, kdyby se jedním voláním
fwrite() podařilo zapsat všechna data bez chyby. Ve všech ostatních případech by ten kód dělal nesmysly. Dále jsem tazateli poradil, že až si kód opraví tak, aby opravdu detekoval selhání
fwrite(), ať vyzkouší, zda přesnou chybu nezjistí z funkcí
posix_get_last_error() nebo
error_get_last(). Že to doteď tazatel nevyzkoušel nebo nenapsal výsledek toho pokusu, za to nemůžu. A povinnost zkoušet to za tazatele fakt nemám, už tak dostal mnohem lepší rady, než by si svým chováním zasloužil.
Citace od: Filip Jirsák kdy 02. 07. 2018, 17:44:38
Mohl byste být přesnější, co z toho, co jsem radil, byla hovadina?
Možná bude jednodušší popsat, co z "rad" hovadina nebyla... To si ušetříme hodně práce. ;D
Citace od: Filip Jirsák kdy 02. 07. 2018, 17:44:38
Tazatel měl špatně napsaný zápis do souboru, to jsem mu poradil, jak opravit – ten původní kód by fungoval jedině tehdy, kdyby se jedním voláním fwrite() podařilo zapsat všechna data bez chyby. Ve všech ostatních případech by ten kód dělal nesmysly.
Na což se neptal, nesouviselo to s tím na co se ptal, a ani to nijak nepomohlo s jeho problémem. Rada na nic.
Citace od: Filip Jirsák kdy 02. 07. 2018, 17:44:38
Dále jsem tazateli poradil, že až si kód opraví tak, aby opravdu detekoval selhání fwrite(), ať vyzkouší, zda přesnou chybu nezjistí z funkcí posix_get_last_error() nebo error_get_last(). Že to doteď tazatel nevyzkoušel nebo nenapsal výsledek toho pokusu, za to nemůžu.
Což udělal, a podle jeho reakcí soudě vyzkoušel. Že tvrdíš, že to nevyzkoušel, že tvrdíš, že to nenapsal, přestože to má uvedené hned v prvním příspěvku - to už je tvůj problém. A tvá drzost.
Citace od: Filip Jirsák kdy 02. 07. 2018, 17:44:38
A povinnost zkoušet to za tazatele fakt nemám, už tak dostal mnohem lepší rady, než by si svým chováním zasloužil.
Jaký chování? Že není spokojený s radou, která prostě nefunguje? Když by se všichni chovali jako on, tak by bylo krásně na foru.
Víš, problém jsi tu ty, ne ostatní.
Citace od: BoneFlute kdy 02. 07. 2018, 21:33:41
Na což se neptal, nesouviselo to s tím na co se ptal, a ani to nijak nepomohlo s jeho problémem. Rada na nic.
Vy jste stále ještě nepochopil, jaký problém se tu řeší. Takže vaše názory na to, co pomohlo a co ne, jsou k ničemu.
Citace od: BoneFlute kdy 02. 07. 2018, 21:33:41
Což udělal, a podle jeho reakcí soudě vyzkoušel. Že tvrdíš, že to nevyzkoušel, že tvrdíš, že to nenapsal, přestože to má uvedené hned v prvním příspěvku - to už je tvůj problém. A tvá drzost.
Kdyby napsal výsledky toho pokusu, napsal by
fwrite() zaplnilo disk a vrátilo v poslední smyčce
0 a
posix_get_last_error() také
0, v druhém pokusu vrátilo po zaplnění disku
error_get_last() hodnotu
NULL. To by to ovšem nejdřív musel vyzkoušet, že... Kód v prvním příspěvku by mohl hlásit chybu zaplnění disku jedině v případě, že by disk byl plný už před začátkem zápisu. Kdyby se disk zaplnil už voláním té funkce
fwrite(), selhalo by už druhé volání
fwrite(), a tam žádný výpis chybového kódu není. Programátor to musí vidět na první pohled. Takže vaše snaha najít nějaký programovací jazyk, kde byste vůbec nemusel programovat, protože vám to nejde, je pochopitelná. A to ještě pořád nejsem drzý.
Citace od: BoneFlute kdy 02. 07. 2018, 21:33:41
Jaký chování? Že není spokojený s radou, která prostě nefunguje? Když by se všichni chovali jako on, tak by bylo krásně na foru.
Jestli ta rada funguje nebo nefunguje by mohl zjistit teprve tehdy, až by ten kód opravil. Což se nestalo. Pokud nepochopil, v čem je problém, mohl se slušně zeptat. Což se také nestalo.
Citace od: BoneFlute kdy 02. 07. 2018, 21:33:41
Víš, problém jsi tu ty, ne ostatní.
Můj problém je, že se tu vybavuju s někým, kdo si o sobě myslí, že je mistr světa, a přitom si ani neumí zavázat tkaničky. Pozdravujte Jéčko na ignorlistu.
Citace od: L. kdy 02. 07. 2018, 15:38:44
No a včil mudrujte.
No tak hurá, aspoň někdo to zkusil! Odtud:
https://github.com/php/php-src/blob/master/ext/standard/file.c#L1189
a odtud:
https://github.com/php/php-src/blob/master/main/streams/streams.c#L1189
#define php_stream_write(stream, buf, count) _php_stream_write(stream, (buf), (count))
to vypadá, že se pracuje s FILE, nikoliv s fd.
Byl byste ochotný udělat ještě jeden pokus, kdy se soubor otevře pomocí dio_open() a odtud se teprve získá stream?
Citace od: Ladislav Michl kdy 02. 07. 2018, 22:39:22
Citace od: L. kdy 02. 07. 2018, 15:38:44
No a včil mudrujte.
No tak hurá, aspoň někdo to zkusil! Odtud:
https://github.com/php/php-src/blob/master/ext/standard/file.c#L1189
a odtud:
https://github.com/php/php-src/blob/master/main/streams/streams.c#L1189
#define php_stream_write(stream, buf, count) _php_stream_write(stream, (buf), (count))
to vypadá, že se pracuje s FILE, nikoliv s fd.
Byl byste ochotný udělat ještě jeden pokus, kdy se soubor otevře pomocí dio_open() a odtud se teprve získá stream?
Určitě!
Ale bohužel. Mám PHP verzi 5.6, tohle je pro < 5.1 (dle dokumentace). Pro jistotu jsem to i tak zkusil, člověk nikdy neví, ale už tam není no.
(Degradovat na 5.1 se mi nechce, a i kdyby to pomohlo, tak to stejně nebudu moct použít.)
Citace od: Filip Jirsák kdy 02. 07. 2018, 22:23:51
Citace od: BoneFlute kdy 02. 07. 2018, 21:33:41
Na což se neptal, nesouviselo to s tím na co se ptal, a ani to nijak nepomohlo s jeho problémem. Rada na nic.
Vy jste stále ještě nepochopil, jaký problém se tu řeší. Takže vaše názory na to, co pomohlo a co ne, jsou k ničemu.
Tak jeho rada (https://forum.root.cz/index.php?topic=18906.msg272378#msg272378) sice nebyla moc povzbudivá, ale alespoň byla k věci a normální.
Citace od: andreaw.fean kdy 02. 07. 2018, 23:04:40
Mám PHP verzi 5.6, tohle je pro < 5.1 (dle dokumentace). Pro jistotu jsem to i tak zkusil, člověk nikdy neví, ale už tam není no.
(Degradovat na 5.1 se mi nechce, a i kdyby to pomohlo, tak to stejně nebudu moct použít.)
Pardon. Přiznám se, že jsem nevšiml, že tahle část je obsolete. Teoreticky by mohlo jít použit eio_open() z https://pecl.php.net/package/eio a protože se tím krmí libev, předpokládám, že vrací file descriptor. Bez záruky, do kódu jsem se nedíval.
Citace od: Ladislav Michl kdy 02. 07. 2018, 23:30:40
Pardon. Přiznám se, že jsem nevšiml, že tahle část je obsolete. Teoreticky by mohlo jít použit eio_open() z https://pecl.php.net/package/eio a protože se tím krmí libev, předpokládám, že vrací file descriptor. Bez záruky, do kódu jsem se nedíval.
Tak teda to EIO jsem zkusil. Funguje to hezky. Při vyčerpání místa to vrátí chybu, a tu lze přečíst pomocí eio_get_last_error(). Takhle by se mi to líbilo u to fwrite(), škoda, že to neumí no.
Citace od: Filip Jirsák kdy 02. 07. 2018, 17:44:38
Mohl byste být přesnější, co z toho, co jsem radil, byla hovadina?
Prakticky všechno. Nejdřív jsi se tu točil na nějakém částečném zápisu, což ale problém vůbec nebyl. Ono totiž PHP, jak se zdá, tu smyčku dělá už interně ve funkci, kterou volá ten
fwrite(): https://github.com/php/php-src/blob/master/main/streams/streams.c#L1080 (https://github.com/php/php-src/blob/master/main/streams/streams.c#L1080)
Dál jsi psal:
Citace od: Filip Jirsák kdy 01. 07. 2018, 07:43:01
Pokud by vám i posix_get_last_error() vracela, že k žádné chybě nedošlo, máte smůlu, protože PHP mezitím zavolalo nějakou jinou POSIXovou funkci, která výsledek volání write() překryla.
Kdybys měl alespoň trochu ánunk o tom, o čem píšeš, tak by ti došlo, že
posix_get_last_error() je z POSIX modulu, tedy funguje jen pro jeho funkce. Ty se vyznačují tím, že mají prefix
posix_. No a jak si můžeš všimnout, funkce fwrite() ten prefix nemá. Takže na ni
posix_get_last_error() logicky nefunguje a tedy to co jsi psal, je totální hovadina.
Citace od: Filip Jirsák kdy 02. 07. 2018, 22:23:51
Kód v prvním příspěvku by mohl hlásit chybu zaplnění disku jedině v případě, že by disk byl plný už před začátkem zápisu. Kdyby se disk zaplnil už voláním té funkce fwrite(), selhalo by už druhé volání fwrite(), a tam žádný výpis chybového kódu není.
Hele a tohle jsi v praxi ověřoval? Řek bych že ne a zase jen plácáš ty svoje neověřený teoretický nesmysly. PHP prostě žádný chybový kód nenastaví. Ani při prvním, ani při jakémkoli dalším volání.
Citace od: L. kdy 03. 07. 2018, 05:31:17
Nejdřív jsi se tu točil na nějakém částečném zápisu, což ale problém vůbec nebyl. Ono totiž PHP, jak se zdá, tu smyčku dělá už interně ve funkci, kterou volá ten fwrite(): https://github.com/php/php-src/blob/master/main/streams/streams.c#L1080 (https://github.com/php/php-src/blob/master/main/streams/streams.c#L1080)
Normální je programovat proti specifikaci funkce, ne proti tomu, jak je aktuálně naimplementovaná. Když je zdokumentováno, že funkce vrací počet zapsaných bajtů, plyne z toho, že nemusí zapsat vše (zvlášť když je to obvyklé chování funkcí zapisujících do streamu). Když si někdo zjistí, že zrovna v jeho verzi ta funkce zapíše vše nebo vrátí chybu, naprogramuje podle toho svůj kód, a pak se chování funkce změní (ale bude pořád v souladu s dokumentací), bude mít v programu chybu, v tomto případě navíc těžko odhalitelnou (protože bude nastávat jen někdy).
Že ta PHP funkce
fwrite() funguje úplně jinak, než je popsáno v dokumentaci, je dost zásadní chyba. Pokud to tazatel věděl, měl to napsat. Jinak bývá dobrým zvykem hledat chybu nejprve ve svém kódu a teprve pak v knihovnách. A ten kód andreaw.fean je špatně, a to i v případě, když bude počítat s tím, že tu smyčku dělá
fwrite() interně.
Citace od: L. kdy 03. 07. 2018, 05:31:17
Kdybys měl alespoň trochu ánunk o tom, o čem píšeš, tak by ti došlo, že posix_get_last_error() je z POSIX modulu, tedy funguje jen pro jeho funkce. Ty se vyznačují tím, že mají prefix posix_. No a jak si můžeš všimnout, funkce fwrite() ten prefix nemá. Takže na ni posix_get_last_error() logicky nefunguje a tedy to co jsi psal, je totální hovadina.
Dalo se předpokládat, že
fwrite() interně volá nativní funkci
write(), která je definovaná POSIX standardem, a která v případě neúspěchu ukládá chybový kód do
errno. Funkce
posix_get_last_error() mohl být způsob, jak
errno přečíst.
Citace od: L. kdy 03. 07. 2018, 05:31:17
Hele a tohle jsi v praxi ověřoval? Řek bych že ne a zase jen plácáš ty svoje neověřený teoretický nesmysly. PHP prostě žádný chybový kód nenastaví. Ani při prvním, ani při jakémkoli dalším volání.
Ten kód, tak jak je napsaný, nejdřív předpokládá, že když se nezapíše vše, je to hned chyba, a vzápětí se pokusí zapsat ještě zbytek. Při jaké konstelaci tenhle kód dává smysl?
Ověřit to chování měl andreaw.fean, on měl prostředí, kde k nějaké chybě docházelo. Když se mně nepodaří nasimulovat případ, že by
fwrite() vrátilo menší počet zapsaných bajtů, než byl počet bajtů k zápisu, v žádném případě to neznamená, že mám počítat s tím, že to nemůže nikdy nastat. Přesně na základě takovýchto předpokladů vznikají programy, které pak různě náhodně padají.
To, že PHP žádný chybový kód nenastaví bylo potřeba zjistit – buď zkoumáním zdrojáků, nebo testem. Ten test je ovšem potřeba provést tak, aby vůbec byla šance, že tu chybu nastaví. Tvrdit, že funkce
fwrite() chybu nenastavuje, na základě kódu, který nastavení chyby neumí zjistit, je dost
odvážné. A nic na tom nemění fakt, že se nakonec (úplně jiným způsobem) ukázalo, že
fwrite() opravdu chybu nenastavuje.
Kdyby se funkce
fwrite() chovala tak, jak je popsané v dokumentaci, ten kód andreaw.fean by se choval přesně tak, jak popisoval – tj. žádnou chybu by to nevypsalo. Stačilo by ten kód opravit. Že se nakonec
fwrite() chová úplně jinak je dost problém, a vzhledem k této diskusi je to jen náhoda. Kdyby andreaw.fean ten svůj kód opravil, vzápětí by se přišlo na to, že
fwrite() funguje špatně – a mohlo by se to řešit. Místo toho se tu pořád dokola řešilo, že vlastně nikdo neví, jak vlastně ten kód funguje. Vždyť andreaw.fean ani nebyl schopen napsat, jestli mu to volání
fwrite() vrací
FALSE,
0 nebo nějakou kladnou hodnotu. To by hledání chyby značně urychlilo, protože kdyby opakovaně vracelo
0, bylo by jasné, že se to chová jinak, než je zdokumentováno.
Nakonec se tedy strašně dlouhou a klopotnou cestou skládání náhodných úryvků kódu dospělo k řešení, se kterým je andreaw.fean spokojen. Je ale velmi smutné, kolik lidí tady v diskusi vůbec nepochopilo, proč je ten původní kód špatně, a vlastně jim je úplně jedno, že to nechápou – prostě ten kód zkouší náhodnými výstřely měnit, a když jim to jednou udělá, co chtějí, jsou spokojení, a mají pocit, že je kód správně. A ještě mají pocit, jací jsou machři. Už se vůbec nedivím, že BoneFluteovi jednotkové testy vůbec nepomáhají – pokud testuje jenom to, co mu zrovna spadlo pod rukama, a vůbec nechápe, co jeho kód vlastně dělá a kde jsou potenciální chyby, jednotkové testy mu opravdu nijak nepomůžou.
Citace od: Filip Jirsák kdy 03. 07. 2018, 07:49:25
< ... bláboly snipped ... >
Stále kvoká, stále kvoká... (https://www.youtube.com/watch?v=j4UpBVN-qE8&feature=youtu.be&t=10s)
Citace od: Lol Phirae kdy 03. 07. 2018, 08:00:09
Stále kvoká, stále kvoká... (https://www.youtube.com/watch?v=j4UpBVN-qE8&feature=youtu.be&t=10s)
Je to tak. Pevně doufám, že nikde neprogramuje a pokud ano, tak lituju jeho spolupracovníky. U mě by takový nemehlo vyletělo na hodinu zavřenýma dveřma a ještě bych mu je dal k úhradě.
Citace od: L. kdy 03. 07. 2018, 08:22:58
Je to tak. Pevně doufám, že nikde neprogramuje a pokud ano, tak lituju jeho spolupracovníky. U mě by takový nemehlo vyletělo na hodinu zavřenýma dveřma a ještě bych mu je dal k úhradě.
Dobře, uznávám, rozumíte tomu lépe než já. Můžete mi tedy některé věci na tom kódu uvedeném v dotazu vysvětlit? Napíšu i nijaké příklady možných odpovědí, aby bylo srozumitelnější, na co se ptám – těmi příklady odpovědí se ale nenechte zmást, ty jsou evidentně špatně.
- Jaký je význam toho druhého volání fwrite() – na řádku 14? Myslím tím jakou situaci ošetřuje. Např. by odpověď mohla být: ,,Ošetřuje situaci, kdy první volání fwrite() na řádku 9 je jen částečně úspěšné, zapíše jen část dat, ale je možné, že se při dalším pokusu podaří zapsat další část – např. pokud by při prvním volání byl disk plný, ale před druhým voláním by se místo uvolnilo."
- V jakém případě dojde program k tomu druhému volání fwrite() – na řádku 14? Jaké budou invarianty programu? Např.: ,,První volání fwrite() na řádku 9 vrátilo hodnotu FALSE nebo 0." Nebo.: ,,První volání fwrite() na řádku 9 vrátilo hodnotu počet zapsaných bajtů, větší než 0 a menší než délka $s."
- Jaký bude výsledek volání programu, pokud před prvním voláním fwrite() (na řádku 9) bude na cílovém disku volné místo, ale ne tolik, aby se tam vešlo celé $s, a před druhým voláním fwrite() (na řádku 14) se nějaké místo na disku uvolní? Zajímá mne především co bude aplikace vypisovat a co bude zapsané v cílovém souboru.
Citace od: L. kdy 03. 07. 2018, 08:22:58
Citace od: Lol Phirae kdy 03. 07. 2018, 08:00:09
Stále kvoká, stále kvoká... (https://www.youtube.com/watch?v=j4UpBVN-qE8&feature=youtu.be&t=10s)
Je to tak. Pevně doufám, že nikde neprogramuje a pokud ano, tak lituju jeho spolupracovníky. U mě by takový nemehlo vyletělo na hodinu zavřenýma dveřma a ještě bych mu je dal k úhradě.
No tak strasne to asi nebude, ale v tymu nebo ve firme bych ho nechtel. At si nekde cosi patla na kontrakt, kdyz je s tim zakaznik happy, proc ne. Ale jinak domluva s nim musi byt ukrutne slozita.
To je vtipná představa, že by junioři ve zkušební době (protože po zkušebce už musí takhle očividné chyby vidět sám) vyhazovali seniory, když by si senior dovolil upozornit na chybu v kódu juniora.
Ale je teda dost smutné vidět tu několik lidí, kteří si o sobě očividně myslí bůhví co a myslí si, že umí programovat, kterým nevadí program pro zápis do souboru, který:
- úspěšně zapíše všechna data a vypíše chybu, že se podařilo zapsat jenom část dat
- skončí s chybou, že se nepodařilo všechna data zapsat, přestože na disku je dost místa a ani nic jiného nebrání všechna data zapsat
Navíc kdyby ta funkce
fwrite() uměla nějak signalizovat příčinu chyby, při zápisu na zcela plný disk by program správně oznámil, že disk je plný, ale kdyby se disk zaplnil teprve v průběhu zápisu, program by v lepším případě (pokud by andreaw.feana něco osvítilo a počítal by s tím, že se při zjištění chyby může dozvědět, že k žádné chybě nedošlo) oznámil, že došlo k nečekané chybě.
Stejně by mne ale zajímalo, kdyby L., ffd, BoneFlute nebo andreaw.fean odpověděli na ty tři otázky, které jsou v mém předchozím komentáři. Zajímalo by mne, jestli aspoň chápete význam jednotlivých řádků kódu, jenom si nedokážete spojit dohromady, co to dělá, když se ty řádky provádí postupně za sebou, a nebo jestli vám uniká i význam těch jednotlivých řádků.
CitaceKdybys měl alespoň trochu ánunk o tom, o čem píšeš, tak by ti došlo, že posix_get_last_error() je z POSIX modulu, tedy funguje jen pro jeho funkce. Ty se vyznačují tím, že mají prefix posix_. No a jak si můžeš všimnout, funkce fwrite() ten prefix nemá. Takže na ni posix_get_last_error() logicky nefunguje a tedy to co jsi psal, je totální hovadina.
Přímo v dokumentaci http://php.net/manual/en/function.posix-get-last-error.php se používá v příkladu stream_select(), takže to s tím "posix_" prefixem není pravda. Zbytek se mi nechce hledat, ale řekl bych, že ta funkce logicky vrací "errno".
Citace od: unicode kdy 04. 07. 2018, 03:57:43
CitaceKdybys měl alespoň trochu ánunk o tom, o čem píšeš, tak by ti došlo, že posix_get_last_error() je z POSIX modulu, tedy funguje jen pro jeho funkce. Ty se vyznačují tím, že mají prefix posix_. No a jak si můžeš všimnout, funkce fwrite() ten prefix nemá. Takže na ni posix_get_last_error() logicky nefunguje a tedy to co jsi psal, je totální hovadina.
Přímo v dokumentaci http://php.net/manual/en/function.posix-get-last-error.php se používá v příkladu stream_select(), takže to s tím "posix_" prefixem není pravda. Zbytek se mi nechce hledat, ale řekl bych, že ta funkce logicky vrací "errno".
Zkoušel jsem to. Ty funkce bohužel nefachají. Ani jedna.