<<< Date Index >>>     <<< Thread Index >>>

[PATCH] optionally disabling pipeline



After all Brendan's hard work on letting mutt pipeline commands
properly, a thread on mutt-users suggests that at least one server
($$$-RDBMS-based thingy) has severe problems dealing with pipelined
commands.  :^(

The attached makes pipelining a default-on option; when disabled, the
only remaining instance of pipelining should be that the result of the
IDLE command is not waited for after sending DONE.

The technique is not perfectly clean and there may be problems (I need
to go to bed).  The idea is to invoke imap_cmd_start() in flush-mode
(NULL command) and then process untagged responses, unless called _via_
imap_cmd_start(), in which case either:
 * we're in imap_exec()
or:
 * something is explicitly dealing with what happens next because it's
   expecting a command continuation (eg AUTHENTICATE <mech>)

My reasoning may be severely flawed.  My testing is limited to opening
my INBOX and then quitting, under "mutt -d9" and looking at the
.muttdebug0 file to see the ordering.  I don't have a severely broken
IMAP server to test against.

The wording in the option documentation might be a little strong, but
can be made stronger with an explicit comment "Unsetting this option is
not well supported and may cause problems elsewhere."

The option name, imap_pipeline_enable, doesn't cleanly fit existing
option naming style because of the _enable.  I was strongly tempted to
invert the sense and call it imap_server_pipelining_broken.  But if
users end up being advised to set that option when using product X, the
vendor of X might become irate at the harsh truth and so I opted for
future tact.

-Phil
diff -pur mutt/imap/command.c mutt-pipelinedis/imap/command.c
--- mutt/imap/command.c 2006-02-21 12:35:26.000000000 +0100
+++ mutt-pipelinedis/imap/command.c     2006-03-04 01:11:13.000000000 +0100
@@ -71,6 +71,7 @@ static char *Capabilities[] = {
 int imap_cmd_queue (IMAP_DATA* idata, const char* cmdstr)
 {
   IMAP_COMMAND* cmd;
+  int rc;
 
   if (idata->status == IMAP_FATAL)
   {
@@ -88,6 +89,18 @@ int imap_cmd_queue (IMAP_DATA* idata, co
   if (idata->state == IMAP_IDLE)
     idata->state = IMAP_SELECTED;
 
+  /* NB: this reverses the usual callstack */
+  if (!option(OPTIMAPSERVERPIPELINE)) {
+    rc = imap_cmd_start (idata, NULL);
+    if (rc < 0)
+      return rc;
+
+    do
+      rc = imap_cmd_step (idata);
+    while (rc == IMAP_CMD_CONTINUE);
+    return rc;
+  }
+
   return 0;
 }
 
@@ -96,9 +109,21 @@ int imap_cmd_queue (IMAP_DATA* idata, co
 int imap_cmd_start (IMAP_DATA* idata, const char* cmdstr)
 {
   int rc;
+  int pipeline_reset = 0;
 
-  if (cmdstr && (rc = imap_cmd_queue (idata, cmdstr)) < 0)
-    return rc;
+  if (cmdstr) {
+    if (!option(OPTIMAPSERVERPIPELINE)) {
+      pipeline_reset = 1;
+      set_option(OPTIMAPSERVERPIPELINE);
+    }
+
+    rc = imap_cmd_queue (idata, cmdstr);
+
+    if (pipeline_reset)
+      unset_option(OPTIMAPSERVERPIPELINE);
+    if (rc < 0)
+      return rc;
+  }
 
   /* don't write old or empty commands */
   if (idata->cmdbuf->dptr == idata->cmdbuf->data)
diff -pur mutt/init.h mutt-pipelinedis/init.h
--- mutt/init.h 2006-01-09 20:43:58.000000000 +0100
+++ mutt-pipelinedis/init.h     2006-03-04 00:33:04.000000000 +0100
@@ -915,6 +915,14 @@ struct option_t MuttVars[] = {
   ** but can make closing an IMAP folder somewhat slower. This option
   ** exists to appease speed freaks.
   */
+  { "imap_pipeline_enable",    DT_BOOL, R_NONE, OPTIMAPSERVERPIPELINE, 1},
+  /*
+  ** .pp
+  ** When \fIset\fP, mutt will use a command pipeline for efficiency, so
+  ** that a server can deal with several commands at once, letting fast
+  ** commands finish sooner.  All IMAP servers are required to support this,
+  ** but some are broken.  Disable this option if your IMAP server is broken.
+  */
   { "imap_servernoise",                DT_BOOL, R_NONE, OPTIMAPSERVERNOISE, 1 
},
   /*
   ** .pp
diff -pur mutt/mutt.h mutt-pipelinedis/mutt.h
--- mutt/mutt.h 2006-01-09 20:43:59.000000000 +0100
+++ mutt-pipelinedis/mutt.h     2006-03-04 00:33:30.000000000 +0100
@@ -375,6 +375,7 @@ enum
   OPTIMAPPASSIVE,
   OPTIMAPPEEK,
   OPTIMAPSERVERNOISE,
+  OPTIMAPSERVERPIPELINE,
 #endif
 #if defined(USE_SSL) || defined(USE_GNUTLS)
 # ifndef USE_GNUTLS