Browse Source

getinfo: CURLINFO_QUEUE_TIME_T

Returns the time, in microseconds, during which this transfer was held
in a waiting queue before it started "for real". A transfer might be put
in a queue if after getting started, it cannot create a new connection
etc due to set conditions and limits imposed by the application.

Ref: #12293
Closes #12368
Daniel Stenberg 4 months ago
parent
commit
68f96fc9bf

+ 14 - 7
docs/libcurl/curl_easy_getinfo.3

@@ -95,6 +95,9 @@ See \fICURLINFO_PRETRANSFER_TIME(3)\fP
 .IP CURLINFO_PRETRANSFER_TIME_T
 Time from start until just before the transfer begins.
 See \fICURLINFO_PRETRANSFER_TIME_T(3)\fP
+.IP CURLINFO_QUEUE_TIME_T
+Time during which this transfer was held in a waiting queue.
+See \fICURLINFO_QUEUE_TIME_T(3\fP
 .IP CURLINFO_STARTTRANSFER_TIME
 Time from start until just when the first byte is received.
 See \fICURLINFO_STARTTRANSFER_TIME(3)\fP
@@ -259,14 +262,18 @@ An overview of the six time values available from \fIcurl_easy_getinfo(3)\fP
 
 curl_easy_perform()
     |
-    |--NAMELOOKUP
-    |--|--CONNECT
-    |--|--|--APPCONNECT
-    |--|--|--|--PRETRANSFER
-    |--|--|--|--|--STARTTRANSFER
-    |--|--|--|--|--|--TOTAL
-    |--|--|--|--|--|--REDIRECT
+    |--QUEUE_TIME
+    |--|--NAMELOOKUP
+    |--|--|--CONNECT
+    |--|--|--|--APPCONNECT
+    |--|--|--|--|--PRETRANSFER
+    |--|--|--|--|--|--STARTTRANSFER
+    |--|--|--|--|--|--|--TOTAL
+    |--|--|--|--|--|--|--REDIRECT
 .fi
+.IP "QUEUE_TIME"
+\fICURLINFO_QUEUE_TIME_T(3\fP. The time during which the transfer was held in
+a waiting queue before it could start for real. (Added in 8.6.0)
 .IP NAMELOOKUP
 \fICURLINFO_NAMELOOKUP_TIME(3)\fP and \fICURLINFO_NAMELOOKUP_TIME_T(3)\fP.
 The time it took from the start until the name resolving was completed.

+ 74 - 0
docs/libcurl/opts/CURLINFO_QUEUE_TIME_T.3

@@ -0,0 +1,74 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLINFO_QUEUE_TIME_T 3 "28 Apr 2018" libcurl libcurl
+.SH NAME
+CURLINFO_QUEUE_TIME_T \- time this transfer was queued
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_QUEUE_TIME_T,
+                           curl_off_t *timep);
+.fi
+.SH DESCRIPTION
+Pass a pointer to a curl_off_t to receive the time, in microseconds, this
+transfer was held in a waiting queue before it started "for real". A transfer
+might be put in a queue if after getting started, it cannot create a new
+connection etc due to set conditions and limits imposed by the application.
+
+See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
+.SH PROTOCOLS
+All
+.SH EXAMPLE
+.nf
+int main(void)
+{
+  CURL *curl = curl_easy_init();
+  if(curl) {
+    CURLcode res;
+    curl_off_t queue;
+    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+    res = curl_easy_perform(curl);
+    if(CURLE_OK == res) {
+      res = curl_easy_getinfo(curl, CURLINFO_QUEUE_TIME_T, &queue);
+      if(CURLE_OK == res) {
+        printf("Queued: %" CURL_FORMAT_CURL_OFF_T ".%06ld us", queue / 1000000,
+               (long)(queue % 1000000));
+      }
+    }
+    /* always cleanup */
+    curl_easy_cleanup(curl);
+  }
+}
+.fi
+.SH AVAILABILITY
+Added in 8.6.0
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR curl_easy_getinfo (3),
+.BR curl_easy_setopt (3),
+.BR CURLINFO_STARTTRANSFER_TIME_T (3),
+.BR CURLOPT_TIMEOUT (3)

+ 1 - 0
docs/libcurl/opts/Makefile.inc

@@ -65,6 +65,7 @@ man_MANS =                                      \
   CURLINFO_PROXY_ERROR.3                        \
   CURLINFO_PROXY_SSL_VERIFYRESULT.3             \
   CURLINFO_PROXYAUTH_AVAIL.3                    \
+  CURLINFO_QUEUE_TIME_T.3                       \
   CURLINFO_REDIRECT_COUNT.3                     \
   CURLINFO_REDIRECT_TIME.3                      \
   CURLINFO_REDIRECT_TIME_T.3                    \

+ 1 - 0
docs/libcurl/symbols-in-versions

@@ -469,6 +469,7 @@ CURLINFO_PROXY_ERROR            7.73.0
 CURLINFO_PROXY_SSL_VERIFYRESULT 7.52.0
 CURLINFO_PROXYAUTH_AVAIL        7.10.8
 CURLINFO_PTR                    7.54.1
+CURLINFO_QUEUE_TIME_T           8.6.0
 CURLINFO_REDIRECT_COUNT         7.9.7
 CURLINFO_REDIRECT_TIME          7.9.7
 CURLINFO_REDIRECT_TIME_T        7.61.0

+ 2 - 1
include/curl/curl.h

@@ -2936,7 +2936,8 @@ typedef enum {
   CURLINFO_CAPATH           = CURLINFO_STRING + 62,
   CURLINFO_XFER_ID          = CURLINFO_OFF_T + 63,
   CURLINFO_CONN_ID          = CURLINFO_OFF_T + 64,
-  CURLINFO_LASTONE          = 64
+  CURLINFO_QUEUE_TIME_T     = CURLINFO_OFF_T + 65,
+  CURLINFO_LASTONE          = 65
 } CURLINFO;
 
 /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as

+ 4 - 1
lib/getinfo.c

@@ -409,6 +409,9 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
   case CURLINFO_STARTTRANSFER_TIME_T:
     *param_offt = data->progress.t_starttransfer;
     break;
+  case CURLINFO_QUEUE_TIME_T:
+    *param_offt = data->progress.t_postqueue;
+    break;
   case CURLINFO_REDIRECT_TIME_T:
     *param_offt = data->progress.t_redirect;
     break;
@@ -420,7 +423,7 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
     break;
   case CURLINFO_CONN_ID:
     *param_offt = data->conn?
-                  data->conn->connection_id : data->state.recent_conn_id;
+      data->conn->connection_id : data->state.recent_conn_id;
     break;
   default:
     return CURLE_UNKNOWN_OPTION;

+ 1 - 0
lib/multi.c

@@ -1943,6 +1943,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       }
 
       if(!result) {
+        *nowp = Curl_pgrsTime(data, TIMER_POSTQUEUE);
         if(async)
           /* We're now waiting for an asynchronous name lookup */
           multistate(data, MSTATE_RESOLVING);

+ 9 - 1
lib/progress.c

@@ -174,10 +174,18 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
     data->progress.t_startop = timestamp;
     break;
   case TIMER_STARTSINGLE:
-    /* This is set at the start of each single fetch */
+    /* This is set at the start of each single transfer */
     data->progress.t_startsingle = timestamp;
     data->progress.is_t_startransfer_set = false;
     break;
+  case TIMER_POSTQUEUE:
+    /* Set when the transfer starts (after potentially having been brought
+       back from the waiting queue). It needs to count from t_startop and not
+       t_startsingle since the latter is reset when a connection is brought
+       back from the pending queue. */
+    data->progress.t_postqueue =
+      Curl_timediff_us(timestamp, data->progress.t_startop);
+    break;
   case TIMER_STARTACCEPT:
     data->progress.t_acceptdata = timestamp;
     break;

+ 2 - 1
lib/progress.h

@@ -30,7 +30,8 @@
 typedef enum {
   TIMER_NONE,
   TIMER_STARTOP,
-  TIMER_STARTSINGLE,
+  TIMER_STARTSINGLE, /* start of transfer, might get queued */
+  TIMER_POSTQUEUE,   /* start, immediately after dequeue */
   TIMER_NAMELOOKUP,
   TIMER_CONNECT,
   TIMER_APPCONNECT,

+ 1 - 0
lib/urldata.h

@@ -1189,6 +1189,7 @@ struct Progress {
   curl_off_t dlspeed;
   curl_off_t ulspeed;
 
+  timediff_t t_postqueue;
   timediff_t t_nslookup;
   timediff_t t_connect;
   timediff_t t_appconnect;