src/lib/net.c 1.66

1.66 2009/02/10 21:43:14 galt
fixing FTP so it does not waste 1 second waiting to see if there is going to be an error, this should make it faster to retrieve multiple FTP requests
Index: src/lib/net.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/lib/net.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -b -B -U 4 -r1.65 -r1.66
--- src/lib/net.c	10 Feb 2009 21:00:42 -0000	1.65
+++ src/lib/net.c	10 Feb 2009 21:43:14 -0000	1.66
@@ -397,9 +397,16 @@
 	}
     }
 }
 
-struct dyString *sendFtpCommand(int sd, char *cmd, boolean seeResult, boolean noTimeoutError)
+void sendFtpCommandOnly(int sd, char *cmd)
+/* send command to ftp server */
+{   
+write(sd, cmd, strlen(cmd));
+}
+
+
+struct dyString *receiveFtpReply(int sd, char *cmd, boolean seeResult)
 /* send command to ftp server and check resulting reply code, 
    give error if not desired reply */
 {   
 struct dyString *rs = NULL;
@@ -408,20 +415,16 @@
 int readSize;
 char *startLastLine = NULL;
 long timeOut = 1000000; /* wait in microsec */
 
-write(sd, cmd, strlen(cmd));
-
 rs = newDyString(4*1024);
 while (1)
     {
     while (1)
 	{
 	if (!readReadyWait(sd, timeOut))
 	    {
-	    if (!noTimeoutError)
 		errAbort("ftp server response timed out > %ld microsec",timeOut);
-	    return rs;
 	    }
 	if ((readSize = read(sd, buf, sizeof(buf))) == 0)
 	    break;
 
@@ -461,8 +464,17 @@
 return rs;
 }
 
 
+
+struct dyString *sendFtpCommand(int sd, char *cmd, boolean seeResult)
+/* send command to ftp server and check resulting reply code, 
+   give error if not desired reply */
+{   
+sendFtpCommandOnly(sd, cmd);
+return receiveFtpReply(sd, cmd, seeResult);
+}
+
 int parsePasvPort(char *rs)
 /* parse PASV reply to get the port and return it */
 {
 char *rsCopy = strdup(rs);
@@ -500,42 +512,59 @@
 /* Ask remote ftp server for a file. */
 
 /* don't send a command, just read the welcome msg */
 if (readReadyWait(sd, timeOut))
-    sendFtpCommand(sd, "", FALSE, FALSE);
+    sendFtpCommand(sd, "", FALSE);
 
 safef(cmd,sizeof(cmd),"USER %s\r\n",npu.user);
-sendFtpCommand(sd, cmd, FALSE, FALSE);
+sendFtpCommand(sd, cmd, FALSE);
 
 safef(cmd,sizeof(cmd),"PASS %s\r\n",npu.password);
-sendFtpCommand(sd, cmd, FALSE, FALSE);
+sendFtpCommand(sd, cmd, FALSE);
 
-sendFtpCommand(sd, "TYPE I\r\n", FALSE, FALSE);
+sendFtpCommand(sd, "TYPE I\r\n", FALSE);
 /* 200 Type set to I */
 /* (send the data as binary, so can support compressed files) */
 
-rs = sendFtpCommand(sd, "PASV\r\n", TRUE, FALSE);
+rs = sendFtpCommand(sd, "PASV\r\n", TRUE);
 /* 227 Entering Passive Mode (128,231,210,81,222,250) */
 
 safef(cmd,sizeof(cmd),"RETR %s\r\n", npu.file);
-/* we can't wait for reply because 
-   we need to start the next fetch connect 
-   but then if there is an error e.g. missing file,
-   then we don't see the err msg because we
-   already closed the port and are waiting.
-   And our timeout is long - indefinitely so?
-*/
-sendFtpCommand(sd, cmd, FALSE, TRUE);  
+sendFtpCommandOnly(sd, cmd);  
 
 sdata = netMustConnect(npu.host, parsePasvPort(rs->string));
 
-/* Clean up and return handle. */
-dyStringFree(&rs);
-
 /* Because some FTP servers will kill the data connection
  * as soon as the control connection closes,
  * we have to develop a workaround using a partner process. */
 
+/* see which comes first, an error message on the control conn
+ * or data on the data conn */
+
+int secondsWaited=0;
+while (TRUE)
+    {
+    if (secondsWaited >= 10)
+	{
+	errAbort("ftp server error on cmd=[%s] timed-out waiting for data or error\n",cmd);
+	}
+    timeOut = 1000000; /* wait in microsec */
+    if (readReadyWait(sdata, timeOut))
+	{
+	break;   // we have some data
+	}
+    if (readReadyWait(sd, 0)) /* wait in microsec */
+	{
+	receiveFtpReply(sd, cmd, FALSE);  // this can see an error like bad filename
+	}
+    ++secondsWaited;
+    }
+    
+
+/* Clean up and return handle. */
+dyStringFree(&rs);
+
+
 fflush(stdin);
 fflush(stdout);
 fflush(stderr);