summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2007-03-11 15:53:34 +0000
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2007-03-11 15:53:34 +0000
commit52214a3195d062bc45522e7da58bbe7611d040f6 (patch)
tree9648e735b327dab6cf98804bb39ea4770214b8ca
parent9802f6f93554ef1266ba6cac41a7752d25a35380 (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
-rw-r--r--include/modules.h6
-rw-r--r--src/modules.cpp1
-rw-r--r--src/modules/m_safelist.cpp197
-rw-r--r--src/socketengine_epoll.cpp1
-rw-r--r--src/users.cpp5
5 files changed, 72 insertions, 138 deletions
diff --git a/include/modules.h b/include/modules.h
index e90c66fe9..793ccdc98 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -75,7 +75,7 @@ enum MessageType {
* ipv4 servers, so this value will be ten times as
* high on ipv6 servers.
*/
-#define NATIVE_API_VERSION 11016
+#define NATIVE_API_VERSION 11017
#ifdef IPV6
#define API_VERSION (NATIVE_API_VERSION * 10)
#else
@@ -394,7 +394,7 @@ enum Implementation { I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUse
I_OnPostLocalTopicChange, I_OnEvent, I_OnRequest, I_OnOperCompre, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan, I_OnDelBan,
I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketWrite, I_OnRawSocketRead, I_OnChangeLocalUserGECOS, I_OnUserRegister,
I_OnOperCompare, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnCancelAway, I_OnUserList,
- I_OnPostCommand, I_OnPostJoin, I_OnWhoisLine, I_OnBuildExemptList, I_OnRawSocketConnect, I_OnGarbageCollect };
+ I_OnPostCommand, I_OnPostJoin, I_OnWhoisLine, I_OnBuildExemptList, I_OnRawSocketConnect, I_OnGarbageCollect, I_OnBufferFlushed };
/** Base class for all InspIRCd modules
* This class is the base class for InspIRCd modules. All modules must inherit from this class,
@@ -1350,6 +1350,8 @@ class Module : public Extensible
* method is called when it is time to do that.
*/
virtual void OnGarbageCollect();
+
+ virtual void OnBufferFlushed(userrec* user);
};
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 &parameter)
{
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)