]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/coremods/core_reloadmodule.cpp
383d574bfe3c077798d22c24116532cf36378e91
[user/henk/code/inspircd.git] / src / coremods / core_reloadmodule.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com>
5  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
6  *   Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
7  *
8  * This file is part of InspIRCd.  InspIRCd is free software: you can
9  * redistribute it and/or modify it under the terms of the GNU General Public
10  * License as published by the Free Software Foundation, version 2.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21
22 #include "inspircd.h"
23 #include "listmode.h"
24 #include "modules/reload.h"
25
26 static Events::ModuleEventProvider* reloadevprov;
27 static ClientProtocol::Serializer* dummyserializer;
28
29 class DummySerializer : public ClientProtocol::Serializer
30 {
31         bool Parse(LocalUser* user, const std::string& line, ClientProtocol::ParseOutput& parseoutput) CXX11_OVERRIDE
32         {
33                 return false;
34         }
35
36         ClientProtocol::SerializedMessage Serialize(const ClientProtocol::Message& msg, const ClientProtocol::TagSelection& tagwl) const CXX11_OVERRIDE
37         {
38                 return ClientProtocol::SerializedMessage();
39         }
40
41  public:
42         DummySerializer(Module* mod)
43                 : ClientProtocol::Serializer(mod, "dummy")
44         {
45         }
46 };
47
48 class CommandReloadmodule : public Command
49 {
50         Events::ModuleEventProvider evprov;
51         DummySerializer dummyser;
52
53  public:
54         /** Constructor for reloadmodule.
55          */
56         CommandReloadmodule(Module* parent)
57                 : Command(parent, "RELOADMODULE", 1)
58                 , evprov(parent, "event/reloadmodule")
59                 , dummyser(parent)
60         {
61                 reloadevprov = &evprov;
62                 dummyserializer = &dummyser;
63                 flags_needed = 'o';
64                 syntax = "<modulename>";
65         }
66
67         /** Handle command.
68          * @param parameters The parameters to the command
69          * @param user The user issuing the command
70          * @return A value from CmdResult to indicate command success or failure.
71          */
72         CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE;
73 };
74
75 namespace ReloadModule
76 {
77
78 class DataKeeper
79 {
80         /** Data we save for each mode and extension provided by the module
81          */
82         struct ProviderInfo
83         {
84                 std::string itemname;
85                 union
86                 {
87                         ModeHandler* mh;
88                         ExtensionItem* extitem;
89                         ClientProtocol::Serializer* serializer;
90                 };
91
92                 ProviderInfo(ModeHandler* mode)
93                         : itemname(mode->name)
94                         , mh(mode)
95                 {
96                 }
97
98                 ProviderInfo(ExtensionItem* ei)
99                         : itemname(ei->name)
100                         , extitem(ei)
101                 {
102                 }
103
104                 ProviderInfo(ClientProtocol::Serializer* ser)
105                         : itemname(ser->name)
106                         , serializer(ser)
107                 {
108                 }
109         };
110
111         struct InstanceData
112         {
113                 /** Position of the ModeHandler or ExtensionItem that the serialized data belongs to
114                  */
115                 size_t index;
116
117                 /** Serialized data
118                  */
119                 std::string serialized;
120
121                 InstanceData(size_t Index, const std::string& Serialized)
122                         : index(Index)
123                         , serialized(Serialized)
124                 {
125                 }
126         };
127
128         struct ModesExts
129         {
130                 /** Mode data for the object, one entry per mode set by the module being reloaded
131                  */
132                 std::vector<InstanceData> modelist;
133
134                 /** Extensions for the object, one entry per extension set by the module being reloaded
135                  */
136                 std::vector<InstanceData> extlist;
137
138                 bool empty() const { return ((modelist.empty()) && (extlist.empty())); }
139
140                 void swap(ModesExts& other)
141                 {
142                         modelist.swap(other.modelist);
143                         extlist.swap(other.extlist);
144                 }
145         };
146
147         struct OwnedModesExts : public ModesExts
148         {
149                 /** User uuid or channel name
150                  */
151                 std::string owner;
152
153                 OwnedModesExts(const std::string& Owner)
154                         : owner(Owner)
155                 {
156                 }
157         };
158
159         // Data saved for each channel
160         struct ChanData : public OwnedModesExts
161         {
162                 /** Type of data stored for each member who has any affected modes or extensions set
163                  */
164                 typedef OwnedModesExts MemberData;
165
166                 /** List of data (modes and extensions) about each member
167                  */
168                 std::vector<MemberData> memberdatalist;
169
170                 ChanData(Channel* chan)
171                         : OwnedModesExts(chan->name)
172                 {
173                 }
174         };
175
176         // Data saved for each user
177         struct UserData : public OwnedModesExts
178         {
179                 static const size_t UNUSED_INDEX = (size_t)-1;
180                 size_t serializerindex;
181
182                 UserData(User* user, size_t serializeridx)
183                         : OwnedModesExts(user->uuid)
184                         , serializerindex(serializeridx)
185                 {
186                 }
187         };
188
189         /** Module being reloaded
190          */
191         Module* mod;
192
193         /** Stores all user and channel modes provided by the module
194          */
195         std::vector<ProviderInfo> handledmodes[2];
196
197         /** Stores all extensions provided by the module
198          */
199         std::vector<ProviderInfo> handledexts;
200
201         /** Stores all serializers provided by the module
202          */
203         std::vector<ProviderInfo> handledserializers;
204
205         /** Stores all of the module data related to users
206          */
207         std::vector<UserData> userdatalist;
208
209         /** Stores all of the module data related to channels and memberships
210          */
211         std::vector<ChanData> chandatalist;
212
213         /** Data attached by modules
214          */
215         ReloadModule::CustomData moddata;
216
217         void SaveExtensions(Extensible* extensible, std::vector<InstanceData>& extdatalist);
218         void SaveMemberData(Channel* chan, std::vector<ChanData::MemberData>& memberdatalist);
219         static void SaveListModes(Channel* chan, ListModeBase* lm, size_t index, ModesExts& currdata);
220         size_t SaveSerializer(User* user);
221
222         /** Get the index of a ProviderInfo representing the serializer in the handledserializers list.
223          * If the serializer is not already in the list it is added.
224          * @param serializer Serializer to get an index to.
225          * @return Index of the ProviderInfo representing the serializer.
226          */
227         size_t GetSerializerIndex(ClientProtocol::Serializer* serializer);
228
229         void CreateModeList(ModeType modetype);
230         void DoSaveUsers();
231         void DoSaveChans();
232
233         /** Link previously saved extension names to currently available ExtensionItems
234          */
235         void LinkExtensions();
236
237         /** Link previously saved mode names to currently available ModeHandlers
238          * @param modetype Type of the modes to look for
239          */
240         void LinkModes(ModeType modetype);
241
242         /** Link previously saved serializer names to currently available Serializers
243          */
244         void LinkSerializers();
245
246         void DoRestoreUsers();
247         void DoRestoreChans();
248         void DoRestoreModules();
249
250         /** Restore previously saved modes and extensions on an Extensible.
251          * The extensions are set directly on the extensible, the modes are added into the provided mode change list.
252          * @param data Data to unserialize from
253          * @param extensible Object to restore
254          * @param modetype MODETYPE_USER if the object being restored is a User, MODETYPE_CHANNEL otherwise
255          * (for Channels and Memberships).
256          * @param modechange Mode change to populate with the modes
257          */
258         void RestoreObj(const OwnedModesExts& data, Extensible* extensible, ModeType modetype, Modes::ChangeList& modechange);
259
260         /** Restore all previously saved extensions on an Extensible
261          * @param list List of extensions and their serialized data to restore
262          * @param extensible Target Extensible
263          */
264         void RestoreExtensions(const std::vector<InstanceData>& list, Extensible* extensible);
265
266         /** Restore all previously saved modes on a User, Channel or Membership
267          * @param list List of modes to restore
268          * @param modetype MODETYPE_USER if the object being restored is a User, MODETYPE_CHANNEL otherwise
269          * @param modechange Mode change to populate with the modes
270          */
271         void RestoreModes(const std::vector<InstanceData>& list, ModeType modetype, Modes::ChangeList& modechange);
272
273         /** Restore previously saved serializer on a User.
274          * Quit the user if the serializer cannot be restored.
275          * @param serializerindex Saved serializer index to restore.
276          * @param user User whose serializer to restore. If not local then calling this method is a no-op.
277          * @return True if the serializer didn't need restoring or was restored successfully.
278          * False if the serializer should have been restored but the required serializer is unavailable and the user was quit.
279          */
280         bool RestoreSerializer(size_t serializerindex, User* user);
281
282         /** Restore all modes and extensions of all members on a channel
283          * @param chan Channel whose members are being restored
284          * @param memberdata Data to restore
285          * @param modechange Mode change to populate with prefix modes
286          */
287         void RestoreMemberData(Channel* chan, const std::vector<ChanData::MemberData>& memberdatalist, Modes::ChangeList& modechange);
288
289         /** Verify that a service which had its data saved is available and owned by the module that owned it previously
290          * @param service Service descriptor
291          * @param type Human-readable type of the service for log messages
292          */
293         void VerifyServiceProvider(const ProviderInfo& service, const char* type);
294
295  public:
296         /** Save module state
297          * @param currmod Module whose data to save
298          */
299         void Save(Module* currmod);
300
301         /** Restore module state
302          * @param newmod Newly loaded instance of the module which had its data saved
303          */
304         void Restore(Module* newmod);
305
306         /** Handle reload failure
307          */
308         void Fail();
309 };
310
311 void DataKeeper::DoSaveUsers()
312 {
313         ModesExts currdata;
314
315         const user_hash& users = ServerInstance->Users->GetUsers();
316         for (user_hash::const_iterator i = users.begin(); i != users.end(); ++i)
317         {
318                 User* const user = i->second;
319
320                 // Serialize user modes
321                 for (size_t j = 0; j < handledmodes[MODETYPE_USER].size(); j++)
322                 {
323                         ModeHandler* mh = handledmodes[MODETYPE_USER][j].mh;
324                         if (user->IsModeSet(mh))
325                                 currdata.modelist.push_back(InstanceData(j, mh->GetUserParameter(user)));
326                 }
327
328                 // Serialize all extensions attached to the User
329                 SaveExtensions(user, currdata.extlist);
330
331                 // Save serializer name if applicable and get an index to it
332                 size_t serializerindex = SaveSerializer(user);
333
334                 // Add to list if the user has any modes or extensions set that we are interested in, otherwise we don't
335                 // have to do anything with this user when restoring
336                 if ((!currdata.empty()) || (serializerindex != UserData::UNUSED_INDEX))
337                 {
338                         userdatalist.push_back(UserData(user, serializerindex));
339                         userdatalist.back().swap(currdata);
340                 }
341         }
342 }
343
344 size_t DataKeeper::GetSerializerIndex(ClientProtocol::Serializer* serializer)
345 {
346         for (size_t i = 0; i < handledserializers.size(); i++)
347         {
348                 if (handledserializers[i].serializer == serializer)
349                         return i;
350         }
351
352         handledserializers.push_back(ProviderInfo(serializer));
353         return handledserializers.size()-1;
354 }
355
356 size_t DataKeeper::SaveSerializer(User* user)
357 {
358         LocalUser* const localuser = IS_LOCAL(user);
359         if ((!localuser) || (!localuser->serializer))
360                 return UserData::UNUSED_INDEX;
361         if (localuser->serializer->creator != mod)
362                 return UserData::UNUSED_INDEX;
363
364         const size_t serializerindex = GetSerializerIndex(localuser->serializer);
365         localuser->serializer = dummyserializer;
366         return serializerindex;
367 }
368
369 void DataKeeper::SaveExtensions(Extensible* extensible, std::vector<InstanceData>& extdata)
370 {
371         const Extensible::ExtensibleStore& setexts = extensible->GetExtList();
372
373         // Position of the extension saved in the handledexts list
374         size_t index = 0;
375         for (std::vector<ProviderInfo>::const_iterator i = handledexts.begin(); i != handledexts.end(); ++i, index++)
376         {
377                 ExtensionItem* const item = i->extitem;
378                 Extensible::ExtensibleStore::const_iterator it = setexts.find(item);
379                 if (it == setexts.end())
380                         continue;
381
382                 std::string value = item->serialize(FORMAT_INTERNAL, extensible, it->second);
383                 // If the serialized value is empty the extension won't be saved and restored
384                 if (!value.empty())
385                         extdata.push_back(InstanceData(index, value));
386         }
387 }
388
389 void DataKeeper::SaveListModes(Channel* chan, ListModeBase* lm, size_t index, ModesExts& currdata)
390 {
391         const ListModeBase::ModeList* list = lm->GetList(chan);
392         if (!list)
393                 return;
394
395         for (ListModeBase::ModeList::const_iterator i = list->begin(); i != list->end(); ++i)
396         {
397                 const ListModeBase::ListItem& listitem = *i;
398                 currdata.modelist.push_back(InstanceData(index, listitem.mask));
399         }
400 }
401
402 void DataKeeper::DoSaveChans()
403 {
404         ModesExts currdata;
405         std::vector<OwnedModesExts> currmemberdata;
406
407         const chan_hash& chans = ServerInstance->GetChans();
408         for (chan_hash::const_iterator i = chans.begin(); i != chans.end(); ++i)
409         {
410                 Channel* const chan = i->second;
411
412                 // Serialize channel modes
413                 for (size_t j = 0; j < handledmodes[MODETYPE_CHANNEL].size(); j++)
414                 {
415                         ModeHandler* mh = handledmodes[MODETYPE_CHANNEL][j].mh;
416                         ListModeBase* lm = mh->IsListModeBase();
417                         if (lm)
418                                 SaveListModes(chan, lm, j, currdata);
419                         else if (chan->IsModeSet(mh))
420                                 currdata.modelist.push_back(InstanceData(j, chan->GetModeParameter(mh)));
421                 }
422
423                 // Serialize all extensions attached to the Channel
424                 SaveExtensions(chan, currdata.extlist);
425
426                 // Serialize all extensions attached to and all modes set on all members of the channel
427                 SaveMemberData(chan, currmemberdata);
428
429                 // Same logic as in DoSaveUsers() plus we consider the modes and extensions of all members
430                 if ((!currdata.empty()) || (!currmemberdata.empty()))
431                 {
432                         chandatalist.push_back(ChanData(chan));
433                         chandatalist.back().swap(currdata);
434                         chandatalist.back().memberdatalist.swap(currmemberdata);
435                 }
436         }
437 }
438
439 void DataKeeper::SaveMemberData(Channel* chan, std::vector<OwnedModesExts>& memberdatalist)
440 {
441         ModesExts currdata;
442         const Channel::MemberMap& users = chan->GetUsers();
443         for (Channel::MemberMap::const_iterator i = users.begin(); i != users.end(); ++i)
444         {
445                 Membership* const memb = i->second;
446
447                 for (size_t j = 0; j < handledmodes[MODETYPE_CHANNEL].size(); j++)
448                 {
449                         ModeHandler* mh = handledmodes[MODETYPE_CHANNEL][j].mh;
450                         const PrefixMode* const pm = mh->IsPrefixMode();
451                         if ((pm) && (memb->HasMode(pm)))
452                                 currdata.modelist.push_back(InstanceData(j, memb->user->uuid)); // Need to pass the user's uuid to the mode parser to set the mode later
453                 }
454
455                 SaveExtensions(memb, currdata.extlist);
456
457                 // Same logic as in DoSaveUsers()
458                 if (!currdata.empty())
459                 {
460                         memberdatalist.push_back(OwnedModesExts(memb->user->uuid));
461                         memberdatalist.back().swap(currdata);
462                 }
463         }
464 }
465
466 void DataKeeper::RestoreMemberData(Channel* chan, const std::vector<ChanData::MemberData>& memberdatalist, Modes::ChangeList& modechange)
467 {
468         for (std::vector<ChanData::MemberData>::const_iterator i = memberdatalist.begin(); i != memberdatalist.end(); ++i)
469         {
470                 const ChanData::MemberData& md = *i;
471                 User* const user = ServerInstance->FindUUID(md.owner);
472                 if (!user)
473                 {
474                         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "User %s is gone (while processing %s)", md.owner.c_str(), chan->name.c_str());
475                         continue;
476                 }
477
478                 Membership* const memb = chan->GetUser(user);
479                 if (!memb)
480                 {
481                         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Member %s is no longer on channel %s", md.owner.c_str(), chan->name.c_str());
482                         continue;
483                 }
484
485                 RestoreObj(md, memb, MODETYPE_CHANNEL, modechange);
486         }
487 }
488
489 void DataKeeper::CreateModeList(ModeType modetype)
490 {
491         const ModeParser::ModeHandlerMap& modes = ServerInstance->Modes->GetModes(modetype);
492         for (ModeParser::ModeHandlerMap::const_iterator i = modes.begin(); i != modes.end(); ++i)
493         {
494                 ModeHandler* mh = i->second;
495                 if (mh->creator == mod)
496                         handledmodes[modetype].push_back(ProviderInfo(mh));
497         }
498 }
499
500 void DataKeeper::Save(Module* currmod)
501 {
502         this->mod = currmod;
503
504         const ExtensionManager::ExtMap& allexts = ServerInstance->Extensions.GetExts();
505         for (ExtensionManager::ExtMap::const_iterator i = allexts.begin(); i != allexts.end(); ++i)
506         {
507                 ExtensionItem* ext = i->second;
508                 if (ext->creator == mod)
509                         handledexts.push_back(ProviderInfo(ext));
510         }
511
512         CreateModeList(MODETYPE_USER);
513         DoSaveUsers();
514
515         CreateModeList(MODETYPE_CHANNEL);
516         DoSaveChans();
517
518         FOREACH_MOD_CUSTOM(*reloadevprov, ReloadModule::EventListener, OnReloadModuleSave, (mod, this->moddata));
519
520         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());
521 }
522
523 void DataKeeper::VerifyServiceProvider(const ProviderInfo& service, const char* type)
524 {
525         const ServiceProvider* sp = service.extitem;
526         if (!sp)
527                 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "%s \"%s\" is no longer available", type, service.itemname.c_str());
528         else if (sp->creator != mod)
529                 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "%s \"%s\" is now handled by %s", type, service.itemname.c_str(), (sp->creator ? sp->creator->ModuleSourceFile.c_str() : "<core>"));
530 }
531
532 void DataKeeper::LinkModes(ModeType modetype)
533 {
534         std::vector<ProviderInfo>& list = handledmodes[modetype];
535         for (std::vector<ProviderInfo>::iterator i = list.begin(); i != list.end(); ++i)
536         {
537                 ProviderInfo& item = *i;
538                 item.mh = ServerInstance->Modes->FindMode(item.itemname, modetype);
539                 VerifyServiceProvider(item, (modetype == MODETYPE_USER ? "User mode" : "Channel mode"));
540         }
541 }
542
543 void DataKeeper::LinkExtensions()
544 {
545         for (std::vector<ProviderInfo>::iterator i = handledexts.begin(); i != handledexts.end(); ++i)
546         {
547                 ProviderInfo& item = *i;
548                 item.extitem = ServerInstance->Extensions.GetItem(item.itemname);
549                 VerifyServiceProvider(item.extitem, "Extension");
550         }
551 }
552
553 void DataKeeper::LinkSerializers()
554 {
555         for (std::vector<ProviderInfo>::iterator i = handledserializers.begin(); i != handledserializers.end(); ++i)
556         {
557                 ProviderInfo& item = *i;
558                 item.serializer = ServerInstance->Modules.FindDataService<ClientProtocol::Serializer>(item.itemname);
559                 VerifyServiceProvider(item.serializer, "Serializer");
560         }
561 }
562
563 void DataKeeper::Restore(Module* newmod)
564 {
565         this->mod = newmod;
566
567         // Find the new extension items
568         LinkExtensions();
569         LinkModes(MODETYPE_USER);
570         LinkModes(MODETYPE_CHANNEL);
571         LinkSerializers();
572
573         // Restore
574         DoRestoreUsers();
575         DoRestoreChans();
576         DoRestoreModules();
577
578         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Restore finished");
579 }
580
581 void DataKeeper::Fail()
582 {
583         this->mod = NULL;
584
585         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Restore failed, notifying modules");
586         DoRestoreModules();
587 }
588
589 void DataKeeper::RestoreObj(const OwnedModesExts& data, Extensible* extensible, ModeType modetype, Modes::ChangeList& modechange)
590 {
591         RestoreExtensions(data.extlist, extensible);
592         RestoreModes(data.modelist, modetype, modechange);
593 }
594
595 void DataKeeper::RestoreExtensions(const std::vector<InstanceData>& list, Extensible* extensible)
596 {
597         for (std::vector<InstanceData>::const_iterator i = list.begin(); i != list.end(); ++i)
598         {
599                 const InstanceData& id = *i;
600                 handledexts[id.index].extitem->unserialize(FORMAT_INTERNAL, extensible, id.serialized);
601         }
602 }
603
604 void DataKeeper::RestoreModes(const std::vector<InstanceData>& list, ModeType modetype, Modes::ChangeList& modechange)
605 {
606         for (std::vector<InstanceData>::const_iterator i = list.begin(); i != list.end(); ++i)
607         {
608                 const InstanceData& id = *i;
609                 modechange.push_add(handledmodes[modetype][id.index].mh, id.serialized);
610         }
611 }
612
613 bool DataKeeper::RestoreSerializer(size_t serializerindex, User* user)
614 {
615         if (serializerindex == UserData::UNUSED_INDEX)
616                 return true;
617
618         // The following checks are redundant
619         LocalUser* const localuser = IS_LOCAL(user);
620         if (!localuser)
621                 return true;
622         if (localuser->serializer != dummyserializer)
623                 return true;
624
625         const ProviderInfo& provinfo = handledserializers[serializerindex];
626         if (!provinfo.serializer)
627         {
628                 // Users cannot exist without a serializer
629                 ServerInstance->Users.QuitUser(user, "Serializer lost in reload");
630                 return false;
631         }
632
633         localuser->serializer = provinfo.serializer;
634         return true;
635 }
636
637 void DataKeeper::DoRestoreUsers()
638 {
639         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Restoring user data");
640         Modes::ChangeList modechange;
641
642         for (std::vector<UserData>::const_iterator i = userdatalist.begin(); i != userdatalist.end(); ++i)
643         {
644                 const UserData& userdata = *i;
645                 User* const user = ServerInstance->FindUUID(userdata.owner);
646                 if (!user)
647                 {
648                         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "User %s is gone", userdata.owner.c_str());
649                         continue;
650                 }
651
652                 // Attempt to restore serializer first, if it fails it's a fatal error and RestoreSerializer() quits them
653                 if (!RestoreSerializer(userdata.serializerindex, user))
654                         continue;
655
656                 RestoreObj(userdata, user, MODETYPE_USER, modechange);
657                 ServerInstance->Modes.Process(ServerInstance->FakeClient, NULL, user, modechange, ModeParser::MODE_LOCALONLY);
658                 modechange.clear();
659         }
660 }
661
662 void DataKeeper::DoRestoreChans()
663 {
664         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Restoring channel data");
665         Modes::ChangeList modechange;
666
667         for (std::vector<ChanData>::const_iterator i = chandatalist.begin(); i != chandatalist.end(); ++i)
668         {
669                 const ChanData& chandata = *i;
670                 Channel* const chan = ServerInstance->FindChan(chandata.owner);
671                 if (!chan)
672                 {
673                         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Channel %s not found", chandata.owner.c_str());
674                         continue;
675                 }
676
677                 RestoreObj(chandata, chan, MODETYPE_CHANNEL, modechange);
678                 // Process the mode change before applying any prefix modes
679                 ServerInstance->Modes.Process(ServerInstance->FakeClient, chan, NULL, modechange, ModeParser::MODE_LOCALONLY);
680                 modechange.clear();
681
682                 // Restore all member data
683                 RestoreMemberData(chan, chandata.memberdatalist, modechange);
684                 ServerInstance->Modes.Process(ServerInstance->FakeClient, chan, NULL, modechange, ModeParser::MODE_LOCALONLY);
685                 modechange.clear();
686         }
687 }
688
689 void DataKeeper::DoRestoreModules()
690 {
691         for (ReloadModule::CustomData::List::iterator i = moddata.list.begin(); i != moddata.list.end(); ++i)
692         {
693                 ReloadModule::CustomData::Data& data = *i;
694                 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Calling module data handler %p", (void*)data.handler);
695                 data.handler->OnReloadModuleRestore(mod, data.data);
696         }
697 }
698
699 } // namespace ReloadModule
700
701 class ReloadAction : public ActionBase
702 {
703         Module* const mod;
704         const std::string uuid;
705         const std::string passedname;
706
707  public:
708         ReloadAction(Module* m, const std::string& uid, const std::string& passedmodname)
709                 : mod(m)
710                 , uuid(uid)
711                 , passedname(passedmodname)
712         {
713         }
714
715         void Call() CXX11_OVERRIDE
716         {
717                 ReloadModule::DataKeeper datakeeper;
718                 datakeeper.Save(mod);
719
720                 DLLManager* dll = mod->ModuleDLLManager;
721                 std::string name = mod->ModuleSourceFile;
722                 ServerInstance->Modules->DoSafeUnload(mod);
723                 ServerInstance->GlobalCulls.Apply();
724                 delete dll;
725                 bool result = ServerInstance->Modules->Load(name);
726
727                 if (result)
728                 {
729                         Module* newmod = ServerInstance->Modules->Find(name);
730                         datakeeper.Restore(newmod);
731                 }
732                 else
733                         datakeeper.Fail();
734
735                 ServerInstance->SNO->WriteGlobalSno('a', "RELOAD MODULE: %s %ssuccessfully reloaded", passedname.c_str(), result ? "" : "un");
736                 User* user = ServerInstance->FindUUID(uuid);
737                 if (user)
738                         user->WriteNumeric(RPL_LOADEDMODULE, passedname, InspIRCd::Format("Module %ssuccessfully reloaded.", (result ? "" : "un")));
739
740                 ServerInstance->GlobalCulls.AddItem(this);
741         }
742 };
743
744 CmdResult CommandReloadmodule::Handle(User* user, const Params& parameters)
745 {
746         Module* m = ServerInstance->Modules->Find(parameters[0]);
747         if (m == creator)
748         {
749                 user->WriteNumeric(RPL_LOADEDMODULE, parameters[0], "You cannot reload core_reloadmodule (unload and load it)");
750                 return CMD_FAILURE;
751         }
752
753         if (creator->dying)
754                 return CMD_FAILURE;
755
756         if ((m) && (ServerInstance->Modules.CanUnload(m)))
757         {
758                 ServerInstance->AtomicActions.AddAction(new ReloadAction(m, user->uuid, parameters[0]));
759                 return CMD_SUCCESS;
760         }
761         else
762         {
763                 user->WriteNumeric(RPL_LOADEDMODULE, parameters[0], "Could not find module by that name");
764                 return CMD_FAILURE;
765         }
766 }
767
768 COMMAND_INIT(CommandReloadmodule)