diff options
author | brain <brain@e03df62e-2008-0410-955e-edbf42e46eb7> | 2007-03-11 15:53:34 +0000 |
---|---|---|
committer | brain <brain@e03df62e-2008-0410-955e-edbf42e46eb7> | 2007-03-11 15:53:34 +0000 |
commit | 52214a3195d062bc45522e7da58bbe7611d040f6 (patch) | |
tree | 9648e735b327dab6cf98804bb39ea4770214b8ca /src | |
parent | 9802f6f93554ef1266ba6cac41a7752d25a35380 (diff) |
Added OnBufferFlush, improved m_safelist, no longer works on a timer but works on the writeability state of each user who is listing.
Seems to test fine with 500 reet bots all listing at once. (doesnt lock up the ircd while listing them all any more, either, just lags a small amount)
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@6657 e03df62e-2008-0410-955e-edbf42e46eb7
Diffstat (limited to 'src')
-rw-r--r-- | src/modules.cpp | 1 | ||||
-rw-r--r-- | src/modules/m_safelist.cpp | 197 | ||||
-rw-r--r-- | src/socketengine_epoll.cpp | 1 | ||||
-rw-r--r-- | src/users.cpp | 5 |
4 files changed, 68 insertions, 136 deletions
diff --git a/src/modules.cpp b/src/modules.cpp index 7505dd21e..46272a2bd 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -192,6 +192,7 @@ int Module::OnUserList(userrec* user, chanrec* Ptr) { return 0; }; int Module::OnWhoisLine(userrec* user, userrec* dest, int &numeric, std::string &text) { return 0; }; void Module::OnBuildExemptList(MessageType message_type, chanrec* chan, userrec* sender, char status, CUList &exempt_list) { }; void Module::OnGarbageCollect() { }; +void Module::OnBufferFlushed(userrec* user) { }; long InspIRCd::PriorityAfter(const std::string &modulename) { diff --git a/src/modules/m_safelist.cpp b/src/modules/m_safelist.cpp index af7fefc6a..1bdfb97bd 100644 --- a/src/modules/m_safelist.cpp +++ b/src/modules/m_safelist.cpp @@ -6,7 +6,7 @@ * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see - * the file COPYING for details. + * the file COPYING for details. * * --------------------------------------------------- */ @@ -33,143 +33,26 @@ class ListData : public classbase }; /* $ModDesc: A module overriding /list, and making it safe - stop those sendq problems. */ - -typedef std::vector<userrec *> UserList; -UserList listusers; /* vector of people doing a /list */ -class ListTimer *timer; - -/** To create a timer which recurs every second, we inherit from InspTimer. - * InspTimer is only one-shot however, so at the end of each Tick() we simply - * insert another of ourselves into the pending queue :) - */ -class ListTimer : public InspTimer -{ - private: - - char buffer[MAXBUF]; - chanrec *chan; - InspIRCd* ServerInstance; - const std::string glob; - size_t ServerNameSize; - - public: - - ListTimer(InspIRCd* Instance, long interval) : InspTimer(interval,Instance->Time()), ServerInstance(Instance) - { - ServerNameSize = 4 + strlen(ServerInstance->Config->ServerName); - } - - virtual void Tick(time_t TIME) - { - bool go_again = true; - - while (go_again) - { - go_again = false; - for (UserList::iterator iter = listusers.begin(); iter != listusers.end(); iter++) - { - /* - * What we do here: - * - Get where they are up to - * - If it's more than total number of channels, erase - * them from the iterator, set go_again to true - * - If not, spool more channels - */ - userrec* u = (userrec*)(*iter); - ListData* ld; - u->GetExt("safelist_cache", ld); - if ((size_t)ld->list_position > ServerInstance->chanlist->size()) - { - u->Shrink("safelist_cache"); - DELETE(ld); - listusers.erase(iter); - go_again = true; - break; - } - chan = NULL; - /* Attempt to fill up to 25% the user's sendq with /LIST output */ - long amount_sent = 0; - do - { - if (!ld->list_position) - u->WriteServ("321 %s Channel :Users Name",u->nick); - chan = ServerInstance->GetChannelIndex(ld->list_position); - /* spool details */ - bool has_user = (chan && chan->HasUser(u)); - if ((chan) && (chan->modes[CM_PRIVATE])) - { - bool display = match(chan->name, ld->glob.c_str()); - long users = chan->GetUserCounter(); - if ((users) && (display)) - { - int counter = snprintf(buffer, MAXBUF, "322 %s *", u->nick); - amount_sent += counter + ServerNameSize; - u->WriteServ(std::string(buffer)); - } - } - else if ((chan) && (((!(chan->modes[CM_PRIVATE])) && (!(chan->modes[CM_SECRET]))) || (has_user))) - { - bool display = match(chan->name, ld->glob.c_str()); - long users = chan->GetUserCounter(); - - if ((users) && (display)) - { - int counter = snprintf(buffer, MAXBUF, "322 %s %s %ld :[+%s] %s",u->nick, chan->name, users, chan->ChanModes(has_user), chan->topic); - /* Increment total plus linefeed */ - amount_sent += counter + ServerNameSize; - u->WriteServ(std::string(buffer)); - } - } - else - { - if (!chan) - { - if (!ld->list_ended) - { - ld->list_ended = true; - u->WriteServ("323 %s :End of channel list.",u->nick); - } - } - } - - ld->list_position++; - } - while ((chan != NULL) && (amount_sent < (u->sendqmax / 4))); - } - } - - if (listusers.size()) - { - timer = new ListTimer(ServerInstance,1); - ServerInstance->Timers->AddTimer(timer); - } - else - { - timer = NULL; - } - } -}; class ModuleSafeList : public Module { time_t ThrottleSecs; + size_t ServerNameSize; public: ModuleSafeList(InspIRCd* Me) : Module::Module(Me) { - timer = NULL; OnRehash(NULL, ""); } virtual ~ModuleSafeList() { - if (timer) - ServerInstance->Timers->DelTimer(timer); } virtual void OnRehash(userrec* user, const std::string ¶meter) { ConfigReader MyConf(ServerInstance); ThrottleSecs = MyConf.ReadInteger("safelist", "throttle", "60", 0, true); + ServerNameSize = strlen(ServerInstance->Config->ServerName) + 4; } virtual Version GetVersion() @@ -179,7 +62,7 @@ class ModuleSafeList : public Module void Implements(char* List) { - List[I_OnPreCommand] = List[I_OnCleanup] = List[I_OnUserQuit] = List[I_On005Numeric] = List[I_OnRehash] = 1; + List[I_OnBufferFlushed] = List[I_OnPreCommand] = List[I_OnCleanup] = List[I_OnUserQuit] = List[I_On005Numeric] = List[I_OnRehash] = 1; } /* @@ -240,21 +123,72 @@ class ModuleSafeList : public Module */ ld = new ListData(0,ServerInstance->Time(), pcnt ? parameters[0] : "*"); user->Extend("safelist_cache", ld); - listusers.push_back(user); time_t* llt = new time_t; *llt = ServerInstance->Time(); user->Extend("safelist_last", llt); - if (!timer) - { - timer = new ListTimer(ServerInstance,1); - ServerInstance->Timers->AddTimer(timer); - } + user->WriteServ("321 %s Channel :Users Name",user->nick); return 1; } + virtual void OnBufferFlushed(userrec* user) + { + char buffer[MAXBUF]; + ListData* ld; + if (user->GetExt("safelist_cache", ld)) + { + chanrec* chan = NULL; + long amount_sent = 0; + do + { + chan = ServerInstance->GetChannelIndex(ld->list_position); + bool has_user = (chan && chan->HasUser(user)); + if ((chan) && (chan->modes[CM_PRIVATE])) + { + bool display = match(chan->name, ld->glob.c_str()); + long users = chan->GetUserCounter(); + if ((users) && (display)) + { + int counter = snprintf(buffer, MAXBUF, "322 %s *", user->nick); + amount_sent += counter + ServerNameSize; + user->WriteServ(std::string(buffer)); + } + } + else if ((chan) && (((!(chan->modes[CM_PRIVATE])) && (!(chan->modes[CM_SECRET]))) || (has_user))) + { + bool display = match(chan->name, ld->glob.c_str()); + long users = chan->GetUserCounter(); + if ((users) && (display)) + { + int counter = snprintf(buffer, MAXBUF, "322 %s %s %ld :[+%s] %s",user->nick, chan->name, users, chan->ChanModes(has_user), chan->topic); + amount_sent += counter + ServerNameSize; + user->WriteServ(std::string(buffer)); + } + } + else + { + if (!chan) + { + if (!ld->list_ended) + { + ld->list_ended = true; + user->WriteServ("323 %s :End of channel list.",user->nick); + } + } + } + ld->list_position++; + } + while ((chan != NULL) && (amount_sent < (user->sendqmax / 4))); + if (ld->list_ended) + { + user->Shrink("safelist_cache"); + DELETE(ld); + } + } + } + virtual void OnCleanup(int target_type, void* item) { if(target_type == TYPE_USER) @@ -267,15 +201,6 @@ class ModuleSafeList : public Module u->Shrink("safelist_cache"); DELETE(ld); } - for (UserList::iterator iter = listusers.begin(); iter != listusers.end(); iter++) - { - userrec* u2 = (userrec*)(*iter); - if (u2 == u) - { - listusers.erase(iter); - break; - } - } time_t* last_list_time; u->GetExt("safelist_last", last_list_time); if (last_list_time) diff --git a/src/socketengine_epoll.cpp b/src/socketengine_epoll.cpp index 4ed68ca57..732ce1e77 100644 --- a/src/socketengine_epoll.cpp +++ b/src/socketengine_epoll.cpp @@ -113,6 +113,7 @@ int EPollEngine::DispatchEvents() socklen_t codesize; int errcode; int i = epoll_wait(EngineHandle, events, MAX_DESCRIPTORS, 1000); + ServerInstance->Log(DEBUG,"%d events", i); for (int j = 0; j < i; j++) { if (events[j].events & EPOLLHUP) diff --git a/src/users.cpp b/src/users.cpp index b10753b8b..9f54975b4 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -734,6 +734,11 @@ void userrec::FlushWriteBuf() { ServerInstance->Log(DEBUG,"Exception in userrec::FlushWriteBuf()"); } + + if (this->sendq.empty()) + { + FOREACH_MOD(I_OnBufferFlushed,OnBufferFlushed(this)); + } } void userrec::SetWriteError(const std::string &error) |