diff --git a/rtu/startup.lua b/rtu/startup.lua index 174d400..413290b 100644 --- a/rtu/startup.lua +++ b/rtu/startup.lua @@ -31,7 +31,7 @@ local sna_rtu = require("rtu.dev.sna_rtu") local sps_rtu = require("rtu.dev.sps_rtu") local turbinev_rtu = require("rtu.dev.turbinev_rtu") -local RTU_VERSION = "v1.10.19" +local RTU_VERSION = "v1.10.20" local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_HW_STATE = databus.RTU_HW_STATE @@ -338,8 +338,8 @@ local function main() formed = device.isFormed() if formed == ppm.ACCESS_FAULT then - println_ts(util.c("sys_config> failed to check if '", name, "' is formed")) - log.warning(util.c("sys_config> failed to check if '", name, "' is a formed boiler multiblock")) + println_ts(util.c("sys_config> failed to check if '", name, "' is formed")) + log.warning(util.c("sys_config> failed to check if '", name, "' is a formed boiler multiblock")) end elseif type == "turbineValve" then -- turbine multiblock @@ -352,8 +352,8 @@ local function main() formed = device.isFormed() if formed == ppm.ACCESS_FAULT then - println_ts(util.c("sys_config> failed to check if '", name, "' is formed")) - log.warning(util.c("sys_config> failed to check if '", name, "' is a formed turbine multiblock")) + println_ts(util.c("sys_config> failed to check if '", name, "' is formed")) + log.warning(util.c("sys_config> failed to check if '", name, "' is a formed turbine multiblock")) end elseif type == "dynamicValve" then -- dynamic tank multiblock @@ -371,8 +371,8 @@ local function main() formed = device.isFormed() if formed == ppm.ACCESS_FAULT then - println_ts(util.c("sys_config> failed to check if '", name, "' is formed")) - log.warning(util.c("sys_config> failed to check if '", name, "' is a formed dynamic tank multiblock")) + println_ts(util.c("sys_config> failed to check if '", name, "' is formed")) + log.warning(util.c("sys_config> failed to check if '", name, "' is a formed dynamic tank multiblock")) end elseif type == "inductionPort" then -- induction matrix multiblock @@ -384,8 +384,8 @@ local function main() formed = device.isFormed() if formed == ppm.ACCESS_FAULT then - println_ts(util.c("sys_config> failed to check if '", name, "' is formed")) - log.warning(util.c("sys_config> failed to check if '", name, "' is a formed induction matrix multiblock")) + println_ts(util.c("sys_config> failed to check if '", name, "' is formed")) + log.warning(util.c("sys_config> failed to check if '", name, "' is a formed induction matrix multiblock")) end elseif type == "spsPort" then -- SPS multiblock @@ -397,8 +397,8 @@ local function main() formed = device.isFormed() if formed == ppm.ACCESS_FAULT then - println_ts(util.c("sys_config> failed to check if '", name, "' is formed")) - log.warning(util.c("sys_config> failed to check if '", name, "' is a formed SPS multiblock")) + println_ts(util.c("sys_config> failed to check if '", name, "' is formed")) + log.warning(util.c("sys_config> failed to check if '", name, "' is a formed SPS multiblock")) end elseif type == "solarNeutronActivator" then -- SNA @@ -428,7 +428,7 @@ local function main() if not formed then if formed == false then log.info(util.c("sys_config> device '", name, "' is not formed")) - end + else formed = false end elseif faulted then -- sometimes there is a race condition on server boot where it reports formed, but -- the other functions are not yet defined (that's the theory at least). mark as unformed to attempt connection later @@ -458,7 +458,7 @@ local function main() table.insert(units, rtu_unit) - local for_message = "facility" + local for_message = "the facility" if for_reactor > 0 then for_message = util.c("reactor ", for_reactor) end diff --git a/rtu/threads.lua b/rtu/threads.lua index 7ecd6f3..e1d8c6c 100644 --- a/rtu/threads.lua +++ b/rtu/threads.lua @@ -486,7 +486,9 @@ function threads.thread__unit_comms(smem, unit) local last_f_check = 0 - local detail_name = util.c(types.rtu_type_to_string(unit.type), " (", unit.name, ") [", unit.index, "] for reactor ", unit.reactor) + local detail_name = util.c(types.rtu_type_to_string(unit.type), " (", unit.name, ") ", + util.trinary(unit.index == false, "", util.c("[", unit.index, "] ")), "for ", + util.trinary(unit.reactor == 0, "the facility", util.c("reactor ", unit.reactor))) local short_name = util.c(types.rtu_type_to_string(unit.type), " (", unit.name, ")") if packet_queue == nil then diff --git a/scada-common/log.lua b/scada-common/log.lua index 49f4c5e..8ebc987 100644 --- a/scada-common/log.lua +++ b/scada-common/log.lua @@ -8,6 +8,10 @@ local util = require("scada-common.util") local DBG_TAG, INF_TAG, WRN_TAG, ERR_TAG, FTL_TAG = "[DBG] ", "[INF] ", "[WRN] ", "[ERR] ", "[FTL] " local COLON, FUNC, ARROW = ":", "():", " > " +local MIN_SPACE = 512 +local OUT_OF_SPACE = "Out of space" +local TIME_FMT = "%F %T " + ---@class logger local log = {} @@ -34,14 +38,20 @@ local free_space = fs.getFreeSpace -- PRIVATE FUNCTIONS -- ----------------------- +-- check if the provided error indicates out of space or if insufficient space available +---@param err_msg string|nil error message +---@return boolean out_of_space +local function check_out_of_space(err_msg) + return (free_space(logger.path) < MIN_SPACE) or ((err_msg ~= nil) and (string.find(err_msg, OUT_OF_SPACE) ~= nil)) +end + -- private log write function ---@param msg_bits any[] local function _log(msg_bits) if logger.not_ready then return end - local out_of_space = false - local time_stamp = os.date("[%c] ") - local stamped = util.c(time_stamp, table.unpack(msg_bits)) + local time_stamp = os.date(TIME_FMT) + local stamped = util.c(time_stamp, table.unpack(msg_bits)) -- attempt to write log local status, result = pcall(function () @@ -50,18 +60,7 @@ local function _log(msg_bits) end) -- if we don't have space, we need to create a new log file - - if (not status) and (result ~= nil) then - out_of_space = string.find(result, "Out of space") ~= nil - - if out_of_space then - -- will delete log file - else - util.println("unknown error writing to logfile: " .. result) - end - end - - if out_of_space or (free_space(logger.path) < 512) then + if check_out_of_space() then -- delete the old log file before opening a new one logger.file.close() fs.delete(logger.path) @@ -69,10 +68,12 @@ local function _log(msg_bits) -- re-init logger and pass dmesg_out so that it doesn't change log.init(logger.path, logger.mode, logger.debug, logger.dmesg_out) - -- leave a message - logger.file.writeLine(time_stamp .. "recycled log file") + -- log the message and recycle warning + logger.file.writeLine(time_stamp .. WRN_TAG .. "recycled log file") logger.file.writeLine(stamped) logger.file.flush() + elseif (not status) and (result ~= nil) then + util.println("unexpected error writing to the log file: " .. result) end end @@ -86,15 +87,12 @@ end ---@param include_debug boolean whether or not to include debug logs ---@param dmesg_redirect? Redirect terminal/window to direct dmesg to function log.init(path, write_mode, include_debug, dmesg_redirect) + local err_msg + logger.path = path logger.mode = write_mode logger.debug = include_debug - - if logger.mode == MODE.APPEND then - logger.file = fs.open(path, "a") - else - logger.file = fs.open(path, "w") - end + logger.file, err_msg = fs.open(path, util.trinary(logger.mode == MODE.APPEND, "a", "w")) if dmesg_redirect then logger.dmesg_out = dmesg_redirect @@ -102,6 +100,25 @@ function log.init(path, write_mode, include_debug, dmesg_redirect) logger.dmesg_out = term.current() end + -- check for space issues + local out_of_space = check_out_of_space(err_msg) + + -- try to handle problems + if logger.file == nil or out_of_space then + if out_of_space then + if fs.exists(logger.path) then + fs.delete(logger.path) + + logger.file, err_msg = fs.open(path, util.trinary(logger.mode == MODE.APPEND, "a", "w")) + + if logger.file then + logger.file.writeLine(os.date(TIME_FMT) .. WRN_TAG .. "init recycled log file") + logger.file.flush() + else error("failed to setup the log file: " .. err_msg) end + else error("failed to make space for the log file, please delete unused files") end + else error("unexpected error setting up the log file: " .. err_msg) end + end + logger.not_ready = false end diff --git a/scada-common/util.lua b/scada-common/util.lua index 96c1ec8..40a9fe3 100644 --- a/scada-common/util.lua +++ b/scada-common/util.lua @@ -24,7 +24,7 @@ local t_pack = table.pack local util = {} -- scada-common version -util.version = "1.4.8" +util.version = "1.4.10" util.TICK_TIME_S = 0.05 util.TICK_TIME_MS = 50