LINUX.ORG.RU

Отслеживать размер файла при непрерывной записи

 , ,


0

3

Есть непрерывный процесс записи в файл. Файловый дискриптор все время открыт. Необходимо когда файл превысит 800Mb закрыть файл и начать писать в новый. Каким образом это лучше сделать? Думал просто иметь переменную типа long long и при каждой записи добавлять туда количество записанных данных.


Можно узнать позицию в файле, например. Вот не знаю сообщает ли линукс размер для несброшенных данных, а вот позиция с точки зрения кода будет точной. Теперь определись записать ещё, или поменять файл в зависимости от объёма данных, ожидающих записи.

anonymous
()

Анон дело говорит, смотреть позицию + размер блока который пытаешься записать, только не надо вот этих long long, если ты используешь системные вызовы, то используй size_t

sparks ★★★
()
Ответ на: комментарий от anarch

Ну мне изначально не нравилось это решение, а по поводу смотреть позицию я думаю что это разумно.

ECLIPSE
() автор топика
Ответ на: комментарий от sparks

Видимо то, что на 32 битах ты переполнишься на 4 гигах. Не совсем понимаю какое отношение к топику, но проблемы на 32 битах с файлами очень популярны.

anonymous
()

типа long long

Не long_long, а size_t. Так и делай. И не слушай дурачков, не нужно смотреть ни на позицию файла на на stat: во-первых, их может не быть (мало ли, приспичит писать в устройство/сокет/fifo), во-вторых, это дополнительный совершенно не нужный сисколл.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Ну 1 раз на них тебе придётся посмотреть в любом случае. Плюс, если кто-то что-нибудь запишет тебе в другом потоке, твоё решение тут же *censored*^W^W^W даст о себе знать.

anonymous
()
Ответ на: комментарий от i-rinat

Если ты неуч, не нужно выдумывать мотивы людей исходя из своих скудных знаний, нужно помалкивать в тряпочку и слушать других. Битность тут совершенно не при чём. Просто использование правильных и безопасных типов.

slovazap ★★★★★
()
Ответ на: комментарий от anonymous

Ну 1 раз на них тебе придётся посмотреть в любом случае

Во-первых, зависит от задачи: если файл открывали с O_TRUNC, не нужно никуда смотреть. Во-вторых, разницу между O(1) и O(n) ещё не проходили?

Плюс, если кто-то что-нибудь запишет тебе в другом потоке, твоё решение тут же *censored*^W^W^W даст о себе знать.

Ни слова не было о таких требованиях.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Не, я ничего против того чтобы кастовать long к size_t не имею, но они ж типа как могут и различаться.

anonymous
()
Ответ на: комментарий от anonymous

Откуда вы взяли long? В этой задаче вообще нет long ни в каком виде, только size_t. В size_t измеряются данные для записи, size_t передаётся write(2) или аналогу, в size_t же накапливается общий объём записанного.

slovazap ★★★★★
()

Позиция в файле так себе решение, потому что какой-нибудь pread/pwrite ее не апдейтят. Так что считай размер сам, это самый разумный выбор.

kirk_johnson ★☆
()
Последнее исправление: kirk_johnson (всего исправлений: 1)
Ответ на: комментарий от slovazap

Просто использование правильных и безопасных типов.

size_t для размера файла является правильным и безопасным типом?

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

он вроде уже признался, что нужно off_t.

Я дополню только топик, что не нужно забывать про магию _FILE_OFFSET_BITS, и лишний раз не помешает заглянуть в ман про lseek

Deleted
()
Ответ на: комментарий от Deleted

Ну мне обидно же. Мало того что неучем обозвал, так ещё и такой бред написал, что аж волосы дыбом становятся. Не представляю, как можно такое заявлять с подобной уверенностью.

i-rinat ★★★★★
()

Надо бы вернуться к теме ТС.

когда файл превысит 800Mb закрыть файл

Тебе нужно ровно 800МБайт или примерно, лишь бы разбить? (Кстати, 'Mb' означает мегабит)

Каким образом это лучше сделать?

