summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/inspircd.h10
-rw-r--r--src/channels.cpp26
-rw-r--r--src/cmd_kill.cpp6
-rw-r--r--src/cmd_list.cpp2
-rw-r--r--src/cmd_quit.cpp11
-rw-r--r--src/cmd_rehash.cpp1
-rw-r--r--src/cmd_stats.cpp6
-rw-r--r--src/cmd_trace.cpp2
-rw-r--r--src/cmd_who.cpp2
-rw-r--r--src/command_parse.cpp83
-rw-r--r--src/commands.cpp12
-rw-r--r--src/cull_list.cpp16
-rw-r--r--src/helperfuncs.cpp26
-rw-r--r--src/inspircd.cpp36
-rw-r--r--src/mode.cpp4
-rw-r--r--src/modules.cpp3
-rw-r--r--src/modules/m_check.cpp2
-rw-r--r--src/modules/m_httpd_stats.cpp4
-rw-r--r--src/modules/m_redirect.cpp2
-rw-r--r--src/modules/m_safelist.cpp2
-rw-r--r--src/modules/m_spanningtree.cpp36
-rw-r--r--src/modules/m_spy.cpp2
-rw-r--r--src/modules/m_tline.cpp2
-rw-r--r--src/users.cpp35
24 files changed, 136 insertions, 195 deletions
diff --git a/include/inspircd.h b/include/inspircd.h
index 9f2ae630a..3d9002f53 100644
--- a/include/inspircd.h
+++ b/include/inspircd.h
@@ -401,11 +401,11 @@ class InspIRCd : public classbase
/** Client list, a hash_map containing all clients, local and remote
*/
- user_hash clientlist;
+ user_hash* clientlist;
/** Channel list, a hash_map containing all channels
*/
- chan_hash chanlist;
+ chan_hash* chanlist;
/** Local client list, a vector containing only local clients
*/
@@ -1129,6 +1129,12 @@ class InspIRCd : public classbase
*/
void Cleanup();
+ /** This copies the user and channel hash_maps into new hash maps.
+ * This frees memory used by the hash_map allocator (which it neglects
+ * to free, most of the time, using tons of ram)
+ */
+ void RehashUsersAndChans();
+
/** Begin execution of the server.
* NOTE: this function NEVER returns. Internally,
* after performing some initialisation routines,
diff --git a/src/channels.cpp b/src/channels.cpp
index 8a44479e0..ea7edd71f 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -217,7 +217,7 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo
/* create a new one */
Ptr = new chanrec(Instance);
- Instance->chanlist[cname] = Ptr;
+ (*(Instance->chanlist))[cname] = Ptr;
strlcpy(Ptr->name, cname,CHANMAX);
@@ -341,12 +341,12 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo
{
Instance->Log(DEBUG,"BLAMMO, Whacking channel.");
/* Things went seriously pear shaped, so take this away. bwahaha. */
- chan_hash::iterator n = Instance->chanlist.find(cname);
- if (n != Instance->chanlist.end())
+ chan_hash::iterator n = Instance->chanlist->find(cname);
+ if (n != Instance->chanlist->end())
{
Ptr->DelUser(user);
DELETE(Ptr);
- Instance->chanlist.erase(n);
+ Instance->chanlist->erase(n);
}
}
@@ -464,13 +464,13 @@ long chanrec::PartUser(userrec *user, const char* reason)
if (!this->DelUser(user)) /* if there are no users left on the channel... */
{
- chan_hash::iterator iter = ServerInstance->chanlist.find(this->name);
+ chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
/* kill the record */
- if (iter != ServerInstance->chanlist.end())
+ if (iter != ServerInstance->chanlist->end())
{
ServerInstance->Log(DEBUG,"del_channel: destroyed: %s", this->name);
FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(this));
- ServerInstance->chanlist.erase(iter);
+ ServerInstance->chanlist->erase(iter);
}
return 0;
}
@@ -507,12 +507,12 @@ long chanrec::ServerKickUser(userrec* user, const char* reason, bool triggereven
if (!this->DelUser(user))
{
- chan_hash::iterator iter = ServerInstance->chanlist.find(this->name);
+ chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
/* kill the record */
- if (iter != ServerInstance->chanlist.end())
+ if (iter != ServerInstance->chanlist->end())
{
FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(this));
- ServerInstance->chanlist.erase(iter);
+ ServerInstance->chanlist->erase(iter);
}
return 0;
}
@@ -580,13 +580,13 @@ long chanrec::KickUser(userrec *src, userrec *user, const char* reason)
if (!this->DelUser(user))
/* if there are no users left on the channel */
{
- chan_hash::iterator iter = ServerInstance->chanlist.find(this->name);
+ chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
/* kill the record */
- if (iter != ServerInstance->chanlist.end())
+ if (iter != ServerInstance->chanlist->end())
{
FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(this));
- ServerInstance->chanlist.erase(iter);
+ ServerInstance->chanlist->erase(iter);
}
return 0;
}
diff --git a/src/cmd_kill.cpp b/src/cmd_kill.cpp
index bc59f8492..001f48e2c 100644
--- a/src/cmd_kill.cpp
+++ b/src/cmd_kill.cpp
@@ -56,12 +56,12 @@ CmdResult cmd_kill::Handle (const char** parameters, int pcnt, userrec *user)
u->WriteCommonExcept("QUIT :%s", killreason);
FOREACH_MOD(I_OnRemoteKill, OnRemoteKill(user, u, killreason));
- user_hash::iterator iter = ServerInstance->clientlist.find(u->nick);
+ user_hash::iterator iter = ServerInstance->clientlist->find(u->nick);
- if (iter != ServerInstance->clientlist.end())
+ if (iter != ServerInstance->clientlist->end())
{
ServerInstance->Log(DEBUG,"deleting user hash value %d", iter->second);
- ServerInstance->clientlist.erase(iter);
+ ServerInstance->clientlist->erase(iter);
}
if (u->registered == REG_ALL)
diff --git a/src/cmd_list.cpp b/src/cmd_list.cpp
index b1bb44172..920d77f34 100644
--- a/src/cmd_list.cpp
+++ b/src/cmd_list.cpp
@@ -31,7 +31,7 @@ CmdResult cmd_list::Handle (const char** parameters, int pcnt, userrec *user)
if ((pcnt == 1) && (*parameters[0] == '<'))
pcnt = 0;
- for (chan_hash::const_iterator i = ServerInstance->chanlist.begin(); i != ServerInstance->chanlist.end(); i++)
+ for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
{
// attempt to match a glob pattern
if (pcnt && !match(i->second->name, parameters[0]))
diff --git a/src/cmd_quit.cpp b/src/cmd_quit.cpp
index 0065987cf..db71bbdb1 100644
--- a/src/cmd_quit.cpp
+++ b/src/cmd_quit.cpp
@@ -26,7 +26,7 @@ extern "C" command_t* init_command(InspIRCd* Instance)
CmdResult cmd_quit::Handle (const char** parameters, int pcnt, userrec *user)
{
- user_hash::iterator iter = ServerInstance->clientlist.find(user->nick);
+ user_hash::iterator iter = ServerInstance->clientlist->find(user->nick);
char reason[MAXBUF];
std::string quitmsg = "Client exited";
@@ -82,17 +82,18 @@ CmdResult cmd_quit::Handle (const char** parameters, int pcnt, userrec *user)
if (IS_LOCAL(user))
{
ServerInstance->SE->DelFd(user);
- if (find(ServerInstance->local_users.begin(),ServerInstance->local_users.end(),user) != ServerInstance->local_users.end())
+ std::vector<userrec*>::iterator x = find(ServerInstance->local_users.begin(),ServerInstance->local_users.end(),user);
+ if (x != ServerInstance->local_users.end())
{
ServerInstance->Log(DEBUG,"Delete local user");
- ServerInstance->local_users.erase(find(ServerInstance->local_users.begin(),ServerInstance->local_users.end(),user));
+ ServerInstance->local_users.erase(x);
}
user->CloseSocket();
}
- if (iter != ServerInstance->clientlist.end())
+ if (iter != ServerInstance->clientlist->end())
{
- ServerInstance->clientlist.erase(iter);
+ ServerInstance->clientlist->erase(iter);
}
if (user->registered == REG_ALL) {
diff --git a/src/cmd_rehash.cpp b/src/cmd_rehash.cpp
index 47554d5ac..518b7fbf4 100644
--- a/src/cmd_rehash.cpp
+++ b/src/cmd_rehash.cpp
@@ -37,6 +37,7 @@ CmdResult cmd_rehash::Handle (const char** parameters, int pcnt, userrec *user)
ServerInstance->WriteOpers("%s is rehashing config file %s",user->nick,ServerConfig::CleanFilename(CONFIG_FILE));
ServerInstance->CloseLog();
ServerInstance->OpenLog(NULL,0);
+ ServerInstance->RehashUsersAndChans();
ServerInstance->Config->Read(false,user);
}
if (old_disabled != ServerInstance->Config->DisabledCommands)
diff --git a/src/cmd_stats.cpp b/src/cmd_stats.cpp
index f31248659..f609864a9 100644
--- a/src/cmd_stats.cpp
+++ b/src/cmd_stats.cpp
@@ -120,7 +120,7 @@ void DoStats(InspIRCd* ServerInstance, char statschar, userrec* user, string_lis
case 'P':
{
int idx = 0;
- for (user_hash::iterator i = ServerInstance->clientlist.begin(); i != ServerInstance->clientlist.end(); i++)
+ for (user_hash::iterator i = ServerInstance->clientlist->begin(); i != ServerInstance->clientlist->end(); i++)
{
if ((*i->second->oper) && (!ServerInstance->ULine(i->second->server)))
{
@@ -169,8 +169,8 @@ void DoStats(InspIRCd* ServerInstance, char statschar, userrec* user, string_lis
{
rusage R;
results.push_back(sn+" 240 "+user->nick+" :InspIRCd(CLASS) "+ConvToStr(sizeof(InspIRCd))+" bytes");
- results.push_back(sn+" 249 "+user->nick+" :Users(HASH_MAP) "+ConvToStr(ServerInstance->clientlist.size())+" ("+ConvToStr(ServerInstance->clientlist.size()*sizeof(userrec))+" bytes, "+ConvToStr(ServerInstance->clientlist.bucket_count())+" buckets)");
- results.push_back(sn+" 249 "+user->nick+" :Channels(HASH_MAP) "+ConvToStr(ServerInstance->chanlist.size())+" ("+ConvToStr(ServerInstance->chanlist.size()*sizeof(chanrec))+" bytes, "+ConvToStr(ServerInstance->chanlist.bucket_count())+" buckets)");
+ results.push_back(sn+" 249 "+user->nick+" :Users(HASH_MAP) "+ConvToStr(ServerInstance->clientlist->size())+" ("+ConvToStr(ServerInstance->clientlist->size()*sizeof(userrec))+" bytes, "+ConvToStr(ServerInstance->clientlist->bucket_count())+" buckets)");
+ results.push_back(sn+" 249 "+user->nick+" :Channels(HASH_MAP) "+ConvToStr(ServerInstance->chanlist->size())+" ("+ConvToStr(ServerInstance->chanlist->size()*sizeof(chanrec))+" bytes, "+ConvToStr(ServerInstance->chanlist->bucket_count())+" buckets)");
results.push_back(sn+" 249 "+user->nick+" :Commands(VECTOR) "+ConvToStr(ServerInstance->Parser->cmdlist.size())+" ("+ConvToStr(ServerInstance->Parser->cmdlist.size()*sizeof(command_t))+" bytes)");
results.push_back(sn+" 249 "+user->nick+" :MOTD(VECTOR) "+ConvToStr(ServerInstance->Config->MOTD.size())+", RULES(VECTOR) "+ConvToStr(ServerInstance->Config->RULES.size()));
results.push_back(sn+" 249 "+user->nick+" :Modules(VECTOR) "+ConvToStr(ServerInstance->modules.size())+" ("+ConvToStr(ServerInstance->modules.size()*sizeof(Module))+")");
diff --git a/src/cmd_trace.cpp b/src/cmd_trace.cpp
index d34252f38..23a72f199 100644
--- a/src/cmd_trace.cpp
+++ b/src/cmd_trace.cpp
@@ -24,7 +24,7 @@ extern "C" command_t* init_command(InspIRCd* Instance)
CmdResult cmd_trace::Handle (const char** parameters, int pcnt, userrec *user)
{
- for (user_hash::iterator i = ServerInstance->clientlist.begin(); i != ServerInstance->clientlist.end(); i++)
+ for (user_hash::iterator i = ServerInstance->clientlist->begin(); i != ServerInstance->clientlist->end(); i++)
{
if (i->second)
{
diff --git a/src/cmd_who.cpp b/src/cmd_who.cpp
index bd9457d6f..11b001eab 100644
--- a/src/cmd_who.cpp
+++ b/src/cmd_who.cpp
@@ -234,7 +234,7 @@ CmdResult cmd_who::Handle (const char** parameters, int pcnt, userrec *user)
}
else
{
- for (user_hash::iterator i = ServerInstance->clientlist.begin(); i != ServerInstance->clientlist.end(); i++)
+ for (user_hash::iterator i = ServerInstance->clientlist->begin(); i != ServerInstance->clientlist->end(); i++)
{
if (whomatch(i->second, matchtext, opt_realname, opt_showrealhost, opt_mode))
{
diff --git a/src/command_parse.cpp b/src/command_parse.cpp
index cb43df1a1..07b41c4cb 100644
--- a/src/command_parse.cpp
+++ b/src/command_parse.cpp
@@ -106,89 +106,6 @@ long InspIRCd::Duration(const char* str)
return total;
}
-/* All other ircds when doing this check usually just look for a string of *@* or *. We're smarter than that, though. */
-
-bool InspIRCd::HostMatchesEveryone(const std::string &mask, userrec* user)
-{
- char buffer[MAXBUF];
- char itrigger[MAXBUF];
- long matches = 0;
-
- if (!Config->ConfValue(Config->config_data, "insane","trigger", 0, itrigger, MAXBUF))
- strlcpy(itrigger,"95.5",MAXBUF);
-
- if (Config->ConfValueBool(Config->config_data, "insane","hostmasks", 0))
- return false;
-
- for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
- {
- strlcpy(buffer,u->second->ident,MAXBUF);
- charlcat(buffer,'@',MAXBUF);
- strlcat(buffer,u->second->host,MAXBUF);
- if (match(buffer,mask.c_str()))
- matches++;
- }
- float percent = ((float)matches / (float)clientlist.size()) * 100;
- if (percent > (float)atof(itrigger))
- {
- WriteOpers("*** \2WARNING\2: %s tried to set a G/K/E line mask of %s, which covers %.2f%% of the network!",user->nick,mask.c_str(),percent);
- return true;
- }
- return false;
-}
-
-bool InspIRCd::IPMatchesEveryone(const std::string &ip, userrec* user)
-{
- char itrigger[MAXBUF];
- long matches = 0;
-
- if (!Config->ConfValue(Config->config_data, "insane","trigger",0,itrigger,MAXBUF))
- strlcpy(itrigger,"95.5",MAXBUF);
-
- if (Config->ConfValueBool(Config->config_data, "insane","ipmasks",0))
- return false;
-
- for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
- {
- if (match(u->second->GetIPString(),ip.c_str(),true))
- matches++;
- }
-
- float percent = ((float)matches / (float)clientlist.size()) * 100;
- if (percent > (float)atof(itrigger))
- {
- WriteOpers("*** \2WARNING\2: %s tried to set a Z line mask of %s, which covers %.2f%% of the network!",user->nick,ip.c_str(),percent);
- return true;
- }
- return false;
-}
-
-bool InspIRCd::NickMatchesEveryone(const std::string &nick, userrec* user)
-{
- char itrigger[MAXBUF];
- long matches = 0;
-
- if (!Config->ConfValue(Config->config_data, "insane","trigger",0,itrigger,MAXBUF))
- strlcpy(itrigger,"95.5",MAXBUF);
-
- if (Config->ConfValueBool(Config->config_data, "insane","nickmasks",0))
- return false;
-
- for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
- {
- if (match(u->second->nick,nick.c_str()))
- matches++;
- }
-
- float percent = ((float)matches / (float)clientlist.size()) * 100;
- if (percent > (float)atof(itrigger))
- {
- WriteOpers("*** \2WARNING\2: %s tried to set a Q line mask of %s, which covers %.2f%% of the network!",user->nick,nick.c_str(),percent);
- return true;
- }
- return false;
-}
-
/* LoopCall is used to call a command classes handler repeatedly based on the contents of a comma seperated list.
* There are two overriden versions of this method, one of which takes two potential lists and the other takes one.
* We need a version which takes two potential lists for JOIN, because a JOIN may contain two lists of items at once,
diff --git a/src/commands.cpp b/src/commands.cpp
index 9b127b8bf..aa43685d4 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -113,7 +113,7 @@ bool InspIRCd::HostMatchesEveryone(const std::string &mask, userrec* user)
if (Config->ConfValueBool(Config->config_data, "insane","hostmasks", 0))
return false;
- for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
+ for (user_hash::iterator u = clientlist->begin(); u != clientlist->end(); u++)
{
strlcpy(buffer,u->second->ident,MAXBUF);
charlcat(buffer,'@',MAXBUF);
@@ -121,7 +121,7 @@ bool InspIRCd::HostMatchesEveryone(const std::string &mask, userrec* user)
if (match(buffer,mask.c_str()))
matches++;
}
- float percent = ((float)matches / (float)clientlist.size()) * 100;
+ float percent = ((float)matches / (float)clientlist->size()) * 100;
if (percent > (float)atof(itrigger))
{
WriteOpers("*** \2WARNING\2: %s tried to set a G/K/E line mask of %s, which covers %.2f%% of the network!",user->nick,mask.c_str(),percent);
@@ -141,13 +141,13 @@ bool InspIRCd::IPMatchesEveryone(const std::string &ip, userrec* user)
if (Config->ConfValueBool(Config->config_data, "insane","ipmasks",0))
return false;
- for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
+ for (user_hash::iterator u = clientlist->begin(); u != clientlist->end(); u++)
{
if (match(u->second->GetIPString(),ip.c_str(),true))
matches++;
}
- float percent = ((float)matches / (float)clientlist.size()) * 100;
+ float percent = ((float)matches / (float)clientlist->size()) * 100;
if (percent > (float)atof(itrigger))
{
WriteOpers("*** \2WARNING\2: %s tried to set a Z line mask of %s, which covers %.2f%% of the network!",user->nick,ip.c_str(),percent);
@@ -167,13 +167,13 @@ bool InspIRCd::NickMatchesEveryone(const std::string &nick, userrec* user)
if (Config->ConfValueBool(Config->config_data, "insane","nickmasks",0))
return false;
- for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
+ for (user_hash::iterator u = clientlist->begin(); u != clientlist->end(); u++)
{
if (match(u->second->nick,nick.c_str()))
matches++;
}
- float percent = ((float)matches / (float)clientlist.size()) * 100;
+ float percent = ((float)matches / (float)clientlist->size()) * 100;
if (percent > (float)atof(itrigger))
{
WriteOpers("*** \2WARNING\2: %s tried to set a Q line mask of %s, which covers %.2f%% of the network!",user->nick,nick.c_str(),percent);
diff --git a/src/cull_list.cpp b/src/cull_list.cpp
index 628c80019..b19054b0d 100644
--- a/src/cull_list.cpp
+++ b/src/cull_list.cpp
@@ -25,22 +25,8 @@ bool CullList::IsValid(userrec* user)
if (es != exempt.end())
esignon = es->second;
- for (user_hash::iterator u = ServerInstance->clientlist.begin(); u != ServerInstance->clientlist.end(); u++)
+ for (user_hash::iterator u = ServerInstance->clientlist->begin(); u != ServerInstance->clientlist->end(); u++)
{
- /*
- * BUGFIX
- *
- * Because there is an undetermined period of time between a user existing,
- * and this function being called, we have to check for the following condition:
- *
- * Between CullList::AddItem(u) being called, and CullList::IsValid(u) being called,
- * the user with the pointer u has quit, but only to be REPLACED WITH A NEW USER WHO
- * BECAUSE OF ALLOCATION RULES, HAS THE SAME MEMORY ADDRESS! To prevent this, we
- * cross reference each pointer to the user's signon time, and if the signon times
- * do not match, we return false here to indicate this user is NOT valid as it
- * seems to differ from the pointer snapshot we got a few seconds earlier. Should
- * prevent a few random crashes during netsplits.
- */
if (user == u->second)
return (u->second->signon == esignon);
}
diff --git a/src/helperfuncs.cpp b/src/helperfuncs.cpp
index 4f303d32c..506b6e2d6 100644
--- a/src/helperfuncs.cpp
+++ b/src/helperfuncs.cpp
@@ -228,9 +228,9 @@ void InspIRCd::WriteMode(const char* modes, int flags, const char* text, ...)
userrec* InspIRCd::FindNick(const std::string &nick)
{
- user_hash::iterator iter = clientlist.find(nick);
+ user_hash::iterator iter = clientlist->find(nick);
- if (iter == clientlist.end())
+ if (iter == clientlist->end())
/* Couldn't find it */
return NULL;
@@ -239,9 +239,9 @@ userrec* InspIRCd::FindNick(const std::string &nick)
userrec* InspIRCd::FindNick(const char* nick)
{
- user_hash::iterator iter = clientlist.find(nick);
+ user_hash::iterator iter = clientlist->find(nick);
- if (iter == clientlist.end())
+ if (iter == clientlist->end())
return NULL;
return iter->second;
@@ -251,9 +251,9 @@ userrec* InspIRCd::FindNick(const char* nick)
chanrec* InspIRCd::FindChan(const char* chan)
{
- chan_hash::iterator iter = chanlist.find(chan);
+ chan_hash::iterator iter = chanlist->find(chan);
- if (iter == chanlist.end())
+ if (iter == chanlist->end())
/* Couldn't find it */
return NULL;
@@ -262,9 +262,9 @@ chanrec* InspIRCd::FindChan(const char* chan)
chanrec* InspIRCd::FindChan(const std::string &chan)
{
- chan_hash::iterator iter = chanlist.find(chan);
+ chan_hash::iterator iter = chanlist->find(chan);
- if (iter == chanlist.end())
+ if (iter == chanlist->end())
/* Couldn't find it */
return NULL;
@@ -299,20 +299,20 @@ void InspIRCd::SendError(const std::string &s)
// this function counts all users connected, wether they are registered or NOT.
int InspIRCd::UserCount()
{
- return clientlist.size();
+ return clientlist->size();
}
// this counts only registered users, so that the percentages in /MAP don't mess up when users are sitting in an unregistered state
int InspIRCd::RegisteredUserCount()
{
- return clientlist.size() - this->UnregisteredUserCount();
+ return clientlist->size() - this->UnregisteredUserCount();
}
int InspIRCd::InvisibleUserCount()
{
int c = 0;
- for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
+ for (user_hash::const_iterator i = clientlist->begin(); i != clientlist->end(); i++)
{
c += ((i->second->registered == REG_ALL) && (i->second->modes[UM_INVISIBLE]));
}
@@ -324,7 +324,7 @@ int InspIRCd::OperCount()
{
int c = 0;
- for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
+ for (user_hash::const_iterator i = clientlist->begin(); i != clientlist->end(); i++)
{
if (*(i->second->oper))
c++;
@@ -348,7 +348,7 @@ int InspIRCd::UnregisteredUserCount()
long InspIRCd::ChannelCount()
{
- return chanlist.size();
+ return chanlist->size();
}
long InspIRCd::LocalUserCount()
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 6b9359751..5cfb55ab1 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -138,10 +138,37 @@ void InspIRCd::Rehash(int status)
SI->WriteOpers("Rehashing config file %s due to SIGHUP",ServerConfig::CleanFilename(CONFIG_FILE));
SI->CloseLog();
SI->OpenLog(NULL,0);
+ SI->RehashUsersAndChans();
SI->Config->Read(false,NULL);
FOREACH_MOD_I(SI,I_OnRehash,OnRehash(""));
}
+/** Because hash_map doesnt free its buckets when we delete items (this is a 'feature')
+ * we must occasionally rehash the hash (yes really).
+ * We do this by copying the entries from the old hash to a new hash, causing all
+ * empty buckets to be weeded out of the hash. We dont do this on a timer, as its
+ * very expensive, so instead we do it when the user types /REHASH and expects a
+ * short delay anyway.
+ */
+void InspIRCd::RehashUsersAndChans()
+{
+ user_hash* old_users = this->clientlist;
+ chan_hash* old_chans = this->chanlist;
+
+ this->clientlist = new user_hash();
+ this->chanlist = new chan_hash();
+
+ for (user_hash::const_iterator n = old_users->begin(); n != old_users->end(); n++)
+ this->clientlist->insert(*n);
+
+ delete old_users;
+
+ for (chan_hash::const_iterator n = old_chans->begin(); n != old_chans->end(); n++)
+ this->chanlist->insert(*n);
+
+ delete old_chans;
+}
+
void InspIRCd::CloseLog()
{
this->Logger->Close();
@@ -234,7 +261,10 @@ InspIRCd::InspIRCd(int argc, char** argv)
modules.resize(255);
factory.resize(255);
-
+
+ this->clientlist = new user_hash();
+ this->chanlist = new chan_hash();
+
this->Config = new ServerConfig(this);
this->Config->opertypes.clear();
this->Config->operclass.clear();
@@ -565,11 +595,11 @@ bool InspIRCd::UnloadModule(const char* filename)
return false;
}
/* Give the module a chance to tidy out all its metadata */
- for (chan_hash::iterator c = this->chanlist.begin(); c != this->chanlist.end(); c++)
+ for (chan_hash::iterator c = this->chanlist->begin(); c != this->chanlist->end(); c++)
{
modules[j]->OnCleanup(TYPE_CHANNEL,c->second);
}
- for (user_hash::iterator u = this->clientlist.begin(); u != this->clientlist.end(); u++)
+ for (user_hash::iterator u = this->clientlist->begin(); u != this->clientlist->end(); u++)
{
modules[j]->OnCleanup(TYPE_USER,u->second);
}
diff --git a/src/mode.cpp b/src/mode.cpp
index 4642c296f..dfa846364 100644
--- a/src/mode.cpp
+++ b/src/mode.cpp
@@ -638,13 +638,13 @@ bool ModeParser::DelMode(ModeHandler* mh)
switch (mh->GetModeType())
{
case MODETYPE_USER:
- for (user_hash::iterator i = ServerInstance->clientlist.begin(); i != ServerInstance->clientlist.end(); i++)
+ for (user_hash::iterator i = ServerInstance->clientlist->begin(); i != ServerInstance->clientlist->end(); i++)
{
mh->RemoveMode(i->second);
}
break;
case MODETYPE_CHANNEL:
- for (chan_hash::iterator i = ServerInstance->chanlist.begin(); i != ServerInstance->chanlist.end(); i++)
+ for (chan_hash::iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
{
mh->RemoveMode(i->second);
}
diff --git a/src/modules.cpp b/src/modules.cpp
index 8c38914e9..acd2ae469 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -345,6 +345,7 @@ const std::string& InspIRCd::GetModuleName(Module* m)
void InspIRCd::RehashServer()
{
this->WriteOpers("*** Rehashing config file");
+ this->RehashUsersAndChans();
this->Config->Read(false,NULL);
}
@@ -358,7 +359,7 @@ void InspIRCd::RehashServer()
chanrec* InspIRCd::GetChannelIndex(long index)
{
int target = 0;
- for (chan_hash::iterator n = this->chanlist.begin(); n != this->chanlist.end(); n++, target++)
+ for (chan_hash::iterator n = this->chanlist->begin(); n != this->chanlist->end(); n++, target++)
{
if (index == target)
return n->second;
diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp
index a7d2485ee..aa4e1f6cd 100644
--- a/src/modules/m_check.cpp
+++ b/src/modules/m_check.cpp
@@ -128,7 +128,7 @@ class cmd_check : public command_t
long x = 0;
/* hostname or other */
- for (user_hash::const_iterator a = ServerInstance->clientlist.begin(); a != ServerInstance->clientlist.end(); a++)
+ for (user_hash::const_iterator a = ServerInstance->clientlist->begin(); a != ServerInstance->clientlist->end(); a++)
{
if (match(a->second->host, parameters[0]) || match(a->second->dhost, parameters[0]))
{
diff --git a/src/modules/m_httpd_stats.cpp b/src/modules/m_httpd_stats.cpp
index 7d11d41e4..eb9933ecc 100644
--- a/src/modules/m_httpd_stats.cpp
+++ b/src/modules/m_httpd_stats.cpp
@@ -102,8 +102,8 @@ class ModuleHttpStats : public Module
data << "<div class='totals'>";
data << "<h2>Totals</h2>";
data << "<table>";
- data << "<tr><td>Users</td><td>" << ServerInstance->clientlist.size() << "</td></tr>";
- data << "<tr><td>Channels</td><td>" << ServerInstance->chanlist.size() << "</td></tr>";
+ data << "<tr><td>Users</td><td>" << ServerInstance->clientlist->size() << "</td></tr>";
+ data << "<tr><td>Channels</td><td>" << ServerInstance->chanlist->size() << "</td></tr>";
data << "<tr><td>Opers</td><td>" << ServerInstance->all_opers.size() << "</td></tr>";
data << "<tr><td>Sockets</td><td>" << (ServerInstance->SE->GetMaxFds() - ServerInstance->SE->GetRemainingFds()) << " (Max: " << ServerInstance->SE->GetMaxFds() << " via socket engine '" << ServerInstance->SE->GetName() << "')</td></tr>";
data << "</table>";
diff --git a/src/modules/m_redirect.cpp b/src/modules/m_redirect.cpp
index 6f602e62d..b6600da91 100644
--- a/src/modules/m_redirect.cpp
+++ b/src/modules/m_redirect.cpp
@@ -66,7 +66,7 @@ class Redirect : public ModeHandler
}
else
{
- for (chan_hash::const_iterator i = ServerInstance->chanlist.begin(); i != ServerInstance->chanlist.end(); i++)
+ for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
{
if ((i->second != channel) && (i->second->IsModeSet('L')) && (irc::string(i->second->GetModeParameter('L').c_str()) == irc::string(channel->name)))
{
diff --git a/src/modules/m_safelist.cpp b/src/modules/m_safelist.cpp
index f318300c5..7441f0ea5 100644
--- a/src/modules/m_safelist.cpp
+++ b/src/modules/m_safelist.cpp
@@ -78,7 +78,7 @@ class ListTimer : public InspTimer
userrec* u = (userrec*)(*iter);
ListData* ld;
u->GetExt("safelist_cache", ld);
- if ((size_t)ld->list_position > ServerInstance->chanlist.size())
+ if ((size_t)ld->list_position > ServerInstance->chanlist->size())
{
u->Shrink("safelist_cache");
DELETE(ld);
diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp
index 864feb8b5..3290878f4 100644
--- a/src/modules/m_spanningtree.cpp
+++ b/src/modules/m_spanningtree.cpp
@@ -357,7 +357,7 @@ class TreeServer : public classbase
ServerInstance->Log(DEBUG,"Removing all users from server %s",this->ServerName.c_str());
const char* reason_s = reason.c_str();
std::vector<userrec*> time_to_die;
- for (user_hash::iterator n = ServerInstance->clientlist.begin(); n != ServerInstance->clientlist.end(); n++)
+ for (user_hash::iterator n = ServerInstance->clientlist->begin(); n != ServerInstance->clientlist->end(); n++)
{
if (!strcmp(n->second->server, this->ServerName.c_str()))
{
@@ -1880,9 +1880,9 @@ class TreeSocket : public InspSocket
const char* tempnick = params[1].c_str();
Instance->Log(DEBUG,"Introduce client %s!%s@%s",tempnick,params[4].c_str(),params[2].c_str());
- user_hash::iterator iter = this->Instance->clientlist.find(tempnick);
+ user_hash::iterator iter = this->Instance->clientlist->find(tempnick);
- if (iter != this->Instance->clientlist.end())
+ if (iter != this->Instance->clientlist->end())
{
// nick collision
Instance->Log(DEBUG,"Nick collision on %s!%s@%s: %lu %lu",tempnick,params[4].c_str(),params[2].c_str(),(unsigned long)age,(unsigned long)iter->second->age);
@@ -1892,7 +1892,7 @@ class TreeSocket : public InspSocket
}
userrec* _new = new userrec(this->Instance);
- this->Instance->clientlist[tempnick] = _new;
+ (*(this->Instance->clientlist))[tempnick] = _new;
_new->SetFd(FD_MAGIC_NUMBER);
strlcpy(_new->nick, tempnick,NICKMAX-1);
strlcpy(_new->host, params[2].c_str(),63);
@@ -2027,44 +2027,44 @@ class TreeSocket : public InspSocket
std::string buffer;
std::string n = this->Instance->Config->ServerName;
const char* sn = n.c_str();
- int iterations = 0;
+
/* Yes, these arent too nice looking, but they get the job done */
- for (std::vector<ZLine*>::iterator i = Instance->XLines->zlines.begin(); i != Instance->XLines->zlines.end(); i++, iterations++)
+ for (std::vector<ZLine*>::iterator i = Instance->XLines->zlines.begin(); i != Instance->XLines->zlines.end(); i++)
{
snprintf(data,MAXBUF,":%s ADDLINE Z %s %s %lu %lu :%s\r\n",sn,(*i)->ipaddr,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
buffer.append(data);
}
- for (std::vector<QLine*>::iterator i = Instance->XLines->qlines.begin(); i != Instance->XLines->qlines.end(); i++, iterations++)
+ for (std::vector<QLine*>::iterator i = Instance->XLines->qlines.begin(); i != Instance->XLines->qlines.end(); i++)
{
snprintf(data,MAXBUF,":%s ADDLINE Q %s %s %lu %lu :%s\r\n",sn,(*i)->nick,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
buffer.append(data);
}
- for (std::vector<GLine*>::iterator i = Instance->XLines->glines.begin(); i != Instance->XLines->glines.end(); i++, iterations++)
+ for (std::vector<GLine*>::iterator i = Instance->XLines->glines.begin(); i != Instance->XLines->glines.end(); i++)
{
snprintf(data,MAXBUF,":%s ADDLINE G %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
buffer.append(data);
}
- for (std::vector<ELine*>::iterator i = Instance->XLines->elines.begin(); i != Instance->XLines->elines.end(); i++, iterations++)
+ for (std::vector<ELine*>::iterator i = Instance->XLines->elines.begin(); i != Instance->XLines->elines.end(); i++)
{
snprintf(data,MAXBUF,":%s ADDLINE E %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
buffer.append(data);
}
- for (std::vector<ZLine*>::iterator i = Instance->XLines->pzlines.begin(); i != Instance->XLines->pzlines.end(); i++, iterations++)
+ for (std::vector<ZLine*>::iterator i = Instance->XLines->pzlines.begin(); i != Instance->XLines->pzlines.end(); i++)
{
snprintf(data,MAXBUF,":%s ADDLINE Z %s %s %lu %lu :%s\r\n",sn,(*i)->ipaddr,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
buffer.append(data);
}
- for (std::vector<QLine*>::iterator i = Instance->XLines->pqlines.begin(); i != Instance->XLines->pqlines.end(); i++, iterations++)
+ for (std::vector<QLine*>::iterator i = Instance->XLines->pqlines.begin(); i != Instance->XLines->pqlines.end(); i++)
{
snprintf(data,MAXBUF,":%s ADDLINE Q %s %s %lu %lu :%s\r\n",sn,(*i)->nick,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
buffer.append(data);
}
- for (std::vector<GLine*>::iterator i = Instance->XLines->pglines.begin(); i != Instance->XLines->pglines.end(); i++, iterations++)
+ for (std::vector<GLine*>::iterator i = Instance->XLines->pglines.begin(); i != Instance->XLines->pglines.end(); i++)
{
snprintf(data,MAXBUF,":%s ADDLINE G %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
buffer.append(data);
}
- for (std::vector<ELine*>::iterator i = Instance->XLines->pelines.begin(); i != Instance->XLines->pelines.end(); i++, iterations++)
+ for (std::vector<ELine*>::iterator i = Instance->XLines->pelines.begin(); i != Instance->XLines->pelines.end(); i++)
{
snprintf(data,MAXBUF,":%s ADDLINE E %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
buffer.append(data);
@@ -2079,10 +2079,9 @@ class TreeSocket : public InspSocket
{
char data[MAXBUF];
std::deque<std::string> list;
- int iterations = 0;
std::string n = this->Instance->Config->ServerName;
const char* sn = n.c_str();
- for (chan_hash::iterator c = this->Instance->chanlist.begin(); c != this->Instance->chanlist.end(); c++, iterations++)
+ for (chan_hash::iterator c = this->Instance->chanlist->begin(); c != this->Instance->chanlist->end(); c++)
{
SendFJoins(Current, c->second);
if (*c->second->topic)
@@ -2106,8 +2105,7 @@ class TreeSocket : public InspSocket
char data[MAXBUF];
std::deque<std::string> list;
std::string dataline;
- int iterations = 0;
- for (user_hash::iterator u = this->Instance->clientlist.begin(); u != this->Instance->clientlist.end(); u++, iterations++)
+ for (user_hash::iterator u = this->Instance->clientlist->begin(); u != this->Instance->clientlist->end(); u++)
{
if (u->second->registered == REG_ALL)
{
@@ -4342,13 +4340,13 @@ class ModuleSpanningTree : public Module
float percent;
char text[80];
- if (ServerInstance->clientlist.size() == 0) {
+ if (ServerInstance->clientlist->size() == 0) {
// If there are no users, WHO THE HELL DID THE /MAP?!?!?!
percent = 0;
}
else
{
- percent = ((float)Current->GetUserCount() / (float)ServerInstance->clientlist.size()) * 100;
+ percent = ((float)Current->GetUserCount() / (float)ServerInstance->clientlist->size()) * 100;
}
snprintf(text, 80, "%s %s%5d [%5.2f%%]", Current->GetName().c_str(), spacer, Current->GetUserCount(), percent);
totusers += Current->GetUserCount();
diff --git a/src/modules/m_spy.cpp b/src/modules/m_spy.cpp
index 4ef628436..de48284ba 100644
--- a/src/modules/m_spy.cpp
+++ b/src/modules/m_spy.cpp
@@ -85,7 +85,7 @@ class cmd_spylist : public command_t
{
ServerInstance->WriteOpers("*** Oper %s used SPYLIST to list +s/+p channels and keys.",user->nick);
user->WriteServ("321 %s Channel :Users Name",user->nick);
- for (chan_hash::const_iterator i = ServerInstance->chanlist.begin(); i != ServerInstance->chanlist.end(); i++)
+ for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
{
if (pcnt && !match(i->second->name, parameters[0]))
continue;
diff --git a/src/modules/m_tline.cpp b/src/modules/m_tline.cpp
index 65167cece..801218377 100644
--- a/src/modules/m_tline.cpp
+++ b/src/modules/m_tline.cpp
@@ -39,7 +39,7 @@ class cmd_tline : public command_t
float n_match_host = 0;
float n_match_ip = 0;
- for (user_hash::const_iterator u = ServerInstance->clientlist.begin(); u != ServerInstance->clientlist.end(); u++)
+ for (user_hash::const_iterator u = ServerInstance->clientlist->begin(); u != ServerInstance->clientlist->end(); u++)
{
n_counted++;
if (match(u->second->GetFullRealHost(),parameters[0]))
diff --git a/src/users.cpp b/src/users.cpp
index 268e08d2f..712214100 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -761,7 +761,7 @@ void userrec::UnOper()
void userrec::QuitUser(InspIRCd* Instance, userrec *user, const std::string &quitreason)
{
- user_hash::iterator iter = Instance->clientlist.find(user->nick);
+ user_hash::iterator iter = Instance->clientlist->find(user->nick);
std::string reason = quitreason;
if (reason.length() > MAXQUIT - 1)
@@ -814,15 +814,16 @@ void userrec::QuitUser(InspIRCd* Instance, userrec *user, const std::string &qui
user->AddToWhoWas();
}
- if (iter != Instance->clientlist.end())
+ if (iter != Instance->clientlist->end())
{
Instance->Log(DEBUG,"deleting user hash value %lx",(unsigned long)user);
if (IS_LOCAL(user))
{
- if (find(Instance->local_users.begin(),Instance->local_users.end(),user) != Instance->local_users.end())
- Instance->local_users.erase(find(Instance->local_users.begin(),Instance->local_users.end(),user));
+ std::vector<userrec*>::iterator x = find(Instance->local_users.begin(),Instance->local_users.end(),user);
+ if (x != Instance->local_users.end())
+ Instance->local_users.erase(x);
}
- Instance->clientlist.erase(iter);
+ Instance->clientlist->erase(iter);
DELETE(user);
}
}
@@ -977,7 +978,7 @@ void userrec::AddToWhoWas()
void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached, insp_inaddr ip)
{
std::string tempnick = ConvToStr(socket) + "-unknown";
- user_hash::iterator iter = Instance->clientlist.find(tempnick);
+ user_hash::iterator iter = Instance->clientlist->find(tempnick);
const char *ipaddr = insp_ntoa(ip);
userrec* New;
int j = 0;
@@ -991,17 +992,17 @@ void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached,
* this was probably the cause of 'server ignores me when i hammer it with reconnects'
* issue in earlier alphas/betas
*/
- if (iter != Instance->clientlist.end())
+ if (iter != Instance->clientlist->end())
{
userrec* goner = iter->second;
DELETE(goner);
- Instance->clientlist.erase(iter);
+ Instance->clientlist->erase(iter);
}
Instance->Log(DEBUG,"AddClient: %d %d %s",socket,port,ipaddr);
New = new userrec(Instance);
- Instance->clientlist[tempnick] = New;
+ (*(Instance->clientlist))[tempnick] = New;
New->fd = socket;
strlcpy(New->nick,tempnick.c_str(),NICKMAX-1);
@@ -1198,18 +1199,18 @@ userrec* userrec::UpdateNickHash(const char* New)
try
{
//user_hash::iterator newnick;
- user_hash::iterator oldnick = ServerInstance->clientlist.find(this->nick);
+ user_hash::iterator oldnick = ServerInstance->clientlist->find(this->nick);
if (!strcasecmp(this->nick,New))
return oldnick->second;
- if (oldnick == ServerInstance->clientlist.end())
+ if (oldnick == ServerInstance->clientlist->end())
return NULL; /* doesnt exist */
userrec* olduser = oldnick->second;
- ServerInstance->clientlist[New] = olduser;
- ServerInstance->clientlist.erase(oldnick);
- return ServerInstance->clientlist[New];
+ (*(ServerInstance->clientlist))[New] = olduser;
+ ServerInstance->clientlist->erase(oldnick);
+ return olduser;
}
catch (...)
@@ -1949,12 +1950,12 @@ void userrec::PurgeEmptyChannels()
for (std::vector<chanrec*>::iterator n = to_delete.begin(); n != to_delete.end(); n++)
{
chanrec* thischan = *n;
- chan_hash::iterator i2 = ServerInstance->chanlist.find(thischan->name);
- if (i2 != ServerInstance->chanlist.end())
+ chan_hash::iterator i2 = ServerInstance->chanlist->find(thischan->name);
+ if (i2 != ServerInstance->chanlist->end())
{
FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(i2->second));
DELETE(i2->second);
- ServerInstance->chanlist.erase(i2);
+ ServerInstance->chanlist->erase(i2);
this->chans.erase(*n);
}
}