Comparison

core/modulemanager.lua @ 745:5a343599cd3e

core.modulemanager: Some refactoring to make upcoming changes a little easier
author Matthew Wild <mwild1@gmail.com>
date Sat, 24 Jan 2009 01:15:40 +0000
parent 733:b1aedec00661
child 746:7027de4c039d
comparison
equal deleted inserted replaced
744:328b702fb80c 745:5a343599cd3e
30 local register_actions = require "core.actions".register; 30 local register_actions = require "core.actions".register;
31 31
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, t_concat = table.insert, table.concat;
36 local type = type; 36 local type = type;
37 local next = next; 37 local next = next;
38 local rawget = rawget; 38 local rawget = rawget;
39 39
40 local tostring, print = tostring, print; 40 local tostring, print = tostring, print;
105 elseif modulemap["*"][module_name] then 105 elseif modulemap["*"][module_name] then
106 return nil, "global-module-already-loaded"; 106 return nil, "global-module-already-loaded";
107 end 107 end
108 108
109 109
110 local mod, err = loadfile(plugin_dir.."mod_"..module_name..".lua"); 110 local mod, err = loadfile(get_module_filename(module_name));
111 if not mod then 111 if not mod then
112 log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil"); 112 log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil");
113 return nil, err; 113 return nil, err;
114 end 114 end
115 115
130 modulemap[api_instance.host][module_name] = pluginenv; 130 modulemap[api_instance.host][module_name] = pluginenv;
131 131
132 return true; 132 return true;
133 end 133 end
134 134
135 function get_module(host, name)
136 return modulemap[host] and modulemap[host][name];
137 end
138
135 function is_loaded(host, name) 139 function is_loaded(host, name)
136 return modulemap[host] and modulemap[host][name] and true; 140 return modulemap[host] and modulemap[host][name] and true;
137 end 141 end
138 142
139 function unload(host, name, ...) 143 function unload(host, name, ...)
140 local mod = modulemap[host] and modulemap[host][name]; 144 local mod = get_module(host, name);
141 if not mod then return nil, "module-not-loaded"; end 145 if not mod then return nil, "module-not-loaded"; end
142 146
143 if type(mod.module.unload) == "function" then 147 if module_has_method(mod, "unload") then
144 local ok, err = pcall(mod.module.unload, ...) 148 local ok, err = call_module_method(mod, "unload");
145 if (not ok) and err then 149 if (not ok) and err then
146 log("warn", "Non-fatal error unloading module '%s' from '%s': %s", name, host, err); 150 log("warn", "Non-fatal error unloading module '%s' on '%s': %s", name, host, err);
147 end 151 end
148 end 152 end
149 modulemap[host][name] = nil; 153 modulemap[host][name] = nil;
150 features_table:remove(host, name); 154 features_table:remove(host, name);
151 local params = handler_table:get(host, name); -- , {module.host, origin_type, tag, xmlns} 155 local params = handler_table:get(host, name); -- , {module.host, origin_type, tag, xmlns}
159 event_hooks:remove(host, name); 163 event_hooks:remove(host, name);
160 return true; 164 return true;
161 end 165 end
162 166
163 function reload(host, name, ...) 167 function reload(host, name, ...)
164 local mod = modulemap[host] and modulemap[host][name]; 168 local mod = get_module(host, name);
165 if not mod then return nil, "module-not-loaded"; end 169 if not mod then return nil, "module-not-loaded"; end
166 170
167 local _mod, err = loadfile(plugin_dir.."mod_"..name..".lua"); -- checking for syntax errors 171 local _mod, err = loadfile(get_module_filename(name)); -- checking for syntax errors
168 if not _mod then 172 if not _mod then
169 log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil"); 173 log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil");
170 return nil, err; 174 return nil, err;
171 end 175 end
172 176
173 local saved; 177 local saved;
174 if type(mod.module.save) == "function" then 178
175 local ok, err = pcall(mod.module.save) 179 if module_has_method(mod, "save") then
176 if (not ok) and err then 180 local ok, ret, err = call_module_method(mod, "save");
177 log("warn", "Non-fatal error unloading module '%s' from '%s': %s", name, host, err); 181 if ok then
182 saved = ret;
178 else 183 else
179 saved = err; 184 log("warn", "Error saving module '%s:%s' state: %s", host, module, ret);
185 if not config.get(host, "core", "force_module_reload") then
186 log("warn", "Aborting reload due to error, set force_module_reload to ignore this");
187 return nil, "save-state-failed";
188 else
189 log("warn", "Continuing with reload (using the force)");
190 end
180 end 191 end
181 end 192 end
182 193
183 unload(host, name, ...); 194 unload(host, name, ...);
184 if load(host, name, ...) then 195 local ok, err = load(host, name, ...);
185 mod = modulemap[host] and modulemap[host][name]; 196 if ok then
186 if type(mod.module.restore) == "function" then 197 mod = get_module(host, name);
187 local ok, err = pcall(mod.module.restore, saved or {}) 198 if module_has_method(mod, "restore") then
199 local ok, err = call_module_method(mod, "restore", saved or {})
188 if (not ok) and err then 200 if (not ok) and err then
189 log("warn", "Non-fatal error unloading module '%s' from '%s': %s", name, host, err); 201 log("warn", "Error restoring module '%s' from '%s': %s", name, host, err);
190 end 202 end
191 end 203 end
192 return true; 204 return true;
193 end 205 end
206 return ok, err;
194 end 207 end
195 208
196 function handle_stanza(host, origin, stanza) 209 function handle_stanza(host, origin, stanza)
197 local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type; 210 local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type;
198 if name == "iq" and xmlns == "jabber:client" then 211 if name == "iq" and xmlns == "jabber:client" then
210 (handlers[1])(origin, stanza); 223 (handlers[1])(origin, stanza);
211 return true; 224 return true;
212 else 225 else
213 log("debug", "Stanza unhandled by any modules, xmlns: %s", stanza.attr.xmlns); -- we didn't handle it 226 log("debug", "Stanza unhandled by any modules, xmlns: %s", stanza.attr.xmlns); -- we didn't handle it
214 end 227 end
228 end
229
230 function module_has_method(module, method)
231 return type(module.module[method]) == "function";
232 end
233
234 function call_module_method(module, func, ...)
235 local f = module.module[func];
236 if module_has_method(module, method) then
237 return pcall(f, ...);
238 else
239 return false, "no-such-method";
240 end
241 end
242
243 local _modulepath = { plugin_dir, "mod_", nil, ".lua"};
244 function get_module_filename(name)
245 _modulepath[3] = name;
246 return t_concat(_modulepath);
215 end 247 end
216 248
217 ----- API functions exposed to modules ----------- 249 ----- API functions exposed to modules -----------
218 -- Must all be in api.* 250 -- Must all be in api.*
219 251