diff options
-rw-r--r-- | include/modules/reload.h | 80 | ||||
-rw-r--r-- | src/coremods/core_reloadmodule.cpp | 34 |
2 files changed, 112 insertions, 2 deletions
diff --git a/include/modules/reload.h b/include/modules/reload.h new file mode 100644 index 000000000..6ee30c45e --- /dev/null +++ b/include/modules/reload.h @@ -0,0 +1,80 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +#include "event.h" + +namespace ReloadModule +{ + class EventListener; + class DataKeeper; + + /** Container for data saved by modules before another module is reloaded. + */ + class CustomData + { + struct Data + { + EventListener* handler; + void* data; + Data(EventListener* Handler, void* moddata) : handler(Handler), data(moddata) { } + }; + typedef std::vector<Data> List; + List list; + + public: + /** Add data to the saved state of a module. + * The provided handler's OnReloadModuleRestore() method will be called when the reload is done with the pointer + * provided. + * @param handler Handler for restoring the data + * @param data Pointer to the data, will be passed back to the provided handler's OnReloadModuleRestore() after the + * reload finishes + */ + void add(EventListener* handler, void* data) + { + list.push_back(Data(handler, data)); + } + + friend class DataKeeper; + }; + + class EventListener : public Events::ModuleEventListener + { + public: + EventListener(Module* mod) + : ModuleEventListener(mod, "event/reloadmodule") + { + } + + /** Called whenever a module is about to be reloaded. Use this event to save data related to the module that you want + * to be restored after the reload. + * @param mod Module to be reloaded + * @param cd CustomData instance that can store your data once. + */ + virtual void OnReloadModuleSave(Module* mod, CustomData& cd) = 0; + + /** Restore data after a reload. Only called if data was added in OnReloadModuleSave(). + * @param mod Reloaded module + * @param data Pointer that was passed to CustomData::add() in OnReloadModuleSave() at the time when the module's state + * was saved + */ + virtual void OnReloadModuleRestore(Module* mod, void* data) = 0; + }; +} diff --git a/src/coremods/core_reloadmodule.cpp b/src/coremods/core_reloadmodule.cpp index fd99a5f7e..755b49abf 100644 --- a/src/coremods/core_reloadmodule.cpp +++ b/src/coremods/core_reloadmodule.cpp @@ -21,13 +21,25 @@ #include "inspircd.h" #include "listmode.h" +#include "modules/reload.h" + +static Events::ModuleEventProvider* reloadevprov; class CommandReloadmodule : public Command { + Events::ModuleEventProvider evprov; public: /** Constructor for reloadmodule. */ - CommandReloadmodule ( Module* parent) : Command( parent, "RELOADMODULE",1) { flags_needed = 'o'; syntax = "<modulename>"; } + CommandReloadmodule(Module* parent) + : Command(parent, "RELOADMODULE", 1) + , evprov(parent, "event/reloadmodule") + { + reloadevprov = &evprov; + flags_needed = 'o'; + syntax = "<modulename>"; + } + /** Handle command. * @param parameters The parameters to the command * @param user The user issuing the command @@ -153,6 +165,10 @@ class DataKeeper */ std::vector<ChanData> chandatalist; + /** Data attached by modules + */ + ReloadModule::CustomData moddata; + void SaveExtensions(Extensible* extensible, std::vector<InstanceData>& extdatalist); void SaveMemberData(Channel* chan, std::vector<ChanData::MemberData>& memberdatalist); static void SaveListModes(Channel* chan, ListModeBase* lm, size_t index, ModesExts& currdata); @@ -172,6 +188,7 @@ class DataKeeper void DoRestoreUsers(); void DoRestoreChans(); + void DoRestoreModules(); /** Restore previously saved modes and extensions on an Extensible. * The extensions are set directly on the extensible, the modes are added into the provided mode change list. @@ -399,7 +416,9 @@ void DataKeeper::Save(Module* currmod) CreateModeList(MODETYPE_CHANNEL); DoSaveChans(); - ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Saved data about %lu users %lu chans", (unsigned long)userdatalist.size(), (unsigned long)chandatalist.size()); + FOREACH_MOD_CUSTOM(*reloadevprov, ReloadModule::EventListener, OnReloadModuleSave, (mod, this->moddata)); + + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Saved data about %lu users %lu chans %lu modules", (unsigned long)userdatalist.size(), (unsigned long)chandatalist.size(), (unsigned long)moddata.list.size()); } void DataKeeper::VerifyServiceProvider(const ProviderInfo& service, const char* type) @@ -444,6 +463,7 @@ void DataKeeper::Restore(Module* newmod) // Restore DoRestoreUsers(); DoRestoreChans(); + DoRestoreModules(); ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Restore finished"); } @@ -520,6 +540,16 @@ void DataKeeper::DoRestoreChans() } } +void DataKeeper::DoRestoreModules() +{ + for (ReloadModule::CustomData::List::iterator i = moddata.list.begin(); i != moddata.list.end(); ++i) + { + ReloadModule::CustomData::Data& data = *i; + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Calling module data handler %p", (void*)data.handler); + data.handler->OnReloadModuleRestore(mod, data.data); + } +} + } // namespace ReloadModule class ReloadAction : public HandlerBase0<void> |