-- -- gcsd -- -- gcsd the generic command sequencer daemon can be used to serialize -- commands sent over various paralell communication channels to a -- single command output. It can be seen as a multiplexer for any -- kind of communication between a single resource and various clients -- which want to submit commands to it or query information from it. -- gcsd is written in C and Lua. The goal is to provide an easy to -- understand high level API based on Lua which can be used to -- implement the business logic of the so formed multiplexer daemon. -- -- -- Copyright (C) 2009-2010 Markus Grueneis -- Christian Pointner -- -- This file is part of gcsd. -- -- gcsd is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- any later version. -- -- gcsd is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with gcsd. If not, see . -- local defines = require("defines") module_list = {} module_list.classes = {} local mt = {} function mt.__index(table, key) local value = rawget(table, key) if(value ~= nil) then return value end log.printf(log.DEBUG, "load module class: %s", key) local old_path = package.path package.path = package.path .. ";./modules/?.lua" value = require(key) package.path = old_path rawset(table, key, value) return value end setmetatable(module_list.classes, mt) module_list.inputs = {} module_list.output = nil function module_list:init(opt) local class, config = self:parse_config(opt.cmd_out) if(not class) then return defines.KILL_DAEMON end if(self.classes[class].properties.type ~= defines.OUT_MODULE and self.classes[class].properties.type ~= defines.INOUT_MODULE) then log.printf(log.ERROR, "module class '%s' cannot be used as output module", class); return defines.KILL_DAEMON end log.printf(log.DEBUG, "output module class='%s'", class) for k, v in pairs(config) do log.printf(log.DEBUG, " config['%s'] = '%s'", k, v) end self.output = self.classes[class]:new(config, defines.OUT_MODULE) for idx, input in ipairs(opt.cmd_ins) do local class, config = self:parse_config(input) if(not class) then return defines.KILL_DAEMON end if(self.classes[class].properties.type ~= defines.IN_MODULE and self.classes[class].properties.type ~= defines.INOUT_MODULE and self.classes[class].properties.type ~= defines.MISC_MODULE) then log.printf(log.ERROR, "module class '%s' cannot be used as input module", class); return defines.KILL_DAEMON end log.printf(log.DEBUG, "input[%d] module class='%s'", idx, class) for k, v in pairs(config) do log.printf(log.DEBUG, " config['%s'] = '%s'", k, v) end table.insert(self.inputs, self.classes[class]:new(config, defines.IN_MODULE)) end return defines.OK end function module_list:parse_config(module_config) local class, config_string = string.match(module_config, "^([%w-_]+):(.+)$") if(not class or not config_string) then log.printf(log.ERROR, "module config format error: '%s'", module_config) return nil end local config = {} for k, v in string.gmatch(config_string .. ",", "([^,=]+)=([^,=]+),") do config[k] = v end return class, config end function module_list:unregister(module) if(module == self.output) then log.printf(log.WARNING, "won't remove output module: " .. module.name) return end for i, m in ipairs(self.inputs) do if(m == module) then log.printf(log.INFO, "removing input module: " .. module.name) module:cleanup() table.remove(self.inputs, i) break end end end function module_list:unregister_by_class(class) local free_list = {} for i, m in ipairs(self.inputs) do if(m.class == class) then table.insert(free_list, 1, i) end end for _, i in ipairs(free_list) do log.printf(log.INFO, "removing input module: " .. self.inputs[i].name) self.inputs[i]:cleanup() table.remove(self.inputs, i) end end function module_list:cleanup() for _, module in ipairs(self.inputs) do log.printf(log.INFO, "removing input module: " .. module.name) module:cleanup() end if(self.output ~= nil) then log.printf(log.INFO, "removing output module: " .. self.output.name) self.output:cleanup() end self.inputs = {} end