Author: Kev <klmitch@mit.edu>
authorKevin L. Mitchell <klmitch@mit.edu>
Wed, 3 Jan 2001 20:05:58 +0000 (20:05 +0000)
committerKevin L. Mitchell <klmitch@mit.edu>
Wed, 3 Jan 2001 20:05:58 +0000 (20:05 +0000)
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
config/config-sh.in
include/ircd_features.h
include/whowas.h
ircd/client.c
ircd/ircd_features.c
ircd/s_debug.c
ircd/whowas.c

index f12448864251faeedf1b1fd73fa31d7da010d03f..0d848a3f7e10b823513c45ebd7d84b51edd2b32a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2001-01-03  Kevin L. Mitchell  <klmitch@mit.edu>
+
+       * 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
+       <cbehrens@xo.com> 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  <klmitch@mit.edu>
 
        * config/config-sh.in: get rid of DEFAULT_LIST_PARAMETER
index 71a7226e58c748bf143625373c938b4c7ab4720a..b499b3a09a0df13cf42d6d4d73db73c036de2dd5 100644 (file)
@@ -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
index 6c019bfb018f662d4b78312fd9f83321bf6e38ed..73037bc835a0f5dd7a93f7b1fe8dc079cf8c8aaf 100644 (file)
@@ -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,
index 9084e00d3a6e3b4f5a1e509dc1fa1aa0bfa3c54f..6c1254bfee4c1559ff4a6bb963b5a641c411cc39 100644 (file)
@@ -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 */
index 1ab61a42d65dc1e4e2660140a89dab69d78db60c..88cb0f9c77bc6d58ad0177ad003a1f2473c539cc 100644 (file)
@@ -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));
index 30c13ea3ed95e9d1f570e56d4eb2af0aed811ed3..47a2ffe62be93f4c2ed32d79a3e2f8bcca88a4dd 100644 (file)
@@ -42,6 +42,7 @@
 #include "struct.h"
 #include "support.h"
 #include "sys.h"    /* FALSE bleah */
+#include "whowas.h"    /* whowas_realloc */
 
 #include <assert.h>
 #include <stdlib.h>
@@ -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),
index 96d986e6e87df66253c18f91abc3762f8ac4cd0f..5b54dd5fd9a10ce9aa8ca775a40a37f82484b329 100644 (file)
@@ -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;
 
index 61774d7e9dc5b6c2f1a3cf98ee6d596f41c212ab..b819e1753afd6ac851b17e88afaf81642f87c21e 100644 (file)
 #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"
 #include <string.h>
 
 
-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)