diff options
-rw-r--r-- | include/channels.h | 9 | ||||
-rw-r--r-- | include/inspircd.h | 2 | ||||
-rw-r--r-- | src/channels.cpp | 20 | ||||
-rw-r--r-- | src/commands.cpp | 23 | ||||
-rw-r--r-- | src/inspircd.cpp | 75 |
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); } } |