summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/channels.h9
-rw-r--r--include/inspircd.h2
-rw-r--r--src/channels.cpp20
-rw-r--r--src/commands.cpp23
-rw-r--r--src/inspircd.cpp75
5 files changed, 73 insertions, 56 deletions
diff --git a/include/channels.h b/include/channels.h
index 633d7edef..9b74c546d 100644
--- a/include/channels.h
+++ b/include/channels.h
@@ -101,6 +101,10 @@ class chanrec : public Extensible
* Plugins may use this field in any way they see fit.
*/
char custom_modes[MAXMODES]; /* modes handled by modules */
+
+ /** Count of users on the channel used for fast user counting
+ */
+ long users;
/** Channel topic.
* If this is an empty string, no channel topic is set.
@@ -178,6 +182,11 @@ class chanrec : public Extensible
*/
std::string GetModeParameter(char mode);
+ void IncUserCounter();
+ void DecUserCounter();
+ long GetUserCounter();
+
+
/** Creates a channel record and initialises it with default values
*/
chanrec();
diff --git a/include/inspircd.h b/include/inspircd.h
index 220379d57..10852631a 100644
--- a/include/inspircd.h
+++ b/include/inspircd.h
@@ -132,7 +132,7 @@ void call_handler(const char* commandname,char **parameters, int pcnt, userrec *
long GetRevision();
int loop_call(handlerfunc fn, char **parameters, int pcnt, userrec *u, int start, int end, int joins);
void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason);
-void purge_empty_chans(void);
+void purge_empty_chans(userrec* user);
char* Passwd(userrec *user);
bool IsDenied(userrec *user);
void AddWhoWas(userrec* u);
diff --git a/src/channels.cpp b/src/channels.cpp
index 05bc7fa0d..41ca0468f 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -117,7 +117,7 @@ chanrec::chanrec()
strcpy(topic,"");
strcpy(setby,"");
strcpy(key,"");
- created = topicset = limit = 0;
+ created = topicset = limit = users = 0;
topiclock = noexternal = inviteonly = moderated = secret = c_private = false;
}
@@ -197,3 +197,21 @@ std::string chanrec::GetModeParameter(char mode)
}
return std::string("");
}
+
+void chanrec::IncUserCounter()
+{
+ this->users++;
+ log(DEBUG,"Incremented channel user count for %s to %lu",name,(unsigned long)users);
+}
+
+void chanrec::DecUserCounter()
+{
+ if (this->users > 0)
+ this->users--;
+ log(DEBUG,"Decremented channel user count for %s to %lu",name,(unsigned long)users);
+}
+
+long chanrec::GetUserCounter()
+{
+ return (this->users);
+}
diff --git a/src/commands.cpp b/src/commands.cpp
index 9f3013546..a50fdf666 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -385,12 +385,13 @@ void handle_kill(char **parameters, int pcnt, userrec *user)
if (iter != clientlist.end())
{
log(DEBUG,"deleting user hash value %d",iter->second);
- if ((iter->second) && (user->registered == 7)) {
- delete iter->second;
- }
clientlist.erase(iter);
}
- purge_empty_chans();
+ if (u->registered == 7)
+ {
+ purge_empty_chans(u);
+ }
+ delete u;
}
else
{
@@ -934,14 +935,10 @@ void handle_quit(char **parameters, int pcnt, userrec *user)
if (iter != clientlist.end())
{
clientlist.erase(iter);
- log(DEBUG,"deleting user hash value %d",iter->second);
- //if ((user) && (user->registered == 7)) {
- //delete user;
- //}
}
if (user->registered == 7) {
- purge_empty_chans();
+ purge_empty_chans(user);
}
}
@@ -2048,13 +2045,13 @@ void handle_Q(char token,char* params,serverrec* source,serverrec* reply, char*
if (iter != clientlist.end())
{
log(DEBUG,"deleting user hash value %d",iter->second);
- if ((iter->second) && (user->registered == 7)) {
- delete iter->second;
- }
clientlist.erase(iter);
}
- purge_empty_chans();
+ if (user->registered == 7)
+ {
+ purge_empty_chans(user);
+ }
}
}
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 8da38a225..b28dd9281 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -1219,35 +1219,39 @@ long GetMaxBans(char* name)
}
-void purge_empty_chans(void)
+void purge_empty_chans(userrec* u)
{
+
int go_again = 1, purge = 0;
-
- while (go_again)
+
+ // firstly decrement the count on each channel
+ for (int f = 0; f < MAXCHANS; f++)
+ if (u->chans[f].channel)
+ u->chans[f].channel->DecUserCounter();
+
+ for (int i = 0; i < MAXCHANS; i++)
{
- go_again = 0;
- for (chan_hash::iterator i = chanlist.begin(); i != chanlist.end(); i++)
+ if (u->chans[i].channel)
{
- if (i->second) {
- if (!usercount(i->second))
- {
- /* kill the record */
- if (i != chanlist.end())
- {
- log(DEBUG,"del_channel: destroyed: %s",i->second->name);
- if (i->second)
- delete i->second;
- chanlist.erase(i);
- go_again = 1;
- purge++;
- break;
- }
- }
- else
+ if (!usercount(u->chans[i].channel))
+ {
+ chan_hash::iterator i2 = chanlist.find(u->chans[i].channel->name);
+ /* kill the record */
+ if (i2 != chanlist.end())
{
- log(DEBUG,"skipped purge for %s",i->second->name);
+ log(DEBUG,"del_channel: destroyed: %s",i2->second->name);
+ if (i2->second)
+ delete i2->second;
+ chanlist.erase(i2);
+ go_again = 1;
+ purge++;
+ u->chans[i].channel = NULL;
}
}
+ else
+ {
+ log(DEBUG,"skipped purge for %s",u->chans[i].channel->name);
+ }
}
}
log(DEBUG,"completed channel purge, killed %d",purge);
@@ -1413,28 +1417,12 @@ int usercount_i(chanrec *c)
int usercount(chanrec *c)
{
- int count = 0;
-
if (!c)
{
log(DEFAULT,"*** BUG *** usercount was given an invalid parameter");
return 0;
}
-
- strcpy(list,"");
- for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
- {
- if (i->second)
- {
- if (has_channel(i->second,c))
- {
- if ((isnick(i->second->nick)) && (i->second->registered == 7))
- {
- count++;
- }
- }
- }
- }
+ int count = c->GetUserCounter();
log(DEBUG,"usercount: %s %d",c->name,count);
return count;
}
@@ -1645,6 +1633,7 @@ chanrec* add_channel(userrec *user, const char* cn, const char* key, bool overri
user->chans[index].uc_modes = 0;
}
user->chans[index].channel = Ptr;
+ Ptr->IncUserCounter();
WriteChannel(Ptr,user,"JOIN :%s",Ptr->name);
if (!override) // we're not overriding... so this isnt part of a netburst, broadcast it.
@@ -1745,6 +1734,8 @@ chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool
break;
}
}
+
+ Ptr->DecUserCounter();
/* if there are no users left on the channel */
if (!usercount(Ptr))
@@ -1828,6 +1819,8 @@ void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason)
}
}
+ Ptr->DecUserCounter();
+
/* if there are no users left on the channel */
if (!usercount(Ptr))
{
@@ -2063,7 +2056,7 @@ void kill_link(userrec *user,const char* r)
}
if (user->registered == 7) {
- purge_empty_chans();
+ purge_empty_chans(user);
}
//user = NULL;
}
@@ -2114,7 +2107,7 @@ void kill_link_silent(userrec *user,const char* r)
}
if (user->registered == 7) {
- purge_empty_chans();
+ purge_empty_chans(user);
}
}