diff options
| author | Adam <Adam@anope.org> | 2013-02-13 17:42:01 -0500 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2013-02-14 01:20:18 -0500 |
| commit | 9e544a6443117861c3d6406e435043f1cf0f7099 (patch) | |
| tree | e7449fb01e377576e8a09f386117d2c251de0596 | |
| parent | 225b7c38c127fbc6aac6724012f71c9483a4da77 (diff) | |
Store what channels have references to accounts in NickCore to prevent having to iterate over all channels and then all access entries when nicks expire or from nickserv/alist
| -rw-r--r-- | include/account.h | 6 | ||||
| -rw-r--r-- | include/regchannel.h | 5 | ||||
| -rw-r--r-- | modules/commands/cs_info.cpp | 4 | ||||
| -rw-r--r-- | modules/commands/cs_set.cpp | 4 | ||||
| -rw-r--r-- | modules/commands/ns_alist.cpp | 31 | ||||
| -rw-r--r-- | modules/database/db_old.cpp | 2 | ||||
| -rw-r--r-- | modules/database/db_plain.cpp | 6 | ||||
| -rw-r--r-- | modules/extra/webcpanel/pages/chanserv/drop.cpp | 8 | ||||
| -rw-r--r-- | modules/extra/webcpanel/pages/chanserv/info.cpp | 7 | ||||
| -rw-r--r-- | modules/extra/webcpanel/pages/chanserv/set.cpp | 4 | ||||
| -rw-r--r-- | modules/pseudoclients/chanserv.cpp | 28 | ||||
| -rw-r--r-- | src/access.cpp | 4 | ||||
| -rw-r--r-- | src/nickcore.cpp | 24 | ||||
| -rw-r--r-- | src/regchannel.cpp | 45 |
14 files changed, 132 insertions, 46 deletions
diff --git a/include/account.h b/include/account.h index 8ce457a72..98827fd81 100644 --- a/include/account.h +++ b/include/account.h @@ -147,6 +147,8 @@ class CoreExport NickAlias : public Serializable, public Extensible */ class CoreExport NickCore : public Serializable, public Extensible { + /* Channels which reference this core in some way (this is on their access list, akick list, is founder, successor, etc) */ + Serialize::Checker<std::map<ChannelInfo *, int> > chanaccess; public: /* Name of the account. Find(display)->nc == this. */ Anope::string display; @@ -293,6 +295,10 @@ class CoreExport NickCore : public Serializable, public Extensible * @return The account, if it exists */ static NickCore* Find(const Anope::string &nick); + + void AddChannelReference(ChannelInfo *ci); + void RemoveChannelReference(ChannelInfo *ci); + void GetChannelReferences(std::deque<ChannelInfo *> &queue); }; /* A request to check if an account/password is valid. These can exist for diff --git a/include/regchannel.h b/include/regchannel.h index 02d637800..ab369ce2b 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -159,6 +159,7 @@ class CoreExport ChannelInfo : public Serializable, public Extensible { private: Serialize::Reference<NickCore> founder; /* Channel founder */ + Serialize::Reference<NickCore> successor; /* Who gets the channel if the founder nick is dropped or expires */ Serialize::Checker<std::vector<ChanAccess *> > access; /* List of authorized users */ Serialize::Checker<std::vector<AutoKick *> > akick; /* List of users to kickban */ Serialize::Checker<std::vector<BadWord *> > badwords; /* List of badwords */ @@ -174,7 +175,6 @@ class CoreExport ChannelInfo : public Serializable, public Extensible Serialize::Checker<std::vector<LogSetting *> > log_settings; Anope::string name; /* Channel name */ - Serialize::Reference<NickCore> successor; /* Who gets the channel if the founder nick is dropped or expires */ Anope::string desc; time_t time_registered; @@ -223,6 +223,9 @@ class CoreExport ChannelInfo : public Serializable, public Extensible */ NickCore *GetFounder() const; + void SetSuccessor(NickCore *nc); + NickCore *GetSuccessor() const; + /** Find which bot should send mode/topic/etc changes for this channel * @return The bot */ diff --git a/modules/commands/cs_info.cpp b/modules/commands/cs_info.cpp index c37a74dd5..9485e81fd 100644 --- a/modules/commands/cs_info.cpp +++ b/modules/commands/cs_info.cpp @@ -59,8 +59,8 @@ class CommandCSInfo : public Command if (ci->GetFounder()) info["Founder"] = ci->GetFounder()->display; - if (show_all && ci->successor) - info["Successor"] = ci->successor->display; + if (show_all && ci->GetSuccessor()) + info["Successor"] = ci->GetSuccessor()->display; if (!ci->desc.empty()) info["Description"] = ci->desc; diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index 8c6aa48c1..730f31deb 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -1057,9 +1057,9 @@ class CommandCSSetSuccessor : public Command else nc = NULL; - Log(!source.permission.empty() ? LOG_ADMIN : LOG_COMMAND, source, this, ci) << "to change the successor from " << (ci->successor ? ci->successor->display : "(none)") << " to " << (nc ? nc->display : "(none)"); + Log(!source.permission.empty() ? LOG_ADMIN : LOG_COMMAND, source, this, ci) << "to change the successor from " << (ci->GetSuccessor() ? ci->GetSuccessor()->display : "(none)") << " to " << (nc ? nc->display : "(none)"); - ci->successor = nc; + ci->SetSuccessor(nc); if (nc) source.Reply(_("Successor for \002%s\002 changed to \002%s\002."), ci->name.c_str(), nc->display.c_str()); diff --git a/modules/commands/ns_alist.cpp b/modules/commands/ns_alist.cpp index bd3a22281..c8d7eef0f 100644 --- a/modules/commands/ns_alist.cpp +++ b/modules/commands/ns_alist.cpp @@ -46,12 +46,21 @@ class CommandNSAList : public Command source.Reply(_("Channels that \002%s\002 has access on:"), nc->display.c_str()); - for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it) + std::deque<ChannelInfo *> queue; + nc->GetChannelReferences(queue); + + if (queue.empty()) + { + source.Reply(_("\2%s\2 has no access in any channels."), nc->display.c_str()); + return; + } + + for (unsigned i = 0; i < queue.size(); ++i) { - ChannelInfo *ci = it->second; + ChannelInfo *ci = queue[i]; ListFormatter::ListEntry entry; - if (ci->GetFounder() && ci->GetFounder() == nc) + if (ci->GetFounder() == nc) { ++chan_count; entry["Number"] = stringify(chan_count); @@ -61,6 +70,16 @@ class CommandNSAList : public Command continue; } + if (ci->GetSuccessor() == nc) + { + ++chan_count; + entry["Number"] = stringify(chan_count); + entry["Channel"] = (ci->HasExt("NO_EXPIRE") ? "!" : "") + ci->name; + entry["Access"] = "Successor"; + list.AddEntry(entry); + continue; + } + AccessGroup access = ci->AccessFor(nc); if (access.empty()) continue; @@ -69,8 +88,8 @@ class CommandNSAList : public Command entry["Number"] = stringify(chan_count); entry["Channel"] = (ci->HasExt("NO_EXPIRE") ? "!" : "") + ci->name; - for (unsigned i = 0; i < access.size(); ++i) - entry["Access"] = entry["Access"] + ", " + access[i]->AccessSerialize(); + for (unsigned j = 0; j < access.size(); ++j) + entry["Access"] = entry["Access"] + ", " + access[j]->AccessSerialize(); entry["Access"] = entry["Access"].substr(2); list.AddEntry(entry); } @@ -79,6 +98,8 @@ class CommandNSAList : public Command list.Process(replies); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); + + source.Reply(_("End of list - %d channels shown."), chan_count); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override diff --git a/modules/database/db_old.cpp b/modules/database/db_old.cpp index ac453fdbe..e1fe8f69d 100644 --- a/modules/database/db_old.cpp +++ b/modules/database/db_old.cpp @@ -701,7 +701,7 @@ static void LoadChannels() ci->SetFounder(NickCore::Find(buffer)); READ(read_string(buffer, f)); - ci->successor = NickCore::Find(buffer); + ci->SetSuccessor(NickCore::Find(buffer)); char pwbuf[32]; READ(read_buffer(pwbuf, f)); diff --git a/modules/database/db_plain.cpp b/modules/database/db_plain.cpp index 1256a2012..99bdf947a 100644 --- a/modules/database/db_plain.cpp +++ b/modules/database/db_plain.cpp @@ -142,7 +142,7 @@ EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, co else if (key.equals_ci("FOUNDER")) ci->SetFounder(NickCore::Find(params[0])); else if (key.equals_ci("SUCCESSOR")) - ci->successor = NickCore::Find(params[0]); + ci->SetSuccessor(NickCore::Find(params[0])); else if (key.equals_ci("LEVELS")) { for (unsigned j = 0, end = params.size(); j < end; j += 2) @@ -764,8 +764,8 @@ class DBPlain : public Module db_buffer << "MD MEMOMAX " << ci->memos.memomax << endl; if (ci->GetFounder()) db_buffer << "MD FOUNDER " << ci->GetFounder()->display << endl; - if (ci->successor) - db_buffer << "MD SUCCESSOR " << ci->successor->display << endl; + if (ci->GetSuccessor()) + db_buffer << "MD SUCCESSOR " << ci->GetSuccessor()->display << endl; if (!ci->desc.empty()) db_buffer << "MD DESC :" << ci->desc << endl; if (!ci->last_topic.empty()) diff --git a/modules/extra/webcpanel/pages/chanserv/drop.cpp b/modules/extra/webcpanel/pages/chanserv/drop.cpp index 0ebb8e7a1..5462aa131 100644 --- a/modules/extra/webcpanel/pages/chanserv/drop.cpp +++ b/modules/extra/webcpanel/pages/chanserv/drop.cpp @@ -25,10 +25,12 @@ bool WebCPanel::ChanServ::Drop::OnRequest(HTTPProvider *server, const Anope::str } else replacements["MESSAGES"] = "Invalid Confirmation"; } - // XXX this is slightly inefficient - for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it) + + std::deque<ChannelInfo *> queue; + na->nc->GetChannelReferences(queue); + for (unsigned i = 0; i < queue.size(); ++i) { - ChannelInfo *ci = it->second; + ChannelInfo *ci = queue[i]; if ((ci->HasExt("SECUREFOUNDER") ? ci->AccessFor(na->nc).founder : ci->AccessFor(na->nc).HasPriv("FOUNDER")) || (na->nc->IsServicesOper() && na->nc->o->ot->HasCommand("chanserv/drop"))) { replacements["CHANNEL_NAMES"] = ci->name; diff --git a/modules/extra/webcpanel/pages/chanserv/info.cpp b/modules/extra/webcpanel/pages/chanserv/info.cpp index 18f6b8f7a..95592706d 100644 --- a/modules/extra/webcpanel/pages/chanserv/info.cpp +++ b/modules/extra/webcpanel/pages/chanserv/info.cpp @@ -13,10 +13,11 @@ WebCPanel::ChanServ::Info::Info(const Anope::string &cat, const Anope::string &u bool WebCPanel::ChanServ::Info::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { - // XXX this is slightly inefficient - for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it) + std::deque<ChannelInfo *> queue; + na->nc->GetChannelReferences(queue); + for (unsigned i = 0; i < queue.size(); ++i) { - ChannelInfo *ci = it->second; + ChannelInfo *ci = queue[i]; if (ci->AccessFor(na->nc).HasPriv("SET") || ci->AccessFor(na->nc).HasPriv("ACCESS_LIST")) { diff --git a/modules/extra/webcpanel/pages/chanserv/set.cpp b/modules/extra/webcpanel/pages/chanserv/set.cpp index af3640e33..20026a08a 100644 --- a/modules/extra/webcpanel/pages/chanserv/set.cpp +++ b/modules/extra/webcpanel/pages/chanserv/set.cpp @@ -91,8 +91,8 @@ bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri replacements["CHANNEL_ESCAPED"] = HTTPUtils::URLEncode(ci->name); if (ci->GetFounder()) replacements["FOUNDER"] = ci->GetFounder()->display; - if (ci->successor) - replacements["SUCCESSOR"] = ci->successor->display; + if (ci->GetSuccessor()) + replacements["SUCCESSOR"] = ci->GetSuccessor()->display; replacements["TIME_REGISTERED"] = Anope::strftime(ci->time_registered, na->nc); replacements["LAST_USED"] = Anope::strftime(ci->last_used, na->nc); diff --git a/modules/pseudoclients/chanserv.cpp b/modules/pseudoclients/chanserv.cpp index ee8c08ed6..579c0b391 100644 --- a/modules/pseudoclients/chanserv.cpp +++ b/modules/pseudoclients/chanserv.cpp @@ -103,17 +103,18 @@ class ChanServCore : public Module void OnDelCore(NickCore *nc) anope_override { - // XXX this is slightly inefficient - for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end;) + std::deque<ChannelInfo *> chans; + nc->GetChannelReferences(chans); + + for (unsigned i = 0; i < chans.size(); ++i) { - ChannelInfo *ci = it->second; - ++it; + ChannelInfo *ci = chans[i]; if (ci->GetFounder() == nc) { NickCore *newowner = NULL; - if (ci->successor && (ci->successor->IsServicesOper() || !Config->CSMaxReg || ci->successor->channelcount < Config->CSMaxReg)) - newowner = ci->successor; + if (ci->GetSuccessor() && ci->GetSuccessor() != nc && (ci->GetSuccessor()->IsServicesOper() || !Config->CSMaxReg || ci->GetSuccessor()->channelcount < Config->CSMaxReg)) + newowner = ci->GetSuccessor(); else { const ChanAccess *highest = NULL; @@ -135,7 +136,7 @@ class ChanServCore : public Module { Log(LOG_NORMAL, "chanserv/expire") << "Transferring foundership of " << ci->name << " from deleted nick " << nc->display << " to " << newowner->display; ci->SetFounder(newowner); - ci->successor = NULL; + ci->SetSuccessor(NULL); } else { @@ -146,8 +147,8 @@ class ChanServCore : public Module } } - if (ci->successor == nc) - ci->successor = NULL; + if (ci->GetSuccessor() == nc) + ci->SetSuccessor(NULL); for (unsigned j = 0; j < ci->GetAccessCount(); ++j) { @@ -161,11 +162,14 @@ class ChanServCore : public Module } } - for (unsigned j = ci->GetAkickCount(); j > 0; --j) + for (unsigned j = 0; j < ci->GetAkickCount(); ++j) { - const AutoKick *akick = ci->GetAkick(j - 1); + const AutoKick *akick = ci->GetAkick(j); if (akick->nc == nc) - ci->EraseAkick(j - 1); + { + ci->EraseAkick(j); + break; + } } } } diff --git a/src/access.cpp b/src/access.cpp index fdaada75b..dd5881108 100644 --- a/src/access.cpp +++ b/src/access.cpp @@ -102,6 +102,10 @@ ChanAccess::~ChanAccess() std::vector<ChanAccess *>::iterator it = std::find(this->ci->access->begin(), this->ci->access->end(), this); if (it != this->ci->access->end()) this->ci->access->erase(it); + + const NickAlias *na = NickAlias::Find(this->mask); + if (na != NULL) + na->nc->RemoveChannelReference(this->ci); } } diff --git a/src/nickcore.cpp b/src/nickcore.cpp index 7dda6da5c..f92d4739c 100644 --- a/src/nickcore.cpp +++ b/src/nickcore.cpp @@ -17,7 +17,7 @@ Serialize::Checker<nickcore_map> NickCoreList("NickCore"); -NickCore::NickCore(const Anope::string &coredisplay) : Serializable("NickCore"), aliases("NickAlias") +NickCore::NickCore(const Anope::string &coredisplay) : Serializable("NickCore"), chanaccess("ChannelInfo"), aliases("NickAlias") { if (coredisplay.empty()) throw CoreException("Empty display passed to NickCore constructor"); @@ -44,6 +44,9 @@ NickCore::~NickCore() { FOREACH_MOD(I_OnDelCore, OnDelCore(this)); + if (!this->chanaccess->empty()) + Log(LOG_DEBUG) << "Non-empty chanaccess list in destructor!"; + for (std::list<User *>::iterator it = this->users.begin(); it != this->users.end();) { User *user = *it++; @@ -253,6 +256,25 @@ void NickCore::ClearCert() this->cert.clear(); } +void NickCore::AddChannelReference(ChannelInfo *ci) +{ + ++(*this->chanaccess)[ci]; +} + +void NickCore::RemoveChannelReference(ChannelInfo *ci) +{ + int& i = (*this->chanaccess)[ci]; + if (--i <= 0) + this->chanaccess->erase(ci); +} + +void NickCore::GetChannelReferences(std::deque<ChannelInfo *> &queue) +{ + queue.clear(); + for (std::map<ChannelInfo *, int>::iterator it = this->chanaccess->begin(), it_end = this->chanaccess->end(); it != it_end; ++it) + queue.push_back(it->first); +} + NickCore* NickCore::Find(const Anope::string &nick) { nickcore_map::const_iterator it = NickCoreList->find(nick); diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 257eca0ee..2a82590e2 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -82,6 +82,10 @@ AutoKick::~AutoKick() std::vector<AutoKick *>::iterator it = std::find(this->ci->akick->begin(), this->ci->akick->end(), this); if (it != this->ci->akick->end()) this->ci->akick->erase(it); + + const NickAlias *na = NickAlias::Find(this->mask); + if (na != NULL) + na->nc->RemoveChannelReference(this->ci); } } @@ -444,16 +448,9 @@ Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data) ci->ExtensibleUnserialize(data); - if (ci->founder) - --ci->founder->channelcount; - ci->founder = NickCore::Find(sfounder); - if (ci->founder) - ++ci->founder->channelcount; + ci->SetFounder(NickCore::Find(sfounder)); + ci->SetSuccessor(NickCore::Find(ssuccessor)); - ci->successor = NickCore::Find(ssuccessor); - if (ci->founder && *ci->founder == *ci->successor) - ci->successor = NULL; - data["description"] >> ci->desc; data["time_registered"] >> ci->time_registered; data["last_used"] >> ci->last_used; @@ -511,12 +508,18 @@ Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data) void ChannelInfo::SetFounder(NickCore *nc) { if (this->founder) + { --this->founder->channelcount; + this->founder->RemoveChannelReference(this); + } + this->founder = nc; + if (this->founder) + { ++this->founder->channelcount; - if (*this->founder == *this->successor) - this->successor = NULL; + this->founder->AddChannelReference(this); + } } NickCore *ChannelInfo::GetFounder() const @@ -524,6 +527,20 @@ NickCore *ChannelInfo::GetFounder() const return this->founder; } +void ChannelInfo::SetSuccessor(NickCore *nc) +{ + if (this->successor) + this->successor->RemoveChannelReference(this); + this->successor = nc; + if (this->successor) + this->successor->AddChannelReference(this); +} + +NickCore *ChannelInfo::GetSuccessor() const +{ + return this->successor; +} + BotInfo *ChannelInfo::WhoSends() const { if (this && this->bi) @@ -538,6 +555,10 @@ BotInfo *ChannelInfo::WhoSends() const void ChannelInfo::AddAccess(ChanAccess *taccess) { this->access->push_back(taccess); + + const NickAlias *na = NickAlias::Find(taccess->mask); + if (na != NULL) + na->nc->AddChannelReference(this); } ChanAccess *ChannelInfo::GetAccess(unsigned index) const @@ -639,6 +660,8 @@ AutoKick *ChannelInfo::AddAkick(const Anope::string &user, NickCore *akicknc, co this->akick->push_back(autokick); + akicknc->AddChannelReference(this); + return autokick; } |
