Преглед изворни кода

Cache members when removing them (#49)

Bryan Drewery пре 14 година
родитељ
комит
3caf6fb8b9
5 измењених фајлова са 48 додато и 6 уклоњено
  1. 16 0
      src/chan.h
  2. 19 0
      src/mod/channels.mod/chanmisc.c
  3. 1 1
      src/mod/irc.mod/chan.c
  4. 11 4
      src/mod/irc.mod/irc.c
  5. 1 1
      src/mod/irc.mod/irc.h

+ 16 - 0
src/chan.h

@@ -31,6 +31,19 @@ typedef struct memstruct {
   bd::HashTable<flood_t, int>         *floodnum; // floodnum[FLOOD_PRIVMSG] = 1;
 } memberlist;
 
+#include <bdlib/src/bdlib.h>
+BDLIB_NS_BEGIN
+template<typename T>
+  struct Hash;
+
+template<>
+  struct Hash<memberlist*>
+  {
+    // Use memory address
+    inline size_t operator()(memberlist* m) const { return reinterpret_cast<size_t>(m); }
+  };
+BDLIB_NS_END
+
 #define CHAN_FLAG_OP	1
 #define CHAN_FLAG_VOICE 2
 #define CHAN_FLAG_USER 3
@@ -128,6 +141,9 @@ struct chan_t {
   // Shared non-member counts (JOIN/PART)
   bd::HashTable<bd::String, bd::HashTable<flood_t, time_t> >     *floodtime; // floodtime[uhost][FLOOD_PRIVMSG] = now;
   bd::HashTable<bd::String, bd::HashTable<flood_t, int> >         *floodnum; //  floodnum[uhost][FLOOD_PRIVMSG] = 1;
+
+  // Member caching to cache cyclers
+  bd::HashTable<bd::String, memberlist*> *cached_members;
 };
 
 #define CHANINV    BIT0		/* +i					*/

+ 19 - 0
src/mod/channels.mod/chanmisc.c

@@ -970,6 +970,7 @@ static void init_channel(struct chanset_t *chan, bool reset)
   chan->channel.topic = NULL;
   chan->channel.floodtime = new bd::HashTable<bd::String, bd::HashTable<flood_t, time_t> >;
   chan->channel.floodnum  = new bd::HashTable<bd::String, bd::HashTable<flood_t, int> >;
+  chan->channel.cached_members = new bd::HashTable<bd::String, memberlist*>;
 }
 
 static void clear_masklist(masklist *m)
@@ -1016,6 +1017,24 @@ void clear_channel(struct chanset_t *chan, bool reset)
   delete chan->channel.floodnum;
   chan->channel.floodnum = NULL;
 
+  if (chan->channel.cached_members) {
+    if (chan->channel.cached_members->size()) {
+      bd::Array<bd::String> member_uhosts(chan->channel.cached_members->keys());
+      for (size_t i = 0; i < member_uhosts.length(); ++i) {
+        const bd::String uhost(member_uhosts[i]);
+
+        // Delete the cached member
+        m = (*chan->channel.cached_members)[uhost];
+        delete_member(m);
+
+        // Remove the cached member (not technically needed as it is deleted below, but for completeness.)
+        chan->channel.cached_members->remove(uhost);
+      }
+    }
+    delete chan->channel.cached_members;
+    chan->channel.cached_members = NULL;
+  }
+
   if (reset)
     init_channel(chan, 1);
   for (size_t i = 0; i < MODES_PER_LINE_MAX; ++i) {

+ 1 - 1
src/mod/irc.mod/chan.c

@@ -3059,7 +3059,7 @@ static int gotnick(char *from, char *msg)
       if (rfc_casecmp(nick, msg)) {
         /* Someone on channel with old nick?! */
 	if ((mm = ismember(chan, msg)))
-	  killmember(chan, mm->nick);
+	  killmember(chan, mm->nick, false);
       }
 
       strlcpy(m->nick, msg, sizeof(m->nick));

+ 11 - 4
src/mod/irc.mod/irc.c

@@ -1152,7 +1152,7 @@ new_mask(masklist *m, char *s, char *who)
 /* Removes a nick from the channel member list (returns 1 if successful)
  */
 static bool
-killmember(struct chanset_t *chan, char *nick)
+killmember(struct chanset_t *chan, char *nick, bool cacheMember)
 {
   memberlist *x = NULL, *old = NULL;
 
@@ -1168,8 +1168,15 @@ killmember(struct chanset_t *chan, char *nick)
     old->next = x->next;
   else
     chan->channel.member = x->next;
-  delete_member(x);
-  chan->channel.members--;
+
+  if (cacheMember) {
+    // Don't delete here, will delete when it expires from the cache.
+    (*chan->channel.cached_members)[x->userhost] = x;
+  } else {
+    delete_member(x);
+  }
+
+  --chan->channel.members;
 
   /* The following two errors should NEVER happen. We will try to correct
    * them though, to keep the bot from crashing.
@@ -1526,7 +1533,7 @@ check_expired_chanstuff(struct chanset_t *chan)
         if (now - m->split > wait_split) {
           putlog(LOG_JOIN, chan->dname, "%s (%s) got lost in the net-split.", m->nick, m->userhost);
           --(chan->channel.splitmembers);
-          killmember(chan, m->nick);
+          killmember(chan, m->nick, false);
           continue;
         }
       }

+ 1 - 1
src/mod/irc.mod/irc.h

@@ -92,7 +92,7 @@ static bool detect_chan_flood(memberlist *m, const char* from, struct chanset_t
 static bool new_mask(masklist *, char *, char *);
 static void do_closed_kick(struct chanset_t *, memberlist *);
 static char *quickban(struct chanset_t *, const char *);
-static bool killmember(struct chanset_t *chan, char *nick);
+static bool killmember(struct chanset_t *chan, char *nick, bool cacheMember = true);
 static void check_lonely_channel(struct chanset_t *chan);
 static int gotmode(char *, char *);
 void unset_im(struct chanset_t* chan);