* Applied patches submitted by Kevin Kilbride for TCP_CORK and for
authorArt Cancro <ajc@citadel.org>
Wed, 16 Feb 2005 03:02:29 +0000 (03:02 +0000)
committerArt Cancro <ajc@citadel.org>
Wed, 16 Feb 2005 03:02:29 +0000 (03:02 +0000)
  turning CitContext into a doubly-linked list.

citadel/ChangeLog
citadel/citserver.c
citadel/server.h
citadel/sysdep.c

index f987ca635ffb2465c46224d2c29c8d26f4b79a8e..a782c0fc111a2f1fd514e73dc51c82c95f96b94e 100644 (file)
@@ -1,4 +1,8 @@
  $Log$
+ Revision 640.6  2005/02/16 03:02:28  ajc
+ * Applied patches submitted by Kevin Kilbride for TCP_CORK and for
+   turning CitContext into a doubly-linked list.
+
  Revision 640.5  2005/02/13 04:55:18  ajc
  * Did the server port hooks etc. for SSL listeners.  For some reason it
    doesn't work.  :(
@@ -6392,3 +6396,4 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import
+
index ffeea2170b74f12803e6468177abd63477106cb5..aacfecfdb025e1c5a16289e6c61665477f68261c 100644 (file)
@@ -182,9 +182,6 @@ void deallocate_user_data(struct CitContext *con)
  */
 void RemoveContext (struct CitContext *con)
 {
-       struct CitContext *ptr = NULL;
-       struct CitContext *ToFree = NULL;
-
        if (con==NULL) {
                lprintf(CTDL_ERR, "WARNING: RemoveContext() called with NULL!\n");
                return;
@@ -197,30 +194,11 @@ void RemoveContext (struct CitContext *con)
         */
        lprintf(CTDL_DEBUG, "Removing context for session %d\n", con->cs_pid);
        begin_critical_section(S_SESSION_TABLE);
-       if (ContextList == con) {
-               ToFree = ContextList;
-               ContextList = ContextList->next;
-               --num_sessions;
-       }
-       else {
-               for (ptr = ContextList; ptr != NULL; ptr = ptr->next) {
-                       if (ptr->next == con) {
-                               /* See fair scheduling in sysdep.c */
-                               if (next_session == ptr->next)
-                                       next_session = ptr->next->next;
-                               ToFree = ptr->next;
-                               ptr->next = ptr->next->next;
-                               --num_sessions;
-                       }
-               }
-       }
+         if (con->prev) con->prev->next = con->next; else ContextList = con->next;
+         if (con->next) con->next->prev = con->prev;
+         --num_sessions;
        end_critical_section(S_SESSION_TABLE);
 
-       if (ToFree == NULL) {
-               lprintf(CTDL_DEBUG, "RemoveContext() found nothing to remove\n");
-               return;
-       }
-
        /* Run any cleanup routines registered by loadable modules.
         * Note 1: This must occur *before* deallocate_user_data() because the
         *         cleanup functions might touch dynamic session data.
index 0c68c77d3a18bf856433903762dd589baad54d52..99b8dccb6e03f08264af22dc4738ac19085e7d67 100644 (file)
@@ -67,6 +67,7 @@ enum {
  * modification in a linked list.
  */
 struct CitContext {
+       struct CitContext *prev;
        struct CitContext *next;        /* Link to next session in the list */
 
        struct ctdluser user;   /* Database record buffers */
index 85854cd40812b6b0390f066c422363879341d249..353ab0ed8ad7ffe2020468ced248a3592f67c1b1 100644 (file)
@@ -43,6 +43,7 @@
 #include <limits.h>
 #include <sys/resource.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <sys/un.h>
@@ -415,10 +416,12 @@ struct CitContext *CreateNewContext(void) {
        if (ContextList == NULL) {
                ContextList = me;
                me->cs_pid = 1;
+               me->prev = NULL;
                me->next = NULL;
        }
 
        else if (ContextList->cs_pid > 1) {
+               me->prev = NULL;
                me->next = ContextList;
                ContextList = me;
                me->cs_pid = 1;
@@ -429,11 +432,14 @@ struct CitContext *CreateNewContext(void) {
                        if (ptr->next == NULL) {
                                ptr->next = me;
                                me->cs_pid = ptr->cs_pid + 1;
+                               me->prev = ptr;
                                me->next = NULL;
                                goto DONE;
                        }
                        else if (ptr->next->cs_pid > (ptr->cs_pid+1)) {
+                               me->prev = ptr;
                                me->next = ptr->next;
+                               ptr->next->prev = me;
                                ptr->next = me;
                                me->cs_pid = ptr->cs_pid + 1;
                                goto DONE;
@@ -448,9 +454,40 @@ DONE:      ++num_sessions;
 
 
 /*
- * buffer_output() ... tell client_write to buffer all output until
- *                  instructed to dump it all out later
+ * The following functions implement output buffering. If the kernel supplies
+ * native TCP buffering (Linux & *BSD), use that; otherwise, emulate it with
+ * user-space buffering.
  */
+#ifdef TCP_CORK
+#      define HAVE_TCP_BUFFERING
+#else
+#      ifdef TCP_NOPUSH
+#              define HAVE_TCP_BUFFERING
+#              define TCP_CORK TCP_NOPUSH
+#      endif
+#endif
+
+
+#ifdef HAVE_TCP_BUFFERING
+static unsigned on = 1, off = 0;
+void buffer_output(void) {
+       struct CitContext *ctx = MyContext();
+       setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
+       ctx->buffering = 1;
+}
+
+void unbuffer_output(void) {
+       struct CitContext *ctx = MyContext();
+       setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
+       ctx->buffering = 0;
+}
+
+void flush_output(void) {
+       struct CitContext *ctx = MyContext();
+       setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
+       setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
+}
+#else
 void buffer_output(void) {
        if (CC->buffering == 0) {
                CC->buffering = 1;
@@ -459,9 +496,6 @@ void buffer_output(void) {
        }
 }
 
-/*
- * flush_output()  ...   dump out all that output we've been buffering.
- */
 void flush_output(void) {
        if (CC->buffering == 1) {
                client_write(CC->output_buffer, CC->buffer_len);
@@ -469,9 +503,6 @@ void flush_output(void) {
        }
 }
 
-/*
- * unbuffer_output()  ...  stop buffering output.
- */
 void unbuffer_output(void) {
        if (CC->buffering == 1) {
                CC->buffering = 0;
@@ -482,6 +513,7 @@ void unbuffer_output(void) {
                CC->output_buffer = NULL;
        }
 }
+#endif
 
 
 
@@ -507,6 +539,7 @@ void client_write(char *buf, int nbytes)
                sock = CC->client_socket;
        }
 
+#ifndef HAVE_TCP_BUFFERING
        /* If we're buffering for later, do that now. */
        if (CC->buffering) {
                old_buffer_len = CC->buffer_len;
@@ -515,6 +548,7 @@ void client_write(char *buf, int nbytes)
                memcpy(&CC->output_buffer[old_buffer_len], buf, nbytes);
                return;
        }
+#endif
 
        /* Ok, at this point we're not buffering.  Go ahead and write. */