Не вижу особых подводных камней. Юзаешь write(2). Если данные приходят неравномерно, то сделай накапливающий буфер на несколько десятков мегабайт. Вызов write приводит к копированию данных из юзерспейс в кернел, поэтому надо избегать сотен вызовов в секунду, накапливать данные и затем писать уже большими кусками.

Думал просто иметь переменную и при каждой записи добавлять туда количество записанных данных.

this

Если еще какие-то особенности, вроде необходимости работать с записанными данными параллельно из другого процесса (читать, изменять), или достаточно широкого потока входных данных (>50МБайт/сек) - озвучь, и надо думать

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

Все вы тут в треде забыли один прикол.

У ТС файл всегда открыт. Если этот файл удалит другой процесс (или он сам его почикает из своей прожки), его код продолжит писать в файл как ни в чем не бывало, и даже сикать по нему сможет.

Тут как ни пляши — инотифи прикручивать придется.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

У ТС файл всегда открыт. Если этот файл удалит другой процесс (или он сам его почикает из своей прожки), его код продолжит писать в файл как ни в чем не бывало, и даже сикать по нему сможет.

Это фича. Дописываешь действие «переоткрыть файл лога», и слежение за размером можно переложить на logrotate.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Если «файл» только начали забивать данными, то 800 метров он еще не скоро накопит. Но его уже удалили из другого места.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Все вы тут в треде забыли один прикол.

я специально упомянул,

> Если еще какие-то особенности, вроде необходимости работать с записанными данными параллельно из другого процесса (читать, изменять)

что хочу выпытать у ТС, чего там будет происходить.

Если этот файл удалит другой процесс

если ты предлагаешь учитывать случай, что кто-то случайно удалит файл ТС-а, то это решается методом установки прав на запись-чтение.

если это штатный случай, то ТС надо сформулировать требование и реализовать, никаких проблем.

Deleted
()
Ответ на: комментарий от deep-purple

Чем ты хочешь удивить? Это специфическое поведение, специально оговорено. Если нужно - делается.

Давай обсудим и повангуем, я вот не считаю такое поведение (как ведут себя логи) штатным при условиях, данных ТС-ом. Обоснуй, что оно необходимо. Рутом можно удалить много чего...

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от i-rinat

тридцать-два-бита

Эх, щас бы в 2004.

anonymous
()
Ответ на: комментарий от Deleted

Ничем не удивить. Не цепляйся к руту. Этим я показываю что права доступа не решат проблему удаления файла.

Почему спецефическое? По мне так нормальная реакция приложения на состояние ЕГО файлов, которые удаляются-перемещаются кем-то другим.

В данном случае логи. Ну возьми конфиг как другой пример — запишет вникуда если дескриптор был открыт до удаления файла.

обоснуй

У ТСа файл все время открыт. Нет никакой гарантии что никто не удалит файл (пометит иноду свободной) пока его прожка пишет дальше, думая, что данные все еще не просраны, а они уже просраны, все 800 метров, после закрытия файла уже никак не доступны, ну кроме что попытки восстановить спец утилитами.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Я тебя понял... Но где та грань предусмотрительности, которую надо обеспечить? А если место закончится или вдруг резко возрастет поток входящих данных ( в 100 раз)? Это уже требования к системе в целом. Согласен, эти вопросы надо прорабатывать.

Deleted
()
Ответ на: комментарий от deep-purple

Нет никакой гарантии что никто не удалит файл

Файл можно переименовать, сделать truncate, испортить содержимое и так далее. К чему эти экзерцисы? У каждой задачи есть ТЗ, решение этого ТЗ ТС и хочет получить.

vodz ★★★★★
()
Ответ на: комментарий от deep-purple

У ТСа файл все время открыт. Нет никакой гарантии что никто не удалит файл (пометит иноду свободной)

Хватит чушь нести. Инода как раз таки занята, на нее референс держится через открытый fd. Удалили связанное с ней имя файла. Возможно даже не последнее.

kirk_johnson ★☆
()
Ответ на: комментарий от i-rinat

Ну, блин. Тот самый «чорт», который проценты в урл пихает. Затем, чтобы жизнь малиной не казалась.

