From: Art Cancro Date: Thu, 6 Nov 2003 04:25:30 +0000 (+0000) Subject: * For certain IMAP outputs (such as BODYSTRUCTURE), buffer all output until X-Git-Tag: v7.86~5712 X-Git-Url: https://code.citadel.org/?a=commitdiff_plain;h=d225f65da44828385c69660fb47f6ac58ef2a61d;p=citadel.git * For certain IMAP outputs (such as BODYSTRUCTURE), buffer all output until we've got the whole thing, then spew it all at once to avoid lots of tiny TCP packets. * New API calls buffer_output() (to start buffering) and unbuffer_output() (to dump the buffer and stop buffering) are available to do this. --- diff --git a/citadel/ChangeLog b/citadel/ChangeLog index 0c152ba71..13d0a4d62 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -1,4 +1,11 @@ $Log$ + Revision 611.1 2003/11/06 04:25:30 ajc + * For certain IMAP outputs (such as BODYSTRUCTURE), buffer all output until + we've got the whole thing, then spew it all at once to avoid lots of + tiny TCP packets. + * New API calls buffer_output() (to start buffering) and unbuffer_output() + (to dump the buffer and stop buffering) are available to do this. + Revision 611.0 2003/10/21 04:20:41 ajc * THIS IS 6.11 @@ -5055,3 +5062,4 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant Fri Jul 10 1998 Art Cancro * Initial CVS import + diff --git a/citadel/imap_fetch.c b/citadel/imap_fetch.c index 0c9af927b..d3254473e 100644 --- a/citadel/imap_fetch.c +++ b/citadel/imap_fetch.c @@ -773,14 +773,20 @@ void imap_do_fetch_msg(int seq, struct CtdlMessage *msg, 1, msg); } else if (!strcasecmp(itemlist[i], "BODYSTRUCTURE")) { + buffer_output(); imap_fetch_bodystructure(IMAP->msgids[seq-1], itemlist[i], msg); + unbuffer_output(); } else if (!strcasecmp(itemlist[i], "ENVELOPE")) { + buffer_output(); imap_fetch_envelope(IMAP->msgids[seq-1], msg); + unbuffer_output(); } else if (!strcasecmp(itemlist[i], "FLAGS")) { + buffer_output(); imap_fetch_flags(seq-1); + unbuffer_output(); } else if (!strcasecmp(itemlist[i], "INTERNALDATE")) { imap_fetch_internaldate(msg); diff --git a/citadel/server.h b/citadel/server.h index e8cebf98d..4b9a3ffe8 100644 --- a/citadel/server.h +++ b/citadel/server.h @@ -130,6 +130,10 @@ struct CitContext { int redirect_ssl; #endif + int buffering; + char *output_buffer; /* hold output for one big dump */ + int buffer_len; + /* A linked list of all express messages sent to us. */ struct ExpressMessage *FirstExpressMessage; int disable_exp; /* Set to 1 to disable incoming pages */ diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 988acd9dc..9ec508e08 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -484,6 +484,33 @@ DONE: ++num_sessions; } +/* + * buffer_output() ... tell client_write to buffer all output until + * instructed to dump it all out later + */ +void buffer_output(void) { + if (CC->buffering == 0) { + CC->buffering = 1; + CC->buffer_len = 0; + CC->output_buffer = mallok(SIZ); + } +} + +/* + * unbuffer_output() ... dump out all that output we've been buffering. + */ +void unbuffer_output(void) { + if (CC->buffering == 1) { + CC->buffering = 0; + client_write(CC->output_buffer, CC->buffer_len); + phree(CC->output_buffer); + CC->output_buffer = NULL; + CC->buffer_len = 0; + } +} + + + /* * client_write() ... Send binary data to the client. */ @@ -492,6 +519,7 @@ void client_write(char *buf, int nbytes) int bytes_written = 0; int retval; int sock; + int old_buffer_len = 0; if (CC->redirect_fp != NULL) { fwrite(buf, nbytes, 1, CC->redirect_fp); @@ -505,6 +533,17 @@ void client_write(char *buf, int nbytes) sock = CC->client_socket; } + /* If we're buffering for later, do that now. */ + if (CC->buffering) { + old_buffer_len = CC->buffer_len; + CC->buffer_len += nbytes; + CC->output_buffer = reallok(CC->output_buffer, CC->buffer_len); + memcpy(&CC->output_buffer[old_buffer_len], buf, nbytes); + return; + } + + /* Ok, at this point we're not buffering. Go ahead and write. */ + #ifdef HAVE_OPENSSL if (CC->redirect_ssl) { client_write_ssl(buf, nbytes); diff --git a/citadel/sysdep_decls.h b/citadel/sysdep_decls.h index 406e8f689..c7870e63e 100644 --- a/citadel/sysdep_decls.h +++ b/citadel/sysdep_decls.h @@ -20,6 +20,8 @@ int ig_uds_server(char *sockpath, int queue_len); inline struct CitContext *MyContext (void); struct CitContext *CreateNewContext (void); void InitMyContext (struct CitContext *con); +void buffer_output(void); +void unbuffer_output(void); void client_write (char *buf, int nbytes); int client_read_to (char *buf, int bytes, int timeout); int client_read (char *buf, int bytes); diff --git a/citadel/user_ops.c b/citadel/user_ops.c index 69f45a64d..93957ce29 100644 --- a/citadel/user_ops.c +++ b/citadel/user_ops.c @@ -532,6 +532,11 @@ void logout(struct CitContext *who) /* Do modular stuff... */ PerformSessionHooks(EVT_LOGOUT); + + /* Free any output buffers */ + if (who->output_buffer != NULL) { + unbuffer_output(); + } } #ifdef ENABLE_CHKPWD