Мультипроцессорная запись в файл

zuxel

Новичок
У меня скрипт пишет несколькими процессами данные в файл, столкнулся с тем, что процессы пишут данные поверх того, что уже записали другие процессы, т.к. каждый помнит отступ от начала файла в только для своего дескриптора, подобного можно избежать, если файл открывать не единожды при создании процесса, а для каждой операции записи, как-то так:
PHP:
        $this->file = @fopen($this->getFilePath(), 'a');
        if ( ! $this->file) {
            throw new \Exception('Unable to open file');
        }
        if ( ! flock($this->file, LOCK_EX)) {
            throw new \Exception('Unable to aquire file lock');
        }
        fputcsv($this->file, $r, ';');
        flock($this->file, LOCK_UN);
        fclose($this->file);
Но м.б есть способ считывать количество байт уже записаных в файл и делать fseek?
Или существенной потери в скорости и ресурсах не будет если продолжать использовать вышеприведенный подход?
 

Breeze

goshogun
Команда форума
Партнер клуба
как запускаются процессы?
как используются данные из файла потом?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
В период между моментом считывания количества байт в файле и записью другой процесс может что-то дописать.
Какая у тебя OS?

А в чем, собственно, проблема с локами? это стандартное решение
 
Последнее редактирование:

AnrDaemon

Продвинутый новичок
file_put_contents(…, FILE_APPEND);
Используйте правильные инструменты, к?
 

Absinthe

жожо
file_put_contents(…, FILE_APPEND);
Используйте правильные инструменты, к?
А почему ты считаешь, что при записи через file_put_contents данные из 2 процессов не перемешаются?
Вот давай с пояснениями.

Уже на уровне исходников (не доходя до системных вызовов) это происходит:
https://github.com/php/php-src/blob/0437aa2abf1eb494e4555d7d4dfbdbf566a59bdc/ext/standard/file.c#L644
https://github.com/php/php-src/blob/0437aa2abf1eb494e4555d7d4dfbdbf566a59bdc/main/streams/streams.c#L1113
 

fixxxer

К.О.
Партнер клуба
Потому что надо делать FILE_APPEND | LOCK_EX. Сорцы читать необязательно, пример №2 в мануале.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума

grigori

( ͡° ͜ʖ ͡°)
Команда форума
хотел бы добавить, что собака в @fopen - штука опасная
 

Breeze

goshogun
Команда форума
Партнер клуба
кто б еще проверял, все ли правильно записалось
 

fixxxer

К.О.
Партнер клуба
file_put_contents как раз таки проверяет, вон выше ссылка на сорцы. Смущает, правда, отсутствие проверки на php_stream_close, но может там внутрях проверка и warning.
 

Breeze

goshogun
Команда форума
Партнер клуба
file_put_contents как раз таки проверяет, вон выше ссылка на сорцы. Смущает, правда, отсутствие проверки на php_stream_close, но может там внутрях проверка и warning.
именно, что там в сорцах только варнинг в качестве результата, если ты его словил, то поздно уже при отсутствии еггог хендлера :)
свою ручную проверку так никто и не отменил, особенно при fwrite и fputcsv.

php_stream_close это макрос на _php_stream_free, оно там делает либо return 1, либо 0, и кое-где fclose(stream->stdiocast);
думаю слишком экзотично это, проверять fclose, все-таки ^_^
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
надо бы разобраться что в 7ке меняют в обработке ошибок
 

Breeze

goshogun
Команда форума
Партнер клуба
при работе с файлами, судя по всему, ничего не меняется.
в 5.x и в 7 юзается php_verror из main.c
 

AnrDaemon

Продвинутый новичок
Да там вообще ничего не меняется в самых нужных местах.
Как писали
if(!($result = @action())) throw \Exception();
так и будем писать.
 

Breeze

goshogun
Команда форума
Партнер клуба
Да там вообще ничего не меняется в самых нужных местах.
Как писали
if(!($result = @action())) throw \Exception();
так и будем писать.
а было б лучше, если бы вместо варнингов были некие FileNotFoundException или NoSpaceOnDeviceException, да?
без варнинга, нотайса и т.д.
как с BC быть?
 

AnrDaemon

Продвинутый новичок
В жопу такой BC, ей-богу…
А если серьёзно, то опцию в конфиге - "все ошибки времени выполнения в эксепшены".
Глобально.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
что мешает конвертировать warning-и в excetion-ы?
Redjik даже пытался сделать более-менее универсальную либу на эту тему. https://github.com/Redjik/Filesystem все не так уж сложно
 
Сверху