- Dmitry Kurochkin cleaned up the pipelining code and removed the need for and
authorDaniel Stenberg <daniel@haxx.se>
Sun, 3 Feb 2008 12:31:35 +0000 (12:31 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Sun, 3 Feb 2008 12:31:35 +0000 (12:31 +0000)
  use of the "is_in_pipeline" struct field.

CHANGES
lib/multi.c
lib/url.c
lib/urldata.h

diff --git a/CHANGES b/CHANGES
index 02a476c..e4f9104 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,14 @@
 
                                   Changelog
 
+Daniel S (3 Feb 2008)
+- Dmitry Kurochkin cleaned up the pipelining code and removed the need for and
+  use of the "is_in_pipeline" struct field.
+
+- I wrote up and added the threaded-ssl.c example source code that shows how
+  to do multi-threaded downloads of HTTPS files with a libcurl that is built
+  with OpenSSL. It uses pthreads for the threading.
+
 Daniel S (31 Jan 2008)
 - Niklas Angebrand made the cookie support in libcurl properly deal with the
   "HttpOnly" feature introduced by Microsoft and apparently also supported by
index 5aac09e..504e43b 100644 (file)
@@ -585,7 +585,8 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
       multi->num_alive--;
 
     if(easy->easy_conn &&
-        easy->easy_handle->state.is_in_pipeline &&
+        (easy->easy_conn->send_pipe->size +
+         easy->easy_conn->recv_pipe->size > 1) &&
         easy->state > CURLM_STATE_WAITDO &&
         easy->state < CURLM_STATE_COMPLETED) {
       /* If the handle is in a pipeline and has started sending off its
@@ -868,17 +869,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       infof(easy->easy_handle, "Pipe broke: handle 0x%x, url = %s\n",
             easy, easy->easy_handle->state.path);
 
-      if(easy->easy_handle->state.is_in_pipeline) {
+      if(easy->state != CURLM_STATE_COMPLETED) {
         /* Head back to the CONNECT state */
         multistate(easy, CURLM_STATE_CONNECT);
-        easy->easy_handle->state.is_in_pipeline = FALSE;
         result = CURLM_CALL_MULTI_PERFORM;
         easy->result = CURLE_OK;
       }
-      else {
-        easy->result = CURLE_COULDNT_CONNECT;
-        multistate(easy, CURLM_STATE_COMPLETED);
-      }
 
       easy->easy_handle->state.pipe_broke = FALSE;
       easy->easy_conn = NULL;
@@ -946,32 +942,24 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         easy->result = addHandleToSendOrPendPipeline(easy->easy_handle,
                                                      easy->easy_conn);
         if(CURLE_OK == easy->result) {
-          if (easy->easy_handle->state.is_in_pipeline) {
-            multistate(easy, CURLM_STATE_WAITDO);
-            if(isHandleAtHead(easy->easy_handle,
-                              easy->easy_conn->send_pipe))
-              result = CURLM_CALL_MULTI_PERFORM;
-          }
+          if(async)
+            /* We're now waiting for an asynchronous name lookup */
+            multistate(easy, CURLM_STATE_WAITRESOLVE);
           else {
-            if(async)
-              /* We're now waiting for an asynchronous name lookup */
-              multistate(easy, CURLM_STATE_WAITRESOLVE);
+            /* after the connect has been sent off, go WAITCONNECT unless the
+               protocol connect is already done and we can go directly to
+               WAITDO! */
+            result = CURLM_CALL_MULTI_PERFORM;
+
+            if(protocol_connect)
+              multistate(easy, CURLM_STATE_WAITDO);
             else {
-              /* after the connect has been sent off, go WAITCONNECT unless the
-                 protocol connect is already done and we can go directly to
-                 WAITDO! */
-              result = CURLM_CALL_MULTI_PERFORM;
-
-              if(protocol_connect)
-                multistate(easy, CURLM_STATE_WAITDO);
-              else {
 #ifndef CURL_DISABLE_HTTP
-                if(easy->easy_conn->bits.tunnel_connecting)
-                  multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
-                else
+              if(easy->easy_conn->bits.tunnel_connecting)
+                multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
+              else
 #endif
-                  multistate(easy, CURLM_STATE_WAITCONNECT);
-              }
+                multistate(easy, CURLM_STATE_WAITCONNECT);
             }
           }
         }
@@ -1287,7 +1275,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         easy->easy_conn->bits.close = TRUE;
         Curl_removeHandleFromPipeline(easy->easy_handle,
                                       easy->easy_conn->recv_pipe);
-        easy->easy_handle->state.is_in_pipeline = FALSE;
 
         if(CURL_SOCKET_BAD != easy->easy_conn->sock[SECONDARYSOCKET]) {
           /* if we failed anywhere, we must clean up the secondary socket if
@@ -1311,7 +1298,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
                                         easy->easy_conn->recv_pipe);
           /* Check if we can move pending requests to send pipe */
           checkPendPipeline(easy->easy_conn);
-          easy->easy_handle->state.is_in_pipeline = FALSE;
+
           if(!retry) {
             /* if the URL is a follow-location and not just a retried request
                then figure out the URL here */
@@ -1345,7 +1332,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
                                     easy->easy_conn->recv_pipe);
       /* Check if we can move pending requests to send pipe */
       checkPendPipeline(easy->easy_conn);
-      easy->easy_handle->state.is_in_pipeline = FALSE;
 
       if(easy->easy_conn->bits.stream_was_rewound) {
           /* This request read past its response boundary so we quickly
@@ -1388,7 +1374,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         /* NOTE: no attempt to disconnect connections must be made
            in the case blocks above - cleanup happens only here */
 
-        easy->easy_handle->state.is_in_pipeline = FALSE;
         easy->easy_handle->state.pipe_broke = FALSE;
 
         if(easy->easy_conn) {
index 2e5dd6c..234c581 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -387,9 +387,6 @@ CURLcode Curl_close(struct SessionHandle *data)
   /* only for debugging, scan through all connections and see if there's a
      pipe reference still identifying this handle */
 
-  if(data->state.is_in_pipeline)
-    fprintf(stderr, "CLOSED when in pipeline!\n");
-
   if(data->state.connc && data->state.connc->type == CONNCACHE_MULTI) {
     struct conncache *c = data->state.connc;
     long i;
@@ -2477,9 +2474,9 @@ ConnectionExists(struct SessionHandle *data,
     }
 
     if(match) {
-      if(!check->is_in_pipeline) {
-        /* The check for a dead socket makes sense only in the
-           non-pipelining case */
+      if(pipeLen == 0) {
+        /* The check for a dead socket makes sense only if there
+           are no handles in pipeline */
         bool dead = SocketIsDead(check->sock[FIRSTSOCKET]);
         if(dead) {
           check->data = data;
@@ -2494,10 +2491,6 @@ ConnectionExists(struct SessionHandle *data,
 
       check->inuse = TRUE; /* mark this as being in use so that no other
                               handle in a multi stack may nick it */
-      if(canPipeline) {
-        /* Mark the connection as being in a pipeline */
-        check->is_in_pipeline = TRUE;
-      }
 
       *usethis = check;
       return TRUE; /* yes, we found one to use! */
@@ -2560,8 +2553,6 @@ static void
 ConnectionDone(struct connectdata *conn)
 {
   conn->inuse = FALSE;
-  if(!conn->send_pipe && !conn->recv_pipe && !conn->pend_pipe)
-    conn->is_in_pipeline = FALSE;
 }
 
 /*
@@ -4338,8 +4329,10 @@ CURLcode Curl_connect(struct SessionHandle *data,
 
   if(CURLE_OK == code) {
     /* no error */
-    if((*in_connect)->is_in_pipeline)
-      data->state.is_in_pipeline = TRUE;
+    if((*in_connect)->send_pipe->size +
+       (*in_connect)->recv_pipe->size != 0)
+      /* pipelining */
+      *protocol_done = TRUE;
     else {
       if(dns || !*asyncp)
         /* If an address is available it means that we already have the name
index ec0356d..505da55 100644 (file)
@@ -950,7 +950,6 @@ struct connectdata {
                               handle */
   bool writechannel_inuse; /* whether the write channel is in use by an easy
                               handle */
-  bool is_in_pipeline;     /* TRUE if this connection is in a pipeline */
   bool server_supports_pipelining; /* TRUE if server supports pipelining,
                                       set after first response */
 
@@ -1135,8 +1134,6 @@ struct UrlState {
                                 bytes / second */
   bool this_is_a_follow; /* this is a followed Location: request */
 
-  bool is_in_pipeline; /* Indicates whether this handle is part of a pipeline */
-
   char *first_host; /* if set, this should be the host name that we will
                        sent authorization to, no else. Used to make Location:
                        following not keep sending user+password... This is