Author: Kev <klmitch@mit.edu>
authorKevin L. Mitchell <klmitch@mit.edu>
Fri, 15 Dec 2000 15:30:00 +0000 (15:30 +0000)
committerKevin L. Mitchell <klmitch@mit.edu>
Fri, 15 Dec 2000 15:30:00 +0000 (15:30 +0000)
Log message:

Create a linked list of connections that have queued data.  This allows
flush_connections to scan only the connections that have queued data,
rather than going through every single connection on the server.  This
will improve efficiency, but I doubt it'll have a significant impact on
CPU usage.

Testing:

Compiles and runs with no apparent errors.  It needs to be brute-forced
to make sure there are no assertion failures.

Notes:

If you ever call MsgQClear(), you MUST call client_drop_sendq() as well!
(Perhaps this should be changed to have client_drop_sendq() call
MsgQClear() itself?)

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

ChangeLog
include/client.h
include/send.h
ircd/client.c
ircd/dbuf.c
ircd/list.c
ircd/s_bsd.c
ircd/send.c

index 377d3f308d4e86dc7203cc2e9b96a99058b19d20..df43b1b295d1ab29d1018fbf62c892c071b0c297 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2000-12-15  Kevin L. Mitchell  <klmitch@mit.edu>
+
+       * ircd/send.c: implement the efficiency of flush_connections by
+       creating a linked list of struct Connection's with queued data;
+       also get rid of flush_sendq_except and make sure to yank
+       connections out of the list when their sendQs become empty (notice
+       the assertion in flush_connections!)
+
+       * ircd/s_bsd.c (close_connection): must yank the Connection out of
+       the sendq list
+
+       * ircd/list.c (dealloc_connection): must yank the Connection out
+       of the sendq list
+
+       * ircd/dbuf.c (dbuf_put): call flush_connections instead of the
+       deprecated flush_sendq_except
+
+       * ircd/client.c: define a couple new helper functions for sendq
+       threading--this will make the flush_connections function in send.c
+       considerably more efficient by creating a linked list of
+       Connections that have queued data to send
+
+       * include/send.h: remove flush_sendq_except, as it's not used
+       anymore
+
+       * include/client.h: declare a couple new helper functions for the
+       sendq threading system
+
 2000-12-14  Kevin L. Mitchell  <klmitch@mit.edu>
 
        * ircd/m_ison.c (m_ison): Apply Diane Bruce's patch to make ISON
index fe839f766d480ef2be47e0906b48b71d94f8008c..3bbce511ba98f5ea9ee435c8b5c298d9e6ddc56d 100644 (file)
@@ -411,7 +411,9 @@ typedef enum ShowIPType {
 
 extern const char* get_client_name(const struct Client* sptr, int showip);
 extern int client_get_ping(const struct Client* local_client);
-
+extern void client_drop_sendq(struct Connection* con);
+extern void client_add_sendq(struct Connection* con,
+                            struct Connection** con_p);
 
 #endif /* INCLUDED_client_h */
 
index 4e5ef56898f51fe880d04b4b5cb21611a29b12b8..ca83b50da9e0b68a37571b376e3c3e59c99cc104 100644 (file)
@@ -19,7 +19,6 @@ struct MsgBuf;
  * Prototypes
  */
 extern void send_buffer(struct Client* to, struct MsgBuf* buf, int prio);
-extern void flush_sendq_except(void);
 
 extern void flush_connections(struct Client* cptr);
 extern void send_queued(struct Client *to);
index d9944ef0303d7e1418484411d3d13a6fab0c2c4c..317efc7fb03db697a75d40b3b65ceb700c4c3b4c 100644 (file)
@@ -58,3 +58,37 @@ int client_get_ping(const struct Client* acptr)
   Debug((DEBUG_DEBUG, "Client %s Ping %d", cli_name(acptr), ping));
   return ping;
 }
+
+/*
+ * client_drop_sendq
+ * removes the client's connection from the list of connections with
+ * queued data
+ */
+void client_drop_sendq(struct Connection* con)
+{
+  if (con_prev_p(con)) { /* on the queued data list... */
+    if (con_next(con))
+      con_prev_p(con_next(con)) = con_prev_p(con);
+    *(con_prev_p(con)) = con_next(con);
+
+    con_next(con) = 0;
+    con_prev_p(con) = 0;
+  }
+}
+
+/*
+ * client_add_sendq
+ * adds the client's connection to the list of connections with
+ * queued data
+ */
+void client_add_sendq(struct Connection* con, struct Connection** con_p)
+{
+  if (!con_prev_p(con)) { /* not on the queued data list yet... */
+    con_prev_p(con) = con_p;
+    con_next(con) = *con_p;
+
+    if (*con_p)
+      con_prev_p(*con_p) = &(con_next(con));
+    *con_p = con;
+  }
+}
index c6bc38f55f612601236d77d88e17ffd9941a750f..e2937b4fb47ed69de30497b2e2215496724bd726 100644 (file)
@@ -165,7 +165,7 @@ int dbuf_put(struct DBuf *dyn, const char *buf, unsigned int length)
          * attempt to recover from buffer starvation before
          * bailing this may help servers running out of memory
          */