Проверять наличие файла перед записью в него надо? Надо. Если файла нет, его создать надо? Надо. Только единожды изначально полученый дескриптор уже ничего не скажет, существует ли сейчас файл или нет, и даст успешно туда (вникуда) записать.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Проверять наличие файла перед записью в него надо? Надо.

Нет, не надо. Нужно сделать open() и проверить код возврата. Иначе возможен race condition.

Если файла нет, его создать надо? Надо.

Нет, не надо. Нужно передать open() аргумент O_CREAT и нужный mode. Иначе возможен race condition.

Только единожды изначально полученый дескриптор уже ничего не скажет, существует ли сейчас файл или нет, и даст успешно туда (вникуда) записать.

Нет, скажет. Потому что в Linux (и UNIX) существование ФАЙЛА (не, имени, сиречь линка, а файла) определяется существованием INODE. Который, в свою очередь, имеет refcnt. И любой open (сиречь полученный файловый дескриптор) этот refcnt бампает. А теперь следи за руками: чувак делает open, пишет в полученный дескриптор, а кто-то удаляет линк на файл (делает unlink). Но файл (аллоцированные на диске блоки) никуда не денутся, пока последный fd не будет закрыт. Грубо говоря, если файл не закроют, занятое им место может расти вплоть до ENOMEM.

kirk_johnson ★☆
()
Ответ на: комментарий от deep-purple

Ты какой-то бред несёшь уже. Нельзя проверять всё, просто не получится. Нужно где-то провести границу. Но твоя граница какая-то странная и плохо очерчена.

Каждый раз проверять наличие файла? Что это значит вообще? Допустим, файл переименовали во время работы. Что делать будешь? Допустим, его переименовали обратно. Что делать будешь? Допустим, файл переименовали, а со старым именем создали новый. Что делать будешь?

i-rinat ★★★★★
()
Ответ на: комментарий от kirk_johnson

Нет, не надо

А я по твоему имел ввиду как то иначе?

Что проверять?

В жопе поковырять )) Что, как ты утверждаешь, данные сохранится и будут доступны после закрытия файла. Или что ты там имел ввиду, волшебным образом файл снова появится как только прога его допишет флашнет и закроет.

deep-purple ★★★★★
()
Ответ на: комментарий от i-rinat

Вернемся к тому что я предлагал не проверять каждый раз, а пользовать инотифи.

Что я буду делать? Начну срать в стдэрр/логи о конкретном случившемся.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

А я по твоему имел ввиду как то иначе?

А я понятие не имею, что ты там имел. Либо ты нормально свои мысли выражать не умеешь, либо дурак. В любом случае, я бы тебе посоветовал эту проблему как-то решить.

Что, как ты утверждаешь, данные сохранится и будут доступны после закрытия файла. Или что ты там имел ввиду, волшебным образом файл снова появится как только прога его допишет флашнет и закроет.

Я имел в виду, что пока существует хотя бы один открытый файловый дескриптор, файл никуда не денется. И это мы ещё про хардлинки даже не начинали :)

kirk_johnson ★☆
()
Ответ на: комментарий от kirk_johnson

Я имел в виду

Ты имел ввиду «толсто».

пока существует хотя бы один открытый файловый дескриптор, файл никуда не денется

А это имел ввиду я, только с другого боку, поясняя что файл денется вникуда как только ты его закроешь.

Помоему наркоман ты.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

А это имел ввиду я, только с другого боку, поясняя что файл денется вникуда как только ты его закроешь.

Ты смешно истеришь и предлагаешь совершать странные манипуляции ради никакого профита.

kirk_johnson ★☆
()
Ответ на: комментарий от kirk_johnson

Да, похоже. Или это странная попытка шутить.

i-rinat ★★★★★
()
Ответ на: комментарий от deep-purple

не проверять каждый раз, а пользовать инотифи.

Не спасёт от прямого изменения содержимого /dev/sda.

А ещё пользователь может собрать ядро без поддержки inotify.

А ещё сторонняя программа может загрузить в ядро модуль, с помощью которого будет перехватывать и изменять файловые операции.

i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.