Diff

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
line wrap: on
line diff
--- a/core/modulemanager.lua	Sat Jan 03 18:44:39 2009 +0500
+++ b/core/modulemanager.lua	Sat Jan 03 18:45:51 2009 +0500
@@ -34,6 +34,7 @@
 local pairs, ipairs = pairs, ipairs;
 local t_insert = table.insert;
 local type = type;
+local next = next;
 
 local tostring, print = tostring, print;
 
@@ -51,6 +52,10 @@
 
 local modulehelpers = setmetatable({}, { __index = _G });
 
+local features_table = multitable_new();
+local handler_table = multitable_new();
+local NULL = {};
+
 -- Load modules when a host is activated
 function load_modules_for_host(host)
 	-- Load modules from global section
@@ -116,7 +121,7 @@
 	end
 	
 	-- Use modified host, if the module set one
-	modulemap[api_instance.host][module_name] = mod;
+	modulemap[api_instance.host][module_name] = pluginenv;
 	
 	return true;
 end
@@ -129,13 +134,21 @@
 	local mod = modulemap[host] and modulemap[host][name];
 	if not mod then return nil, "module-not-loaded"; end
 	
-	if type(mod.unload) == "function" then
+	--[[if type(mod.unload) == "function" then
 		local ok, err = pcall(mod.unload, ...)
 		if (not ok) and err then
 			log("warn", "Non-fatal error unloading module '%s' from '%s': %s", name, host, err);
 		end
+	end]]
+	modulemap[host][name] = nil;
+	features_table:remove(host, name);
+	local params = handler_table:get(host, name); -- , {module.host, origin_type, tag, xmlns}
+	for _, param in pairs(params) do
+		local handlers = stanza_handlers:get(param[1], param[2], param[3], param[4]);
+		handler_info[handlers[1]] = nil;
+		stanza_handlers:remove(param[1], param[2], param[3], param[4]);
 	end
-	
+	return true;
 end
 
 function handle_stanza(host, origin, stanza)
@@ -178,6 +191,7 @@
 	if not handlers then
 		stanza_handlers:add(module.host, origin_type, tag, xmlns, handler);
 		handler_info[handler] = module;
+		handler_table:add(module.host, module.name, {module.host, origin_type, tag, xmlns});
 		module:log("debug", "I now handle tag '%s' [%s] with %s '%s'", tag, origin_type, msg, xmlns);
 	else
 		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);
@@ -198,13 +212,23 @@
 	self:add_handler(origin_type, "iq", xmlns, handler);
 end
 
+addDiscoInfoHandler("*host", function(reply, to, from, node)
+	if #node == 0 then
+		local done = {};
+		for module, features in pairs(features_table:get(to) or NULL) do -- for each module
+			for feature in pairs(features) do
+				if not done[feature] then
+					reply:tag("feature", {var = feature}):up(); -- TODO cache
+					done[feature] = true;
+				end
+			end
+		end
+		return next(done) ~= nil;
+	end
+end);
+
 function api:add_feature(xmlns)
-	addDiscoInfoHandler(self.host, function(reply, to, from, node)
-		if #node == 0 then
-			reply:tag("feature", {var = xmlns}):up();
-			return true;
-		end
-	end);
+	features_table:set(self.host, self.name, xmlns, true);
 end
 
 function api:add_event_hook (...) return eventmanager.add_event_hook(...); end