Track in-progress LISTs by next hash bucket to send, rather than a
authorMichael Poole <mdpoole@troilus.org>
Thu, 14 Oct 2004 04:02:52 +0000 (04:02 +0000)
committerMichael Poole <mdpoole@troilus.org>
Thu, 14 Oct 2004 04:02:52 +0000 (04:02 +0000)
channel, to avoid locking channels (idea borrowed from Hybrid).

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1245 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

ChangeLog
include/channel.h
include/hash.h
ircd/Makefile.in
ircd/channel.c
ircd/hash.c
ircd/m_burst.c
ircd/m_list.c
ircd/s_bsd.c
ircd/s_misc.c

index 76b4a4041659cc90a30caae9cd610675bb54044e..f0f515651f2c5ac13c46e2561068de9db11c5df8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2004-10-13  Michael Poole <mdpoole@troilus.org>
+
+       * include/channel.h: Delete MODE_LISTED and is_listed().  Replace
+       ListingArgs.chptr with ListingArgs.bucket.  Move declaration of
+       list_next_channels() to..
+
+       * include/hash.h: here, and drop the "nr" argument.
+
+       * ircd/channel.c: Remove redundant scan of local clients for
+       channels being listed.  Delete list_next_channels() function.
+
+       * ircd/hash.c: Add list_next_channels() here, revising to not use
+       MODE_LISTED and to use ListingArgs.bucket instead of chptr.  Also
+       decide when to stop sending RPL_LISTs based on a half-full sendq.
+
+       * ircd/m_burst.c, ircd/s_misc.c: Delete mention of MODE_LISTED.
+
+       * ircd/m_list.c: Delete mention of MODE_LISTED.  Unconditionally
+       call list_next_channels(sptr).
+
+       * ircd/s_bsd.c: Remove the "nr" argument to list_next_channels().
+
+       * ircd/Makefile.in: Update dependencies (for hash.c).
+
 2004-10-13  Michael Poole <mdpoole@troilus.org>
 
        * ircd/ircd_parser.y: Consistently zero out global variables after
index e0dc9021e496801b4f4fcab54cb2cf7fe25be947..0895b7fa0b08f23015fe3abea665be98621ba571 100644 (file)
@@ -104,7 +104,6 @@ struct Client;
 #define MODE_LIMIT      0x0400         /**< +l Limit */
 #define MODE_REGONLY    0x0800         /**< Only +r users may join */
 #define MODE_DELJOINS   0x1000         /**< New join messages are delayed */
-#define MODE_LISTED     0x10000
 #define MODE_SAVE      0x20000         /**< save this mode-with-arg 'til 
                                         * later */
 #define MODE_FREE      0x40000         /**< string needs to be passed to 
@@ -133,7 +132,6 @@ struct Client;
                                  (IsAnOper(v) && HasPriv(v, PRIV_LIST_CHAN)))
 #define PubChannel(x)           ((!x) || ((x)->mode.mode & \
                                     (MODE_PRIVATE | MODE_SECRET)) == 0)
-#define is_listed(x)            ((x)->mode.mode & MODE_LISTED)
 
 #define IsGlobalChannel(name)   (*(name) == '#')
 #define IsLocalChannel(name)    (*(name) == '&')
