Господа, прошу подсказать. Этой функцией я записываю текущую маркет дату
Код
function rec_big_data(file_path,value)
if rn==nil then rn={} end
if file_open==nil then file_open={} end
if file_open[file_path]==nil then
rn[file_path]=io.open(file_path,"a+")
file_open[file_path]=true
mm("QL:open file "..file_path)
end
rn[file_path]:write(value.."\n")
rn[file_path]:flush()
end
file_path меняется три раза в день (в его название включён тикер, текущая дата и номер триместра: утренняя сессия 1, дневная сессия 2, вечерняя сессия 3). вот пример historyGDM8 20180511-2.lua В функции нет закрытия файла, потому что файл становится огромным, и скрипту тяжело его постоянно открывать-закрывать. Робот пишет большое количество инструментов много дней подряд. Файлы остаются открытыми. Я замечаю, что виртуалка начинает тормозить. Думаю, что это из-за незакрытых файлов. Подскажите пожалуйста как грамотно закрывать файл в конце триместра (при переходе на новый файл) с помощью close()? Не могу сообразить, что в неё писать. Спасибо.
Пользователь
Сообщений: Регистрация: 16.01.2017
12.05.2018 01:03:54
Таблица дескрипторов файлов (rn) у Вас - глобальная. Где-то вне функции rec_big_data Ваш скрипт, судя по всему, в нужный момент понимает, что нужно сменить номер триместра. Что Вам мешает в этот момент просто позакрывать все файлы, зная их дескрипторы из таблицы rn?
Пользователь
Сообщений: Регистрация: 29.03.2017
12.05.2018 03:51:07
Спасибо. подумаю И ещё вопрос. Я открываю много файлов с помощью dofile Файлы имеют вид Файлы огромных размеров. После исполнения dofile эти файлы остаются открытыми? Надо ли заботиться о том чтобы их закрывать?
Пользователь
Сообщений: Регистрация: 10.04.2015
12.05.2018 07:22:10
Цитата
Let_it_go написал: После исполнения dofile эти файлы остаются открытыми? Надо ли заботиться о том чтобы их закрывать?
Нет. Они закрываются внутри dofile, причём ещё до того, как запустится интерпретатор кода загруженного из этих файлов.
Пользователь
Сообщений: Регистрация: 29.03.2017
13.05.2018 14:19:10
Спасибо за ответы. Разрешите задать ещё вопрос. Я открыл файл с помощью io.open. После этого я остановил скрипт. Файл останется открытым, верно? Если да, то следующий вопрос. Я запустил скрипт и снова открыл этот же файл с помощью io.open. Теперь у меня два открытых файла? --- И ещё один вопрос. Как мне принудительно закрыть файл, имея не дескриптор, а только путь file_path? --
Спасибо.
Пользователь
Сообщений: Регистрация: 29.03.2017
13.05.2018 14:22:22
Как мне отлавливать средствами Луа, Windows или специальных программ открытые в данный момент луа-файлы? В Windows server 2003 эта функция не работает и не лечится. Я искал советы по данной проблеме, но они не сработали.
Пользователь
Сообщений: Регистрация: 29.03.2017
13.05.2018 14:58:47
Цитата
Алексей написал: Таблица дескрипторов файлов (rn) у Вас - глобальная. Где-то вне функции rec_big_data Ваш скрипт, судя по всему, в нужный момент понимает, что нужно сменить номер триместра. Что Вам мешает в этот момент просто позакрывать все файлы, зная их дескрипторы из таблицы rn?
Добавил в функцию переменную files_qty - это количество бумаг, которые пишутся. Если размер таблицы rn больше files_qty, значит сменился триместр и надо закрывать старые файлы. Очевиден недостаток: при смене триместра функция один раз закроет хороший файл - файл новенького триместра. Потом ей придётся его переоткрывать. Спасибо за комментарии. Они очень помогают.
Пользователь
Сообщений: Регистрация: 10.04.2015
14.05.2018 11:49:43
Цитата
Let_it_go написал: Я открыл файл с помощью io.open. После этого я остановил скрипт. Файл останется открытым, верно?
Нет. Закроется.
Цитата
Let_it_go написал: И ещё один вопрос. Как мне принудительно закрыть файл, имея не дескриптор, а только путь file_path?
Никак. Если речь идёт о дескрипторе файла в Lua, который имеет тип «userdata».
Цитата
Let_it_go написал: Как мне отлавливать средствами Луа, Windows или специальных программ открытые в данный момент луа-файлы?
Можете использовать для этих целей Process Explorer ().
Цитата
Let_it_go написал: В Windows server 2003 эта функция не работает и не лечится. Я искал советы по данной проблеме, но они не сработали.
Вы не то смотрите. Эта оснастка «Общие папки» показывает файлы открытые по сети (по протоколу SMB), и это никакого отношения к файловой системе и файлом открытым локально не имеет. Оснастка у вас не работает скорее всего, если мне не изменяет память, потому что не запущена одна из служб, на подобие «Files and Folder bla bla bla» или что-то вроде того... чтобы посмотреть системные ресурсы открытые конкретным процессом, в том числе и файлы, используйте Process Explorer.
Цитата
Let_it_go написал: Добавил в функцию переменную files_qty - это количество бумаг, которые пишутся. Если размер таблицы rn больше files_qty, значит сменился триместр и надо закрывать старые файлы. Очевиден недостаток: при смене триместра функция один раз закроет хороший файл - файл новенького триместра. Потом ей придётся его переоткрывать.
1. Файл закрывайте там, где вы определяете смену «триместра», то-есть там, где у вас создаётся новая path. И там же открывайте сразу новый по новому имени. А внутри функции записи оставьте собственно только запись. 2. Уберите строчку «rn[file_path]:flush()», это тяжёлая операция, на которой у вас всё будет тормозить. Этот flush делайте только перед самым закрытием файла, то-есть перед close(). 3. Зачем вам вторая таблица file_open где вы ставите true, она просто дублирует вашу основную таблицу rn с дескрипторами. Уберите её из кода, а открытие файла для конкретного file_path проверяйте условием «nil == rn[file_path]», а после закрытия файла обнуляйте этот же элемент через «rn[file_path] = nil». 4. Выражение «#rn>files_qty» не сработает, потому что у вас таблица строится по строковым ключам, а оператор # работает только для индексированных по номерам таблиц, то-есть когда они используются как массивы. 5. Структура кода у вас неправильная, запись в файл нужно делать после проверки на nil возврата функции io.open. Вы эту проверку вообще не делаете после вызова io.open, а делает только при повторном вызове основной функции при следующей записи. У вас там нужно часть строк стереть, а часть местами поменять, чтобы привести код в порядок.
Пользователь
Сообщений: Регистрация: 29.03.2017
14.05.2018 22:21:35
если я уберу flush при каждой записи, не появятся ли чрезмерные риски того, что какая-то часть данных не запишется? Ну например я принудительно остановил скрипт. Ведь в этом случае какие-то строчки потеряются? Или не потеряются?
если я уберу flush при каждой записи, не появятся ли чрезмерные риски того, что какая-то часть данных не запишется? Ну например я принудительно остановил скрипт. Ведь в этом случае какие-то строчки потеряются? Или не потеряются?
При останове скрипта луа машина, встроенная в терминал, автоматически закрывает все файлы посредством close(). Это происходит с версии qlua 6.xx вроде.
Вызов close() всегда подразумевает flush() - так устроена библиотека С.
Поэтому вы ничем не рискуете.
flush() имеет смысл только в том случае, если вы в реальном времени другой программой читаете создаваемый файл. Flush() сбрасывает файловый буфер на диск немедленно. Без него файловые операции кешируются в памяти. В момент закртытия файла все буферы сбрасываются на диск.
Пасхалочка для Алексея Иванникова:
Пользователь
Сообщений: Регистрация: 29.03.2017
14.05.2018 23:01:50
Спасибо, друзья. Проясняется, хотя мне очень тяжело с этим разбираться. Не то образование... Вот текущая редакция функции, которая пишет слепки стакана. Триместр сменился, если путь поменялся. В этом случае закрываем старый файл, открываем новый.
Пользователь
Сообщений: Регистрация: 10.04.2015
15.05.2018 00:22:34
Цитата
Let_it_go написал: Спасибо, друзья. Проясняется, хотя мне очень тяжело с этим разбираться. Не то образование... Вот текущая редакция функции, которая пишет слепки стакана. Триместр сменился, если путь поменялся. В этом случае закрываем старый файл, открываем новый.
В таком виде, как правильно написал , flush перед самым close смысла особого не имеет. Поэтому можете стереть там строчку. Мне вообще ваш подход не нравится. Вы пытаетесь запихать в одну функцию всю логику работы с файлами. Поэтому у вас в этой функции будет куча лишних проверок замедляющий её основную работу — запись. Но даже, в рамках вашего подхода, я бы всё переписал по-другому. Как-то вот так:
Код
rn = rn or {}
rn[paper] = rn[paper] or {}
if file_path~=rn[paper].file_path then
if rn[paper].handler then
rn[paper].handler:close()
end
rn[paper].handler:io.open(file_path, "a+")
if rn[paper].handler then
rn[paper].file_path = file_path
else
mm("QL:open file error "..file_path)
end
end
if rn[paper].handler then
rn[paper].handler:write(value.."\n")
end
— код не проверял, пишу из головы, чтобы передать суть.
Пользователь
Сообщений: Регистрация: 29.03.2017
15.05.2018 21:51:38
Выключил flush. Почему-то на всех сегодняшних файлах стал появляться одинаковый глюк: вот такое искажение: неадекватная (неполная строчка). Плюс пропуск нескольких секунд. До ошибки время 184444, после ошибки 184449. Может быть я в это время его включал-выключал, но я увы не помню этот момент. Днём на 1 из файлов было то же самое. Раньше, когда flush работал, такого не было. Видоизменил функцию. Добавил в неё flush 1 раз в 100 записей по данной бумаге:
Код
count[paper]=(count[paper] or 0)+1
if count[paper]==100 then
rn[paper].handler:flush()
count[paper]=0
end
Пользователь
Сообщений: Регистрация: 10.04.2015
16.05.2018 12:59:36
Цитата
Let_it_go написал: Выключил flush. Почему-то на всех сегодняшних файлах стал появляться одинаковый глюк: вот такое искажение:
А у вас получение данных и запись их в файл идут в одном потоке или в разных? Очень на «рассинхрон» похоже...
Пользователь
Сообщений: Регистрация: 29.03.2017
16.05.2018 20:41:33
Получаю данные колбеком OnParam. В него вставлена обсуждаемая функция.
Пользователь
Сообщений: Регистрация: 29.03.2017
16.05.2018 20:44:06
Вот ещё один случай. Что характерно, снова перед закрытием сессии. Почти в то же время.
Пользователь
Сообщений: Регистрация: 29.03.2017
16.05.2018 20:46:45
то есть мой метод не сработал. flush раз в 100 записей не помог.
Пользователь
Сообщений: Регистрация: 10.04.2015
16.05.2018 23:30:08
Цитата
Let_it_go написал: Получаю данные колбеком OnParam. В него вставлена обсуждаемая функция.
А внутри OnParam вы несколько раз getParamEx дёргаете для разных параметров? И потом их объединяете в таблицу или строку и кидаете дальше в вашу функцию записи?... если так, то сдаётся мне вы оба (вы и ваш коллега с соседней темы «») встретились, собратья по несчастью... с одной и той же проблемой...
Покажите, что вы делаете в OnParam, и как у вас идёт вызов вашей функции rec_big_data...
Пользователь
Сообщений: Регистрация: 29.03.2017
17.05.2018 00:00:51
Suntor, эта проблема появилась только сейчас, когда я перестал делать flush на каждой записи. До этого я несколько недель подряд записывал каждый день без перерыва и такой проблемы не было. Она абсолютно новая. Вызываю я функцию так:
При таком вызове рваться не должно... у вас какая-то серьёзная проблема с вводом/выводом. Возможно дело даже не в Lua, а в вашей виртуальной машине, настройках виртуального диска и пр.
Попробуйте отключиться кэш совсем, через :
Код
function rec_big_data(file_path, value, paper)
rn = rn or {}
rn[paper] = rn[paper] or {}
if file_path~=rn[paper].file_path then
if rn[paper].handler then
rn[paper].handler:close()
end
rn[paper].handler = io.open(file_path, "a+")
if rn[paper].handler then
rn[paper].handler:setvbuf("no") --<<<--- отключение кэша
rn[paper].file_path = file_path
else
mm("QL:open file error "..file_path)
end
end
if rn[paper].handler then
rn[paper].handler:write(value.."\n")
end
end
а в другой день, наоборот, увеличьте его до 1 МиБ, заодно сравните скорость работы, и посмотрите, будут ли глюки и при каком режиме кэширования:
Код
rn[paper].handler:setvbuf("full", 1024*1024)
Пользователь
Сообщений: Регистрация: 31.01.2015
17.05.2018 06:37:06
Есть гипотеза для объяснения проблем с "битыми" строчками: вы пишете в один физический файл, используя несколько разных дескрипторов на уровне lua.
Код
local f1 = io.open("filename.txt", "a+")
local f2 = io.open("filename.txt", "a+")
f1:write("Some text")
f2:write("Another text")
f1:close()
f2:close()