Software / code / prosody
Comparison
core/modulemanager.lua @ 670:d5cf10b7fc44
Modulemanager: Basic modules can now be unloaded correctly
| author | Waqas Hussain <waqas20@gmail.com> |
|---|---|
| date | Sat, 03 Jan 2009 18:45:51 +0500 |
| parent | 637:30b8ad9f7b70 |
| child | 672:7db1044d2fab |
| child | 674:4f506c627b49 |
comparison
equal
deleted
inserted
replaced
| 669:9255abbb3068 | 670:d5cf10b7fc44 |
|---|---|
| 32 local loadfile, pcall = loadfile, pcall; | 32 local loadfile, pcall = loadfile, pcall; |
| 33 local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; | 33 local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; |
| 34 local pairs, ipairs = pairs, ipairs; | 34 local pairs, ipairs = pairs, ipairs; |
| 35 local t_insert = table.insert; | 35 local t_insert = table.insert; |
| 36 local type = type; | 36 local type = type; |
| 37 local next = next; | |
| 37 | 38 |
| 38 local tostring, print = tostring, print; | 39 local tostring, print = tostring, print; |
| 39 | 40 |
| 40 -- We need this to let modules access the real global namespace | 41 -- We need this to let modules access the real global namespace |
| 41 local _G = _G; | 42 local _G = _G; |
| 48 | 49 |
| 49 local stanza_handlers = multitable_new(); | 50 local stanza_handlers = multitable_new(); |
| 50 local handler_info = {}; | 51 local handler_info = {}; |
| 51 | 52 |
| 52 local modulehelpers = setmetatable({}, { __index = _G }); | 53 local modulehelpers = setmetatable({}, { __index = _G }); |
| 54 | |
| 55 local features_table = multitable_new(); | |
| 56 local handler_table = multitable_new(); | |
| 57 local NULL = {}; | |
| 53 | 58 |
| 54 -- Load modules when a host is activated | 59 -- Load modules when a host is activated |
| 55 function load_modules_for_host(host) | 60 function load_modules_for_host(host) |
| 56 -- Load modules from global section | 61 -- Load modules from global section |
| 57 local modules_enabled = config.get("*", "core", "modules_enabled"); | 62 local modules_enabled = config.get("*", "core", "modules_enabled"); |
| 114 log("error", "Error initialising module '%s': %s", name or "nil", ret or "nil"); | 119 log("error", "Error initialising module '%s': %s", name or "nil", ret or "nil"); |
| 115 return nil, ret; | 120 return nil, ret; |
| 116 end | 121 end |
| 117 | 122 |
| 118 -- Use modified host, if the module set one | 123 -- Use modified host, if the module set one |
| 119 modulemap[api_instance.host][module_name] = mod; | 124 modulemap[api_instance.host][module_name] = pluginenv; |
| 120 | 125 |
| 121 return true; | 126 return true; |
| 122 end | 127 end |
| 123 | 128 |
| 124 function is_loaded(host, name) | 129 function is_loaded(host, name) |
| 127 | 132 |
| 128 function unload(host, name, ...) | 133 function unload(host, name, ...) |
| 129 local mod = modulemap[host] and modulemap[host][name]; | 134 local mod = modulemap[host] and modulemap[host][name]; |
| 130 if not mod then return nil, "module-not-loaded"; end | 135 if not mod then return nil, "module-not-loaded"; end |
| 131 | 136 |
| 132 if type(mod.unload) == "function" then | 137 --[[if type(mod.unload) == "function" then |
| 133 local ok, err = pcall(mod.unload, ...) | 138 local ok, err = pcall(mod.unload, ...) |
| 134 if (not ok) and err then | 139 if (not ok) and err then |
| 135 log("warn", "Non-fatal error unloading module '%s' from '%s': %s", name, host, err); | 140 log("warn", "Non-fatal error unloading module '%s' from '%s': %s", name, host, err); |
| 136 end | 141 end |
| 137 end | 142 end]] |
| 138 | 143 modulemap[host][name] = nil; |
| 144 features_table:remove(host, name); | |
| 145 local params = handler_table:get(host, name); -- , {module.host, origin_type, tag, xmlns} | |
| 146 for _, param in pairs(params) do | |
| 147 local handlers = stanza_handlers:get(param[1], param[2], param[3], param[4]); | |
| 148 handler_info[handlers[1]] = nil; | |
| 149 stanza_handlers:remove(param[1], param[2], param[3], param[4]); | |
| 150 end | |
| 151 return true; | |
| 139 end | 152 end |
| 140 | 153 |
| 141 function handle_stanza(host, origin, stanza) | 154 function handle_stanza(host, origin, stanza) |
| 142 local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type; | 155 local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type; |
| 143 if name == "iq" and xmlns == "jabber:client" then | 156 if name == "iq" and xmlns == "jabber:client" then |
| 176 local handlers = stanza_handlers:get(module.host, origin_type, tag, xmlns); | 189 local handlers = stanza_handlers:get(module.host, origin_type, tag, xmlns); |
| 177 local msg = (tag == "iq") and "namespace" or "payload namespace"; | 190 local msg = (tag == "iq") and "namespace" or "payload namespace"; |
| 178 if not handlers then | 191 if not handlers then |
| 179 stanza_handlers:add(module.host, origin_type, tag, xmlns, handler); | 192 stanza_handlers:add(module.host, origin_type, tag, xmlns, handler); |
| 180 handler_info[handler] = module; | 193 handler_info[handler] = module; |
| 194 handler_table:add(module.host, module.name, {module.host, origin_type, tag, xmlns}); | |
| 181 module:log("debug", "I now handle tag '%s' [%s] with %s '%s'", tag, origin_type, msg, xmlns); | 195 module:log("debug", "I now handle tag '%s' [%s] with %s '%s'", tag, origin_type, msg, xmlns); |
| 182 else | 196 else |
| 183 module:log("warn", "I wanted to handle tag '%s' [%s] with %s '%s' but mod_%s already handles that", tag, origin_type, msg, xmlns, handler_info[handlers[1]].module.name); | 197 module:log("warn", "I wanted to handle tag '%s' [%s] with %s '%s' but mod_%s already handles that", tag, origin_type, msg, xmlns, handler_info[handlers[1]].module.name); |
| 184 end | 198 end |
| 185 end | 199 end |
| 196 end | 210 end |
| 197 function api:add_iq_handler(origin_type, xmlns, handler) | 211 function api:add_iq_handler(origin_type, xmlns, handler) |
| 198 self:add_handler(origin_type, "iq", xmlns, handler); | 212 self:add_handler(origin_type, "iq", xmlns, handler); |
| 199 end | 213 end |
| 200 | 214 |
| 215 addDiscoInfoHandler("*host", function(reply, to, from, node) | |
| 216 if #node == 0 then | |
| 217 local done = {}; | |
| 218 for module, features in pairs(features_table:get(to) or NULL) do -- for each module | |
| 219 for feature in pairs(features) do | |
| 220 if not done[feature] then | |
| 221 reply:tag("feature", {var = feature}):up(); -- TODO cache | |
| 222 done[feature] = true; | |
| 223 end | |
| 224 end | |
| 225 end | |
| 226 return next(done) ~= nil; | |
| 227 end | |
| 228 end); | |
| 229 | |
| 201 function api:add_feature(xmlns) | 230 function api:add_feature(xmlns) |
| 202 addDiscoInfoHandler(self.host, function(reply, to, from, node) | 231 features_table:set(self.host, self.name, xmlns, true); |
| 203 if #node == 0 then | |
| 204 reply:tag("feature", {var = xmlns}):up(); | |
| 205 return true; | |
| 206 end | |
| 207 end); | |
| 208 end | 232 end |
| 209 | 233 |
| 210 function api:add_event_hook (...) return eventmanager.add_event_hook(...); end | 234 function api:add_event_hook (...) return eventmanager.add_event_hook(...); end |
| 211 | 235 |
| 212 -------------------------------------------------------------------- | 236 -------------------------------------------------------------------- |