X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodmanager_static.cpp;h=cea40c7a32364e75a807866f7979e6730c88a40c;hb=748b3a0d89e7ecc9a766471b79fb78f63a5ca2bb;hp=e09310a13bf66fde0823082094565e38540baa39;hpb=19487dbebc520450e457472b97d9e7bcd5160c00;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modmanager_static.cpp b/src/modmanager_static.cpp index e09310a13..cea40c7a3 100644 --- a/src/modmanager_static.cpp +++ b/src/modmanager_static.cpp @@ -1,9 +1,33 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009-2010 Daniel De Graaf + * + * This file is part of InspIRCd. InspIRCd 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, version 2. + * + * This program 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 this program. If not, see . + */ + + +#define MODNAME cmd_all + #include "inspircd.h" +#include "exitcodes.h" +#include #ifdef PURE_STATIC +typedef std::map modmap; static std::vector* cmdlist = NULL; -static std::vector* modlist = NULL; +static modmap* modlist = NULL; AllCommandList::AllCommandList(fn cmd) { @@ -15,8 +39,8 @@ AllCommandList::AllCommandList(fn cmd) AllModuleList::AllModuleList(AllModuleList::fn mod, const std::string& Name) : init(mod), name(Name) { if (!modlist) - modlist = new std::vector(); - modlist->push_back(this); + modlist = new modmap(); + modlist->insert(std::make_pair(Name, this)); } class AllModule : public Module @@ -58,45 +82,139 @@ class AllModule : public Module MODULE_INIT(AllModule) -bool ModuleManager::Load(const char* filename) +bool ModuleManager::Load(const std::string& name, bool defer) { - return false; -} + modmap::iterator it = modlist->find(name); + if (it == modlist->end()) + return false; + Module* mod = NULL; + try + { + mod = (*it->second->init)(); + mod->ModuleSourceFile = name; + mod->ModuleDLLManager = NULL; + mod->dying = false; + Modules[name] = mod; + if (defer) + { + ServerInstance->Logs->Log("MODULE", DEFAULT,"New module introduced: %s", name.c_str()); + return true; + } + else + { + mod->init(); + } + } + catch (CoreException& modexcept) + { + if (mod) + DoSafeUnload(mod); + ServerInstance->Logs->Log("MODULE", DEFAULT, "Unable to load " + name + ": " + modexcept.GetReason()); + return false; + } + FOREACH_MOD(I_OnLoadModule,OnLoadModule(mod)); + /* We give every module a chance to re-prioritize when we introduce a new one, + * not just the one thats loading, as the new module could affect the preference + * of others + */ + for(int tries = 0; tries < 20; tries++) + { + prioritizationState = tries > 0 ? PRIO_STATE_LAST : PRIO_STATE_FIRST; + for (std::map::iterator n = Modules.begin(); n != Modules.end(); ++n) + n->second->Prioritize(); -bool ModuleManager::CanUnload(Module* mod) -{ - return false; + if (prioritizationState == PRIO_STATE_LAST) + break; + if (tries == 19) + ServerInstance->Logs->Log("MODULE", DEFAULT, "Hook priority dependency loop detected while loading " + name); + } + + ServerInstance->BuildISupport(); + return true; } -void ModuleManager::DoSafeUnload(Module* mod) -{ +namespace { + struct UnloadAction : public HandlerBase0 + { + Module* const mod; + UnloadAction(Module* m) : mod(m) {} + void Call() + { + ServerInstance->Modules->DoSafeUnload(mod); + ServerInstance->GlobalCulls.Apply(); + ServerInstance->GlobalCulls.AddItem(this); + } + }; + + struct ReloadAction : public HandlerBase0 + { + Module* const mod; + HandlerBase1* const callback; + ReloadAction(Module* m, HandlerBase1* c) + : mod(m), callback(c) {} + void Call() + { + std::string name = mod->ModuleSourceFile; + ServerInstance->Modules->DoSafeUnload(mod); + ServerInstance->GlobalCulls.Apply(); + bool rv = ServerInstance->Modules->Load(name.c_str()); + if (callback) + callback->Call(rv); + ServerInstance->GlobalCulls.AddItem(this); + } + }; } bool ModuleManager::Unload(Module* mod) { - return false; + if (!CanUnload(mod)) + return false; + ServerInstance->AtomicActions.AddAction(new UnloadAction(mod)); + return true; } void ModuleManager::Reload(Module* mod, HandlerBase1* callback) { - callback->Call(false); + if (CanUnload(mod)) + ServerInstance->AtomicActions.AddAction(new ReloadAction(mod, callback)); + else if (callback) + callback->Call(false); } void ModuleManager::LoadAll() { - ModCount = 0; - for(std::vector::iterator i = modlist->begin(); i != modlist->end(); ++i) + Load("cmd_all", true); + Load("cmd_whowas.so", true); + Load("cmd_lusers.so", true); + + ConfigTagList tags = ServerInstance->Config->ConfTags("module"); + for(ConfigIter i = tags.first; i != tags.second; ++i) { - try + ConfigTag* tag = i->second; + std::string name = tag->getString("name"); + std::cout << "[" << con_green << "*" << con_reset << "] Loading module:\t" << con_green << name << con_reset << std::endl; + + if (!this->Load(name, true)) { - Module* c = (*(**i).init)(); - c->ModuleSourceFile = (**i).name; - Modules[(**i).name] = c; - FOREACH_MOD(I_OnLoadModule,OnLoadModule(c)); + ServerInstance->Logs->Log("MODULE", DEFAULT, this->LastError()); + std::cout << std::endl << "[" << con_red << "*" << con_reset << "] " << this->LastError() << std::endl << std::endl; + ServerInstance->Exit(EXIT_STATUS_MODULE); + } + } + + for(std::map::iterator i = Modules.begin(); i != Modules.end(); i++) + { + Module* mod = i->second; + try + { + mod->init(); } catch (CoreException& modexcept) { - ServerInstance->Logs->Log("MODULE", DEFAULT, "Unable to load " + (**i).name + ": " + modexcept.GetReason()); + LastModuleError = "Unable to initialize " + mod->ModuleSourceFile + ": " + modexcept.GetReason(); + ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError); + std::cout << std::endl << "[" << con_red << "*" << con_reset << "] " << LastModuleError << std::endl << std::endl; + ServerInstance->Exit(EXIT_STATUS_MODULE); } } @@ -113,15 +231,11 @@ void ModuleManager::LoadAll() if (prioritizationState == PRIO_STATE_LAST) break; if (tries == 19) + { ServerInstance->Logs->Log("MODULE", DEFAULT, "Hook priority dependency loop detected"); + ServerInstance->Exit(EXIT_STATUS_MODULE); + } } - - ServerInstance->BuildISupport(); -} - -void ModuleManager::UnloadAll() -{ - // TODO don't really need this, who cares if we leak on exit? } #endif