From 15cb13eb37473d2bb6f7fcbf53dbb6519c5f72d1 Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Wed, 3 Jan 2001 20:05:58 +0000 Subject: [PATCH] Author: Kev Log message: Fixed a minor bug in the privilege setup function; featurized NICKNAMEHISTORYLENGTH--by rewriting much of whowas.c. Testing: I've tested the new feature and made sure that whowas does what's expected, and it seems to. Brute-force it to make sure, but we should be fine... git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@355 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 23 ++++ config/config-sh.in | 1 - include/ircd_features.h | 1 + include/whowas.h | 4 + ircd/client.c | 2 +- ircd/ircd_features.c | 2 + ircd/s_debug.c | 4 +- ircd/whowas.c | 264 +++++++++++++++++++++++++++------------- 8 files changed, 212 insertions(+), 89 deletions(-) diff --git a/ChangeLog b/ChangeLog index f124488..0d848a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2001-01-03 Kevin L. Mitchell + + * ircd/whowas.c: Completely re-did the old allocation scheme by + turning it into a linked list, permitting the + NICKNAMEHISTORYLENGTH feature to be changed on the fly + + * ircd/s_debug.c (count_memory): use FEAT_NICKNAMEHISTORYLENGTH + feature instead of old #define + + * ircd/ircd_features.c: add NICKNAMEHISTORYLENGTH feature as an + integer feature with a notify callback (whowas_realloc) + + * ircd/client.c (client_set_privs): second memset was supposed to + be over antiprivs, not privs; thanks, Chris Behrens + for pointing that out... + + * include/whowas.h: new elements for an extra linked list in + struct Whowas; a notify function for feature value changes + + * include/ircd_features.h: new feature--FEAT_NICKNAMEHISTORYLENGTH + + * config/config-sh.in: NICKNAMEHISTORYLENGTH is now a feature + 2001-01-02 Kevin L. Mitchell * config/config-sh.in: get rid of DEFAULT_LIST_PARAMETER diff --git a/config/config-sh.in b/config/config-sh.in index 71a7226..b499b3a 100644 --- a/config/config-sh.in +++ b/config/config-sh.in @@ -218,5 +218,4 @@ endmenu mainmenu_option next_comment comment 'Configuration' int 'Maximum number of network connections (23 - (FD_SETSIZE-4))' MAXCONNECTIONS 252 - int 'Nickname history length' NICKNAMEHISTORYLENGTH 800 endmenu diff --git a/include/ircd_features.h b/include/ircd_features.h index 6c019bf..73037bc 100644 --- a/include/ircd_features.h +++ b/include/ircd_features.h @@ -40,6 +40,7 @@ enum Feature { FEAT_NODNS, FEAT_RANDOM_SEED, FEAT_DEFAULT_LIST_PARAM, + FEAT_NICKNAMEHISTORYLENGTH, /* features that probably should not be touched */ FEAT_KILLCHASETIMELIMIT, diff --git a/include/whowas.h b/include/whowas.h index 9084e00..6c1254b 100644 --- a/include/whowas.h +++ b/include/whowas.h @@ -57,6 +57,8 @@ struct Whowas { struct Whowas **hprevnextp; /* Pointer to previous next pointer */ struct Whowas *cnext; /* Next entry with the same 'online' pointer */ struct Whowas **cprevnextp; /* Pointer to previous next pointer */ + struct Whowas *wnext; /* Next entry in whowas linked list */ + struct Whowas *wprev; /* Pointer to previous next pointer */ }; /* @@ -72,4 +74,6 @@ extern void off_history(const struct Client *cptr); extern void initwhowas(void); extern void count_whowas_memory(int *wwu, size_t *wwm, int *wwa, size_t *wwam); +extern void whowas_realloc(void); + #endif /* INCLUDED_whowas_h */ diff --git a/ircd/client.c b/ircd/client.c index 1ab61a4..88cb0f9 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -157,7 +157,7 @@ client_set_privs(struct Client* client) int i; memset(&privs, 0, sizeof(struct Privs)); - memset(&privs, 0, sizeof(struct Privs)); + memset(&antiprivs, 0, sizeof(struct Privs)); if (!IsAnOper(client)) { /* clear privilege mask */ memset(&(cli_privs(client)), 0, sizeof(struct Privs)); diff --git a/ircd/ircd_features.c b/ircd/ircd_features.c index 30c13ea..47a2ffe 100644 --- a/ircd/ircd_features.c +++ b/ircd/ircd_features.c @@ -42,6 +42,7 @@ #include "struct.h" #include "support.h" #include "sys.h" /* FALSE bleah */ +#include "whowas.h" /* whowas_realloc */ #include #include @@ -245,6 +246,7 @@ static struct FeatureDesc { F_B(NODNS, 0, 0, 0), F_N(RANDOM_SEED, FEAT_NODISP, random_seed_set, 0, 0, 0, 0, 0, 0), F_S(DEFAULT_LIST_PARAM, FEAT_NULL, 0, list_set_default), + F_I(NICKNAMEHISTORYLENGTH, 0, 800, whowas_realloc), /* features that probably should not be touched */ F_I(KILLCHASETIMELIMIT, 0, 30, 0), diff --git a/ircd/s_debug.c b/ircd/s_debug.c index 96d986e..5b54dd5 100644 --- a/ircd/s_debug.c +++ b/ircd/s_debug.c @@ -255,7 +255,7 @@ void count_memory(struct Client *cptr, char *nick) totcl = 0, totch = 0, totww = 0, tot = 0; count_whowas_memory(&wwu, &wwm, &wwa, &wwam); - wwm += sizeof(struct Whowas) * NICKNAMEHISTORYLENGTH; + wwm += sizeof(struct Whowas) * feature_int(FEAT_NICKNAMEHISTORYLENGTH); wwm += sizeof(struct Whowas *) * WW_MAX; for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) @@ -349,7 +349,7 @@ void count_memory(struct Client *cptr, char *nick) ":Whowas users %d(%zu) away %d(%zu)", wwu, wwu * sizeof(struct User), wwa, wwam); send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":Whowas array %d(%zu)", - NICKNAMEHISTORYLENGTH, wwm); + feature_int(FEAT_NICKNAMEHISTORYLENGTH), wwm); totww = wwu * sizeof(struct User) + wwam + wwm; diff --git a/ircd/whowas.c b/ircd/whowas.c index 61774d7..b819e17 100644 --- a/ircd/whowas.c +++ b/ircd/whowas.c @@ -39,9 +39,11 @@ #include "ircd.h" #include "ircd_alloc.h" #include "ircd_chattr.h" +#include "ircd_features.h" #include "ircd_string.h" #include "list.h" #include "numeric.h" +#include "s_debug.h" #include "s_misc.h" #include "s_user.h" #include "send.h" @@ -55,8 +57,12 @@ #include -static struct Whowas whowas[NICKNAMEHISTORYLENGTH]; -static struct Whowas* whowas_next = whowas; +static struct { + struct Whowas *ww_list; /* list of whowas structures */ + struct Whowas *ww_tail; /* tail of list for getting structures */ + unsigned int ww_alloc; /* alloc count */ +} wwList = { 0, 0, 0 }; + struct Whowas* whowashash[WW_MAX]; /* @@ -131,12 +137,134 @@ struct Whowas* whowashash[WW_MAX]; * --Run */ -typedef union { - struct Whowas *newww; - struct Whowas *oldww; -} Current; +/* whowas_clean() + * + * Clean up a whowas structure + */ +static struct Whowas * +whowas_clean(struct Whowas *ww) +{ + if (!ww) + return 0; + + Debug((DEBUG_LIST, "Cleaning whowas structure for %s", ww->name)); + + if (ww->online) { /* unlink from client */ + if (ww->cnext) /* shouldn't happen, but I'm not confident of that */ + ww->cnext->cprevnextp = ww->cprevnextp; + *ww->cprevnextp = ww->cnext; + } + + if (ww->hnext) /* now unlink from hash table */ + ww->hnext->hprevnextp = ww->hprevnextp; + *ww->hprevnextp = ww->hnext; + + if (ww->wnext) /* unlink from whowas linked list... */ + ww->wnext->wprev = ww->wprev; + if (ww->wprev) + ww->wprev->wnext = ww->wnext; + + if (wwList.ww_tail == ww) /* update tail pointer appropriately */ + wwList.ww_tail = ww->wprev; + + /* Free old info */ + if (ww->name) + MyFree(ww->name); + if (ww->username) + MyFree(ww->username); + if (ww->hostname) + MyFree(ww->hostname); + if (ww->servername) + MyFree(ww->servername); + if (ww->realname) + MyFree(ww->realname); + if (ww->away) + MyFree(ww->away); + + return ww; +} + +/* whowas_free() + * + * Free a struct Whowas... + */ +static void +whowas_free(struct Whowas *ww) +{ + if (!ww) + return; + + Debug((DEBUG_LIST, "Destroying whowas structure for %s", ww->name)); + + MyFree(whowas_clean(ww)); -#define WHOWAS_UNUSED ((unsigned int)-1) + wwList.ww_alloc--; +} + +/* whowas_init() + * + * Initializes a given whowas structure + */ +static struct Whowas * +whowas_init(struct Whowas *ww) +{ + if (!ww) + return 0; + + ww->hashv = 0; + ww->name = 0; + ww->username = 0; + ww->hostname = 0; + ww->servername = 0; + ww->realname = 0; + ww->away = 0; + ww->logoff = 0; + ww->online = 0; + ww->hnext = 0; + ww->hprevnextp = 0; + ww->cnext = 0; + ww->cprevnextp = 0; + ww->wnext = 0; + ww->wprev = 0; + + return ww; +} + +/* whowas_alloc() + * + * Returns a whowas structure to use + */ +static struct Whowas * +whowas_alloc(void) +{ + if (wwList.ww_alloc >= feature_int(FEAT_NICKNAMEHISTORYLENGTH)) + return whowas_init(whowas_clean(wwList.ww_tail)); + + wwList.ww_alloc++; /* going to allocate a new one... */ + return whowas_init((struct Whowas *) MyMalloc(sizeof(struct Whowas))); +} + +/* whowas_realloc() + * + * Prune whowas list + */ +void +whowas_realloc(void) +{ + Debug((DEBUG_LIST, "whowas_realloc() called with alloc count %d, " + "history length %d, tail pointer %p", wwList.ww_alloc, + feature_int(FEAT_NICKNAMEHISTORYLENGTH), wwList.ww_tail)); + + while (wwList.ww_alloc > feature_int(FEAT_NICKNAMEHISTORYLENGTH)) { + if (!wwList.ww_tail) { /* list is empty... */ + Debug((DEBUG_LIST, "whowas list emptied with alloc count %d", + wwList.ww_alloc)); + return; + } + + whowas_free(wwList.ww_tail); /* free oldest element of whowas list */ + } +} /* * add_history @@ -149,75 +277,44 @@ typedef union { */ void add_history(struct Client *cptr, int still_on) { - Current ww; - ww.newww = whowas_next; + struct Whowas *ww; - /* If this entry has already been used, remove it from the lists */ - if (ww.newww->hashv != WHOWAS_UNUSED) - { - if (ww.oldww->online) /* No need to update cnext/cprev when offline! */ - { - /* Remove ww.oldww from the linked list with the same `online' pointers */ - *ww.oldww->cprevnextp = ww.oldww->cnext; + if (!(ww = whowas_alloc())) + return; /* couldn't get a structure */ - assert(0 == ww.oldww->cnext); + ww->hashv = hash_whowas_name(cli_name(cptr)); /* initialize struct */ + ww->logoff = CurrentTime; + DupString(ww->name, cli_name(cptr)); + DupString(ww->username, cli_user(cptr)->username); + DupString(ww->hostname, cli_user(cptr)->host); + DupString(ww->servername, cli_name(cli_user(cptr)->server)); + DupString(ww->realname, cli_info(cptr)); + if (cli_user(cptr)->away) + DupString(ww->away, cli_user(cptr)->away); - } - /* Remove ww.oldww from the linked list with the same `hashv' */ - *ww.oldww->hprevnextp = ww.oldww->hnext; - - assert(0 == ww.oldww->hnext); - - if (ww.oldww->name) - MyFree(ww.oldww->name); - if (ww.oldww->username) - MyFree(ww.oldww->username); - if (ww.oldww->hostname) - MyFree(ww.oldww->hostname); - if (ww.oldww->servername) - MyFree(ww.oldww->servername); - if (ww.oldww->realname) - MyFree(ww.oldww->realname); - if (ww.oldww->away) - MyFree(ww.oldww->away); - } + if (still_on) { /* user changed nicknames... */ + ww->online = cptr; + if ((ww->cnext = cli_whowas(cptr))) + ww->cnext->cprevnextp = &ww->cnext; + ww->cprevnextp = &(cli_whowas(cptr)); + cli_whowas(cptr) = ww; + } else /* user quit */ + ww->online = 0; - /* Initialize aWhoWas struct `newww' */ - ww.newww->hashv = hash_whowas_name(cli_name(cptr)); - ww.newww->logoff = CurrentTime; - DupString(ww.newww->name, cli_name(cptr)); - DupString(ww.newww->username, cli_user(cptr)->username); - DupString(ww.newww->hostname, cli_user(cptr)->host); - /* Should be changed to server numeric */ - DupString(ww.newww->servername, cli_name(cli_user(cptr)->server)); - DupString(ww.newww->realname, cli_info(cptr)); - if (cli_user(cptr)->away) - DupString(ww.newww->away, cli_user(cptr)->away); - else - ww.newww->away = NULL; + /* link new whowas structure to list */ + ww->wnext = wwList.ww_list; + if (wwList.ww_list) + wwList.ww_list->wprev = ww; + wwList.ww_list = ww; - /* Update/initialize online/cnext/cprev: */ - if (still_on) /* User just changed nicknames */ - { - ww.newww->online = cptr; - /* Add struct Whowas struct `newww' to start of 'online list': */ - if ((ww.newww->cnext = cli_whowas(cptr))) - ww.newww->cnext->cprevnextp = &ww.newww->cnext; - ww.newww->cprevnextp = &(cli_whowas(cptr)); - cli_whowas(cptr) = ww.newww; - } - else /* User quitting */ - ww.newww->online = NULL; - - /* Add struct Whowas struct `newww' to start of 'hashv list': */ - if ((ww.newww->hnext = whowashash[ww.newww->hashv])) - ww.newww->hnext->hprevnextp = &ww.newww->hnext; - ww.newww->hprevnextp = &whowashash[ww.newww->hashv]; - whowashash[ww.newww->hashv] = ww.newww; - - /* Advance `whowas_next' to next entry in the `whowas' table: */ - if (++whowas_next == &whowas[NICKNAMEHISTORYLENGTH]) - whowas_next = whowas; + if (!wwList.ww_tail) /* update the tail pointer... */ + wwList.ww_tail = ww; + + /* Now link it into the hash table */ + if ((ww->hnext = whowashash[ww->hashv])) + ww->hnext->hprevnextp = &ww->hnext; + ww->hprevnextp = &whowashash[ww->hashv]; + whowashash[ww->hashv] = ww; } /* @@ -259,7 +356,6 @@ struct Client *get_history(const char *nick, time_t timelimit) void count_whowas_memory(int *wwu, size_t *wwum, int *wwa, size_t *wwam) { struct Whowas *tmp; - int i; int u = 0; int a = 0; size_t um = 0; @@ -269,17 +365,15 @@ void count_whowas_memory(int *wwu, size_t *wwum, int *wwa, size_t *wwam) assert(0 != wwa); assert(0 != wwam); - for (i = 0, tmp = whowas; i < NICKNAMEHISTORYLENGTH; i++, tmp++) { - if (tmp->hashv != WHOWAS_UNUSED) { - u++; - um += (strlen(tmp->name) + 1); - um += (strlen(tmp->username) + 1); - um += (strlen(tmp->hostname) + 1); - um += (strlen(tmp->servername) + 1); - if (tmp->away) { - a++; - am += (strlen(tmp->away) + 1); - } + for (tmp = wwList.ww_list; tmp; tmp = tmp->wnext) { + u++; + um += (strlen(tmp->name) + 1); + um += (strlen(tmp->username) + 1); + um += (strlen(tmp->hostname) + 1); + um += (strlen(tmp->servername) + 1); + if (tmp->away) { + a++; + am += (strlen(tmp->away) + 1); } } *wwu = u; @@ -293,8 +387,8 @@ void initwhowas(void) { int i; - for (i = 0; i < NICKNAMEHISTORYLENGTH; i++) - whowas[i].hashv = WHOWAS_UNUSED; + for (i = 0; i < WW_MAX; i++) + whowashash[i] = 0; } unsigned int hash_whowas_name(const char *name) -- 2.20.1