summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2013-02-13 17:42:01 -0500
committerAdam <Adam@anope.org>2013-02-14 01:20:18 -0500
commit9e544a6443117861c3d6406e435043f1cf0f7099 (patch)
treee7449fb01e377576e8a09f386117d2c251de0596
parent225b7c38c127fbc6aac6724012f71c9483a4da77 (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.h6
-rw-r--r--include/regchannel.h5
-rw-r--r--modules/commands/cs_info.cpp4
-rw-r--r--modules/commands/cs_set.cpp4
-rw-r--r--modules/commands/ns_alist.cpp31
-rw-r--r--modules/database/db_old.cpp2
-rw-r--r--modules/database/db_plain.cpp6
-rw-r--r--modules/extra/webcpanel/pages/chanserv/drop.cpp8
-rw-r--r--modules/extra/webcpanel/pages/chanserv/info.cpp7
-rw-r--r--modules/extra/webcpanel/pages/chanserv/set.cpp4
-rw-r--r--modules/pseudoclients/chanserv.cpp28
-rw-r--r--src/access.cpp4
-rw-r--r--src/nickcore.cpp24
-rw-r--r--src/regchannel.cpp45
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;
}