-        flush_sendq_except();
+        flush_connections(0);
         if (0 == (db = dbuf_alloc()))
 #endif
           return dbuf_malloc_error(dyn);
index cfeb33816defbc00c76bfaac22c4c86a7c34ae12..601d5bff2ee1635a2b02e00017d39055c2a333ef 100644 (file)
@@ -144,6 +144,7 @@ static void dealloc_connection(struct Connection* con)
   if (-1 < con_fd(con))
     close(con_fd(con));
   MsgQClear(&(con_sendQ(con)));
+  client_drop_sendq(con);
   DBufClear(&(con_recvQ(con)));
   if (con_listener(con))
     release_listener(con_listener(con));
index e66a9d97c3c2c201e13d1dd2aece12ebae731393..7e56cf0c8164bc189da8e1aae860a2857e758266 100644 (file)
@@ -516,6 +516,7 @@ void close_connection(struct Client *cptr)
   cli_flags(cptr) |= FLAGS_DEADSOCKET;
 
   MsgQClear(&(cli_sendQ(cptr)));
+  client_drop_sendq(cli_connect(cptr));
   DBufClear(&(cli_recvQ(cptr)));
   memset(cli_passwd(cptr), 0, sizeof(cli_passwd(cptr)));
   set_snomask(cptr, 0, SNO_SET);
index 828c4e099278327654a6948811b2e8836400763a..72487d295f21035255f1818b65fba1a994541396 100644 (file)
@@ -47,6 +47,8 @@ static int sentalong[MAXCONNECTIONS];
 static int sentalong_marker;
 struct SLink *opsarray[32];     /* don't use highest bit unless you change
                                   atoi to strtoul in sendto_op_mask() */
+static struct Connection *send_queues = 0;
+
 /*
  * dead_link
  *
@@ -73,6 +75,7 @@ static void dead_link(struct Client *to, char *notice)
    */
   DBufClear(&(cli_recvQ(to)));
   MsgQClear(&(cli_sendQ(to)));
+  client_drop_sendq(cli_connect(to));
 
   /*
    * Keep a copy of the last comment, for later use...
@@ -106,31 +109,14 @@ void flush_connections(struct Client* cptr)
     send_queued(cptr);
   }
   else {
-    int i;
-    for (i = HighestFd; i >= 0; i--) {
-      if ((cptr = LocalClientArray[i]))
-        send_queued(cptr);
+    struct Connection* con;
+    for (con = send_queues; con; con = con_next(con)) {
+      assert(0 > MsgQLength(&(con_sendQ(con))));
+      send_queued(con_client(con));
     }
   }
 }
 
-/*
- * flush_sendq_except - run through local client array and flush
- * the sendq for each client, if the address of the client sendq
- * is the same as the one specified, it is skipped. This is used
- * by dbuf_put to try to get some more memory before bailing and
- * causing the client to be disconnected.
- */
-void flush_sendq_except(void)
-{
-  int i;
-  struct Client* cptr;
-  for (i = HighestFd; i >= 0; i--) {
-    if ( (cptr = LocalClientArray[i]))
-      send_queued(cptr);
-  }
-}
-
 /*
  * send_queued
  *
@@ -153,7 +139,7 @@ void send_queued(struct Client *to)
       msgq_delete(&(cli_sendQ(to)), len);
       cli_lastsq(to) = MsgQLength(&(cli_sendQ(to))) / 1024;
       if (IsBlocked(to))
-        break;
+        return;
     }
     else {
       if (IsDead(to)) {
@@ -161,9 +147,12 @@ void send_queued(struct Client *to)
         sprintf(tmp,"Write error: %s",(strerror(cli_error(to))) ? (strerror(cli_error(to))) : "Unknown error" );
         dead_link(to, tmp);
       }
-      break;
+      return;
     }
   }
+
+  /* Ok, sendq is now empty... */
+  client_drop_sendq(cli_connect(to));
 }
 
 void send_buffer(struct Client* to, struct MsgBuf* buf, int prio)
@@ -192,6 +181,7 @@ void send_buffer(struct Client* to, struct MsgBuf* buf, int prio)
   Debug((DEBUG_SEND, "Sending [%p] to %s", buf, cli_name(to)));
 
   msgq_add(&(cli_sendQ(to)), buf, prio);
+  client_add_sendq(cli_connect(to), &send_queues);
 
   /*
    * Update statistics. The following is slightly incorrect