@@ -287,7 +285,7 @@ struct ListingArgs {
   unsigned int flags;
   time_t max_topic_time;
   time_t min_topic_time;
-  struct Channel *chptr;
+  unsigned int bucket;
 };
 
 struct ModeBuf {
@@ -407,7 +405,6 @@ extern int IsInvited(struct Client* cptr, const void* chptr);
 extern void send_channel_modes(struct Client *cptr, struct Channel *chptr);
 extern char *pretty_mask(char *mask);
 extern void del_invite(struct Client *cptr, struct Channel *chptr);
-extern void list_next_channels(struct Client *cptr, int nr);
 extern void list_set_default(void); /* this belongs elsewhere! */
 
 extern void RevealDelayedJoin(struct Membership *member);
index 67af00b08d24b027bdf96a45ec5c5628515d47e9..62f4770918c6527723e1a54feb373fdd1ee0a72b 100644 (file)
@@ -87,5 +87,6 @@ extern int m_hash(struct Client *cptr, struct Client *sptr, int parc, char *parv
 extern int isNickJuped(const char *nick);
 extern int addNickJupes(const char *nicks);
 extern void clearNickJupes(void);
+extern void list_next_channels(struct Client *cptr);
 
 #endif /* INCLUDED_hash_h */
index 34c51bd5e769a587d09b7163bfb8d9f450ae4ed4..fc30d23fc2305aa05bb792fd6b3c3c8a40b594ae 100644 (file)
@@ -361,10 +361,10 @@ depend: ${DEP_SRC} chattr.tab.c
 IPcheck.o: IPcheck.c ../config.h ../include/IPcheck.h ../include/client.h \
   ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \
   ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \
-  ../include/ircd.h ../include/struct.h ../include/msg.h \
-  ../include/numnicks.h ../include/ircd_alloc.h \
+  ../include/ircd.h ../include/struct.h ../include/match.h \
+  ../include/msg.h ../include/numnicks.h ../include/ircd_alloc.h \
   ../include/ircd_features.h ../include/s_debug.h ../include/s_user.h \
-  ../include/send.h ../include/match.h
+  ../include/send.h
 channel.o: channel.c ../config.h ../include/channel.h \
   ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \
   ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \
@@ -421,9 +421,10 @@ gline.o: gline.c ../config.h ../include/gline.h ../include/res.h \
 hash.o: hash.c ../config.h ../include/hash.h ../include/client.h \
   ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \
   ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \
-  ../include/channel.h ../include/ircd_chattr.h ../include/ircd_string.h \
-  ../include/ircd.h ../include/struct.h ../include/msg.h \
-  ../include/send.h ../include/sys.h
+  ../include/channel.h ../include/ircd_alloc.h ../include/ircd_chattr.h \
+  ../include/ircd_reply.h ../include/ircd_string.h ../include/ircd.h \
+  ../include/struct.h ../include/msg.h ../include/numeric.h \
+  ../include/random.h ../include/send.h ../include/sys.h
 ircd.o: ircd.c ../config.h ../include/ircd.h ../include/struct.h \
   ../include/ircd_defs.h ../include/IPcheck.h ../include/class.h \
   ../include/client.h ../include/dbuf.h ../include/msgq.h \
@@ -1155,7 +1156,8 @@ querycmds.o: querycmds.c ../config.h ../include/querycmds.h \
 random.o: random.c ../config.h ../include/random.h ../include/client.h \
   ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \
   ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \
-  ../include/ircd_log.h ../include/ircd_reply.h ../include/send.h
+  ../include/ircd_log.h ../include/ircd_md5.h ../include/ircd_reply.h \
+  ../include/send.h
 s_auth.o: s_auth.c ../config.h ../include/s_auth.h \
   ../include/ircd_events.h ../include/client.h ../include/ircd_defs.h \
   ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \
index c5f01b45cf54aa541f2f9348b5b9c0d0468ca773..01813ca50c47f513e5d265f0f6d25e059ce6079c 100644 (file)
@@ -291,21 +291,6 @@ int destruct_channel(struct Channel* chptr)
 
   assert(0 == chptr->members);
 
-  /* Channel became (or was) empty: Remove channel */
-  if (is_listed(chptr))
-  {
-    int i;
-    for (i = 0; i <= HighestFd; i++)
-    {
-      struct Client *acptr = 0;
-      if ((acptr = LocalClientArray[i]) && cli_listing(acptr) &&
-          (cli_listing(acptr))->chptr == chptr)
-      {
-        list_next_channels(acptr, 1);
-        break;                  /* Only one client can list a channel */
-      }
-    }
-  }
   /*
    * Now, find all invite links from channel structure
    */
@@ -1577,58 +1562,6 @@ void del_invite(struct Client *cptr, struct Channel *chptr)
     }
 }
 
