summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeavey <peavey@e03df62e-2008-0410-955e-edbf42e46eb7>2006-11-13 00:45:37 +0000
committerpeavey <peavey@e03df62e-2008-0410-955e-edbf42e46eb7>2006-11-13 00:45:37 +0000
commit41f62a2a3badd6b7dbffb4fdb995c41ef709462c (patch)
treeb87fbf24939d47fe28a066716e0a61682f2d8f87
parentf09dc35b5b03eb19e70333fbb8e5fe6f92c7edee (diff)
add <whowas> config option to control whowas behaviour. *may break*
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@5731 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--docs/inspircd.conf.example26
-rw-r--r--include/configreader.h13
-rw-r--r--include/inspircd.h4
-rw-r--r--include/users.h9
-rw-r--r--src/configreader.cpp27
-rw-r--r--src/users.cpp55
6 files changed, 131 insertions, 3 deletions
diff --git a/docs/inspircd.conf.example b/docs/inspircd.conf.example
index aac661703..a3d90c700 100644
--- a/docs/inspircd.conf.example
+++ b/docs/inspircd.conf.example
@@ -741,6 +741,32 @@
notimesync="no"
allowhalfop="yes">
+#-#-#-#-#-#-#-#-#-#-#-#-#- WHOWAS OPTIONS -#-#-#-#-#-#-#-#-#-#-#-#-#
+# #
+# This tag lets you define the behaviour of the /whowas command of #
+# your server. #
+# #
+# groupsize - Controls the maximum entries per nick shown when #
+# performing a /whowas nick. #
+# #
+# maxgroups - The maximum number of nickgroups that can be added #
+# to the list. If max is reached, oldest group will #
+# be deleted first like a FIFO. A groupsize of 3 and #
+# a maxgroups of 5000 will allow for 5000 nicks to #
+# be stored with a history of 3, thus giving a total #
+# of 3 * 5000 = 15000 entries. #
+# #
+# maxkeep - The maximum time a nick is kept in the whowas list #
+# before being pruned. Time may be specified in #
+# seconds, or in the following format: 1y2w3d4h5m6s #
+# meaning one year, two weeks, three days, 4 hours, #
+# 5 minutes and 6 seconds. All fields in this format #
+# are optional. Minimum is 1 hour, if less InspIRCd #
+# will default back to 1 hour. #
+# #
+#<whowas groupsize="10" #
+# maxgroups="100000" #
+# maxkeep="3d"> #
#-#-#-#-#-#-#-#-#-#-#-#-#- MODULE OPTIONS -#-#-#-#-#-#-#-#-#-#-#-#-#
diff --git a/include/configreader.h b/include/configreader.h
index e6591e7a8..516c6a6ed 100644
--- a/include/configreader.h
+++ b/include/configreader.h
@@ -120,6 +120,19 @@ class ServerConfig : public Extensible
*/
ConfigDataHash config_data;
+ /** Max number of WhoWas entries per user.
+ */
+ int WhoWasGroupSize;
+
+ /** Max number of cumulative user-entries in WhoWas.
+ * When max reached and added to, push out oldest entry FIFO style.
+ */
+ int WhoWasMaxGroups;
+
+ /** Max seconds a user is kept in WhoWas before being pruned.
+ */
+ int WhoWasMaxKeep;
+
/** Holds the server name of the local server
* as defined by the administrator.
*/
diff --git a/include/inspircd.h b/include/inspircd.h
index baa1fb589..7fecf22ae 100644
--- a/include/inspircd.h
+++ b/include/inspircd.h
@@ -401,6 +401,10 @@ class InspIRCd : public classbase
*/
irc::whowas::whowas_users whowas;
+ /** Whowas container, contains a map of time_t to users tracked by WHOWAS
+ */
+ irc::whowas::whowas_users_fifo whowas_fifo;
+
/** DNS class, provides resolver facilities to the core and modules
*/
DNS* Res;
diff --git a/include/users.h b/include/users.h
index 018336e77..ce8f4eb28 100644
--- a/include/users.h
+++ b/include/users.h
@@ -828,9 +828,18 @@ namespace irc
*/
typedef std::map<irc::string,whowas_set*> whowas_users;
+ /** Sets of time and users in whowas list
+ */
+ typedef std::map<time_t, irc::string> whowas_users_fifo;
+
/** Called every hour by the core to remove expired entries
*/
void MaintainWhoWas(InspIRCd* ServerInstance, time_t TIME);
+
+ /** Prune for WhoWasGroupSize, WhoWasMaxGroups and
+ * WhoWasMaxKeep on rehash
+ */
+ void PruneWhoWas(InspIRCd* ServerInstance, time_t TIME);
};
};
diff --git a/src/configreader.cpp b/src/configreader.cpp
index 1b38e7155..ea5d09db9 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -41,6 +41,9 @@ ServerConfig::ServerConfig(InspIRCd* Instance) : ServerInstance(Instance)
debugging = 0;
LogLevel = DEFAULT;
maxbans.clear();
+ WhoWasGroupSize = 10;
+ WhoWasMaxGroups = WhoWasGroupSize * MAXCLIENTS;
+ WhoWasMaxKeep = 3600*24*3; // 3 days
}
void ServerConfig::ClearStack()
@@ -319,6 +322,24 @@ bool ValidateRules(ServerConfig* conf, const char* tag, const char* value, void*
return true;
}
+bool ValidateWhoWas(ServerConfig* conf, const char* tag, const char* value, void* data)
+{
+ const char* max = (const char*)data;
+ conf->WhoWasMaxKeep = conf->GetInstance()->Duration(max);
+
+ if (conf->WhoWasGroupSize < 0)
+ conf->WhoWasGroupSize = 0;
+
+ if (conf->WhoWasMaxGroups < 0)
+ conf->WhoWasMaxGroups = 0;
+
+ if (conf->WhoWasMaxKeep < 3600)
+ conf->WhoWasMaxKeep = 3600;
+
+ irc::whowas::PruneWhoWas(conf->GetInstance(), conf->GetInstance()->Time());
+ return true;
+}
+
/* Callback called before processing the first <connect> tag
*/
bool InitConnect(ServerConfig* conf, const char* tag)
@@ -511,6 +532,7 @@ bool DoneMaxBans(ServerConfig* conf, const char* tag)
void ServerConfig::Read(bool bail, userrec* user)
{
char debug[MAXBUF]; /* Temporary buffer for debugging value */
+ char maxkeep[MAXBUF]; /* Temporary buffer for WhoWasMaxKeep value */
char* data[12]; /* Temporary buffers for reading multiple occurance tags into */
void* ptr[12]; /* Temporary pointers for passing to callbacks */
int r_i[12]; /* Temporary array for casting */
@@ -545,7 +567,7 @@ void ServerConfig::Read(bool bail, userrec* user)
{"dns", "timeout", &this->dns_timeout, DT_INTEGER, ValidateDnsTimeout},
{"options", "moduledir", &this->ModPath, DT_CHARPTR, ValidateModPath},
{"disabled", "commands", &this->DisabledCommands, DT_CHARPTR, NoValidation},
- {"options", "userstats", &this->UserStats, DT_CHARPTR, NoValidation},
+ {"options", "userstats", &this->UserStats, DT_CHARPTR, NoValidation},
{"options", "customversion", &this->CustomVersion, DT_CHARPTR, NoValidation},
{"options", "hidesplits", &this->HideSplits, DT_BOOLEAN, NoValidation},
{"options", "hidebans", &this->HideBans, DT_BOOLEAN, NoValidation},
@@ -556,6 +578,9 @@ void ServerConfig::Read(bool bail, userrec* user)
{"options", "syntaxhints", &this->SyntaxHints, DT_BOOLEAN, NoValidation},
{"options", "cyclehosts", &this->CycleHosts, DT_BOOLEAN, NoValidation},
{"pid", "file", &this->PID, DT_CHARPTR, NoValidation},
+ {"whowas", "groupsize", &this->WhoWasGroupSize, DT_INTEGER, NoValidation},
+ {"whowas", "maxgroups", &this->WhoWasMaxGroups, DT_INTEGER, NoValidation},
+ {"whowas", "maxkeep", &maxkeep, DT_CHARPTR, ValidateWhoWas},
{NULL}
};
diff --git a/src/users.cpp b/src/users.cpp
index 5d6ac2ce7..f3278186b 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -869,7 +869,7 @@ namespace irc
whowas_set* n = (whowas_set*)iter->second;
if (n->size())
{
- while ((n->begin() != n->end()) && ((*n->begin())->signon < t - 259200)) // 3 days
+ while ((n->begin() != n->end()) && ((*n->begin())->signon < t - ServerInstance->Config->WhoWasMaxKeep))
{
WhoWasGroup *a = *(n->begin());
DELETE(a);
@@ -878,6 +878,51 @@ namespace irc
}
}
}
+ /* on rehash, refactor maps according to new conf values */
+ void PruneWhoWas(InspIRCd* ServerInstance, time_t t)
+ {
+ int groupsize = ServerInstance->Config->WhoWasGroupSize;
+ int maxgroups = ServerInstance->Config->WhoWasMaxGroups;
+ int maxkeep = ServerInstance->Config->WhoWasMaxKeep;
+
+ int groupcount = 0;
+ for (whowas_users_fifo::iterator iter = ServerInstance->whowas_fifo.begin(); iter != ServerInstance->whowas_fifo.end(); iter++)
+ {
+ groupcount++;
+
+ if (groupcount > maxgroups || iter->first < t - maxkeep)
+ {
+ whowas_set* n = (whowas_set*)ServerInstance->whowas.find(iter->second)->second;
+ if (n->size())
+ {
+ while (n->begin() != n->end())
+ {
+ WhoWasGroup *a = *(n->begin());
+ DELETE(a);
+ n->erase(n->begin());
+ }
+ }
+ ServerInstance->whowas.erase(iter->second);
+ ServerInstance->whowas_fifo.erase(iter->first);
+ }
+ else {
+ whowas_set* n = (whowas_set*)ServerInstance->whowas.find(iter->second)->second;
+ if (n->size())
+ {
+ int nickcount = 0;
+ while (n->begin() != n->end())
+ {
+ nickcount++;
+ if (nickcount > groupsize){
+ WhoWasGroup *a = *(n->begin());
+ DELETE(a);
+ n->erase(n->begin());
+ }
+ }
+ }
+ }
+ }
+ }
};
};
@@ -895,6 +940,12 @@ void userrec::AddToWhoWas()
irc::whowas::WhoWasGroup *a = new irc::whowas::WhoWasGroup(this);
n->push_back(a);
ServerInstance->whowas[this->nick] = n;
+ ServerInstance->whowas_fifo[ServerInstance->Time()] = this->nick;
+ if ((int)(ServerInstance->whowas.size()) > ServerInstance->Config->WhoWasMaxGroups)
+ {
+ ServerInstance->whowas.erase(ServerInstance->whowas_fifo.begin()->second);
+ ServerInstance->whowas_fifo.erase(ServerInstance->whowas_fifo.begin());
+ }
}
else
{
@@ -902,7 +953,7 @@ void userrec::AddToWhoWas()
ServerInstance->Log(DEBUG,"Using existing whowas group for %s",this->nick);
- if (group->size() > 10)
+ if ((int)(group->size()) > ServerInstance->Config->WhoWasMaxGroups)
{
ServerInstance->Log(DEBUG,"Trimming existing group to ten entries for %s",this->nick);
irc::whowas::WhoWasGroup *a = (irc::whowas::WhoWasGroup*)*(group->begin());