-/** List a set of channels
- * Lists a series of channels that match a filter, skipping channels that 
- * have been listed before.
- *
- * @param cptr Client to send the list to.
- * @param nr   Number of channels to send this update.
- */
-void list_next_channels(struct Client *cptr, int nr)
-{
-  struct ListingArgs *args = cli_listing(cptr);
-  struct Channel *chptr = args->chptr;
-  chptr->mode.mode &= ~MODE_LISTED;
-  while (is_listed(chptr) || --nr >= 0)
-  {
-    for (; chptr; chptr = chptr->next)
-    {
-      if (!cli_user(cptr))
-        continue;
-      if (!(HasPriv(cptr, PRIV_LIST_CHAN) && IsAnOper(cptr)) && 
-          SecretChannel(chptr) && !find_channel_member(cptr, chptr))
-        continue;
-      if (chptr->users > args->min_users && chptr->users < args->max_users &&
-          chptr->creationtime > args->min_time &&
-          chptr->creationtime < args->max_time &&
-          (!(args->flags & LISTARG_TOPICLIMITS) || (*chptr->topic &&
-          chptr->topic_time > args->min_topic_time &&
-          chptr->topic_time < args->max_topic_time)))
-      {
-        if ((args->flags & LISTARG_SHOWSECRET) || ShowChannel(cptr,chptr))
-         send_reply(cptr, RPL_LIST, chptr->chname, chptr->users,
-                    chptr->topic);
-        chptr = chptr->next;
-        break;
-      }
-    }
-    if (!chptr)
-    {
-      MyFree(cli_listing(cptr));
-      cli_listing(cptr) = NULL;
-      send_reply(cptr, RPL_LISTEND);
-      break;
-    }
-  }
-  if (chptr)
-  {
-    (cli_listing(cptr))->chptr = chptr;
-    chptr->mode.mode |= MODE_LISTED;
-  }
-
-  update_write(cptr);
-}
-
 /** @page zombie Explaination of Zombies
  *
  * Consider:
index 03a54adaf519a6128afe0b379cdfade3fc0a4cad..aaf017bba75e9cbe4e2c12cc6cdb91fa6322d839 100644 (file)
 #include "hash.h"
 #include "client.h"
 #include "channel.h"
+#include "ircd_alloc.h"
 #include "ircd_chattr.h"
+#include "ircd_reply.h"
 #include "ircd_string.h"
 #include "ircd.h"
 #include "msg.h"
+#include "numeric.h"
 #include "random.h"
 #include "send.h"
 #include "struct.h"
@@ -403,3 +406,46 @@ void clearNickJupes(void)
   for (i = 0; i < JUPEHASHSIZE; i++)
     jupeTable[i][0] = '\000';
 }
+
+/** Send more channels to a client in mid-LIST.
+ * @param[in] cptr Client to send the list to.
+ */
+void list_next_channels(struct Client *cptr)
+{
+  struct ListingArgs *args;
+  struct Channel *chptr;
+
+  /* Walk consecutive buckets until we hit the end. */
+  for (args = cli_listing(cptr); args->bucket < HASHSIZE; args->bucket++)
+  {
+    /* Send all the matching channels in the bucket. */
+    for (chptr = channelTable[args->bucket]; chptr; chptr = chptr->hnext)
+    {
+      if (chptr->users > args->min_users
+          && chptr->users < args->max_users
+          && chptr->creationtime > args->min_time
+          && chptr->creationtime < args->max_time
+          && (!(args->flags & LISTARG_TOPICLIMITS)
+              || (chptr->topic[0]
+                  && chptr->topic_time > args->min_topic_time
+                  && chptr->topic_time < args->max_topic_time))
+          && ((args->flags & LISTARG_SHOWSECRET)
+              || ShowChannel(cptr, chptr)))
+      {
+        send_reply(cptr, RPL_LIST, chptr->chname, chptr->users, chptr->topic);
+      }
+    }
+    /* If, at the end of the bucket, client sendq is more than half
+     * full, stop. */
+    if (MsgQLength(&cli_sendQ(cptr)) > cli_max_sendq(cptr) / 2)
+      break;
+  }
+
+  /* If we did all buckets, clean the client and send RPL_LISTEND. */
+  if (args->bucket >= HASHSIZE)
+  {
+    MyFree(cli_listing(cptr));
+    cli_listing(cptr) = NULL;
+    send_reply(cptr, RPL_LISTEND);
+  }
+}
index 9e44eca07c8b03d716b0f4a61f01b2dffa3262d8..f7e31da251ad5b8c656f07871adb73004f624113 100644 (file)
@@ -274,7 +274,7 @@ int ms_burst(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
     modebuf_init(mbuf = &modebuf, &me, cptr, chptr,
                 MODEBUF_DEST_CHANNEL | MODEBUF_DEST_NOKEY);
     modebuf_mode(mbuf, MODE_DEL | chptr->mode.mode); /* wipeout modes */
-    chptr->mode.mode &= MODE_LISTED | MODE_BURSTADDED | MODE_WASDELJOINS;
+    chptr->mode.mode &= MODE_BURSTADDED | MODE_WASDELJOINS;
 
     parse_flags |= (MODE_PARSE_SET | MODE_PARSE_WIPEOUT); /* wipeout keys */
 
index 09ab42274abe7119600c4c996f9c375b6ade011b..9c96a118d692c33dec4efbaa9d136d7b35741418 100644 (file)
@@ -291,7 +291,6 @@ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 
   if (cli_listing(sptr))            /* Already listing ? */
   {
-    cli_listing(sptr)->chptr->mode.mode &= ~MODE_LISTED;
     MyFree(cli_listing(sptr));
     cli_listing(sptr) = 0;
     send_reply(sptr, RPL_LISTEND);
@@ -331,14 +330,8 @@ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       cli_listing(sptr) = (struct ListingArgs*) MyMalloc(sizeof(struct ListingArgs));
       assert(0 != cli_listing(sptr));
       memcpy(cli_listing(sptr), &args, sizeof(struct ListingArgs));
-      if ((cli_listing(sptr)->chptr = GlobalChannelList)) {
-        int m = GlobalChannelList->mode.mode & MODE_LISTED;
-        list_next_channels(sptr, 64);
-        GlobalChannelList->mode.mode |= m;
-        return 0;
-      }
-      MyFree(cli_listing(sptr));
-      cli_listing(sptr) = 0;
+      list_next_channels(sptr);
+      return 0;
     }
     send_reply(sptr, RPL_LISTEND);
     return 0;
index d493d9a285c21466c5ef95746d3610542e992ae3..28e078a1ad45a4d7a79ada7e5cc1186e51632593 100644 (file)
@@ -940,7 +940,7 @@ static void client_sock_callback(struct Event* ev)
   case ET_WRITE: /* socket is writable */
     ClrFlag(cptr, FLAG_BLOCKED);
     if (cli_listing(cptr) && MsgQLength(&(cli_sendQ(cptr))) < 2048)
-      list_next_channels(cptr, 64);
+      list_next_channels(cptr);
     Debug((DEBUG_SEND, "Sending queued data to %C", cptr));
     send_queued(cptr);
     break;
index 82855b0d6e768216716c7892855075a6d3142b5b..631cf6bb9f29300888376ea1b314eeb42c84aaba 100644 (file)
@@ -215,7 +215,6 @@ static void exit_one_client(struct Client* bcptr, const char* comment)
      * Stop a running /LIST clean
      */
     if (MyUser(bcptr) && cli_listing(bcptr)) {
-      cli_listing(bcptr)->chptr->mode.mode &= ~MODE_LISTED;
       MyFree(cli_listing(bcptr));
       cli_listing(bcptr) = NULL;
     }