So be it. This drops connOkToAddrequest() in favour of a ConnStateData::concurrentRequestQueueFilled() which simply checks the available queue space and replies true/false. All other state handling relies on the existing code to behave properly. Pity anyone who hits a bug.

I've left in the parsing check we agreed on earlier.

Amos

=== modified file 'doc/release-notes/release-3.4.sgml'
--- doc/release-notes/release-3.4.sgml  2013-05-14 17:54:30 +0000
+++ doc/release-notes/release-3.4.sgml  2013-05-16 03:38:06 +0000
@@ -179,6 +179,9 @@
        <p>New format code <em>%note</em> to log a transaction annotation 
linked to the
           transaction by ICAP, eCAP, a helper, or the <em>note</em> squid.conf 
directive.
 
+       <tag>pipeline_prefetch</tag>
+       <p>Updated to take a numeric count of prefetched pipeline requests 
instead of ON/OFF.
+
        <tag>unlinkd_program</tag>
        <p>New helper response format utilizing result codes <em>OK</em> and 
<em>BH</em>,
           to signal helper lookup results. Also, key-value response values to 
return

=== modified file 'src/Parsing.cc'
--- src/Parsing.cc      2013-05-04 13:14:23 +0000
+++ src/Parsing.cc      2013-05-16 13:55:49 +0000
@@ -33,6 +33,7 @@
 #include "squid.h"
 #include "cache_cf.h"
 #include "compat/strtoll.h"
+#include "ConfigParser.h"
 #include "Parsing.h"
 #include "globals.h"
 #include "Debug.h"
@@ -161,7 +162,7 @@
 int
 GetInteger(void)
 {
-    char *token = strtok(NULL, w_space);
+    char *token = ConfigParser::strtokFile();
     int i;
 
     if (token == NULL)

=== modified file 'src/SquidConfig.h'
--- src/SquidConfig.h   2013-05-13 03:57:03 +0000
+++ src/SquidConfig.h   2013-05-16 03:21:38 +0000
@@ -332,7 +332,6 @@
 
         int ie_refresh;
         int vary_ignore_expire;
-        int pipeline_prefetch;
         int surrogate_is_remote;
         int request_entities;
         int detect_broken_server_pconns;
@@ -361,6 +360,8 @@
         int client_dst_passthru;
     } onoff;
 
+    int pipeline_max_prefetch;
+
     int forward_max_tries;
     int connect_retries;
 

=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc     2013-05-14 18:36:45 +0000
+++ src/cache_cf.cc     2013-05-22 12:17:28 +0000
@@ -965,6 +965,16 @@
                (uint32_t)Config.maxRequestBufferSize, 
(uint32_t)Config.maxRequestHeaderSize);
     }
 
+    /*
+     * Disable client side request pipelining if client_persistent_connections 
OFF.
+     * Waste of resources queueing any pipelined requests when the first will 
close the connection.
+     */
+    if (Config.pipeline_max_prefetch > 0 && !Config.onoff.client_pconns) {
+        debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: pipeline_prefetch " 
<< Config.pipeline_max_prefetch <<
+                   " requires client_persistent_connections ON. Forced 
pipeline_prefetch 0.");
+        Config.pipeline_max_prefetch = 0;
+    }
+
 #if USE_AUTH
     /*
      * disable client side request pipelining. There is a race with
@@ -973,12 +983,12 @@
      * pipelining OFF, the client may fail to authenticate, but squid's
      * state will be preserved.
      */
-    if (Config.onoff.pipeline_prefetch) {
+    if (Config.pipeline_max_prefetch > 0) {
         Auth::Config *nego = Auth::Config::Find("Negotiate");
         Auth::Config *ntlm = Auth::Config::Find("NTLM");
         if ((nego && nego->active()) || (ntlm && ntlm->active())) {
-            debugs(3, DBG_IMPORTANT, "WARNING: pipeline_prefetch breaks NTLM 
and Negotiate authentication. Forced OFF.");
-            Config.onoff.pipeline_prefetch = 0;
+            debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 
pipeline_prefetch breaks NTLM and Negotiate authentication. Forced 
pipeline_prefetch 0.");
+            Config.pipeline_max_prefetch = 0;
         }
     }
 #endif
@@ -2691,6 +2701,29 @@
 
 #define free_tristate free_int
 
+void
+parse_pipelinePrefetch(int *var)
+{
+    char *token = ConfigParser::strtokFile();
+
+    if (token == NULL)
+        self_destruct();
+
+    if (!strcmp(token, "on")) {
+        debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'pipeline_prefetch 
on' is deprecated. Please update to use 1 (or a higher number).");
+        *var = 1;
+    } else if (!strcmp(token, "off")) {
+        debugs(0, DBG_PARSE_NOTE(2), "WARNING: 'pipeline_prefetch off' is 
deprecated. Please update to use '0'.");
+        *var = 0;
+    } else {
+        ConfigParser::strtokFileUndo();
+        parse_int(var);
+    }
+}
+
+#define free_pipelinePrefetch free_int
+#define dump_pipelinePrefetch dump_int
+
 static void
 dump_refreshpattern(StoreEntry * entry, const char *name, RefreshPattern * 
head)
 {

=== modified file 'src/cf.data.depend'
--- src/cf.data.depend  2013-05-12 05:04:14 +0000
+++ src/cf.data.depend  2013-05-16 04:00:13 +0000
@@ -51,6 +51,7 @@
 onoff
 peer
 peer_access            cache_peer acl
+pipelinePrefetch
 PortCfg
 QosConfig
 refreshpattern

=== modified file 'src/cf.data.pre'
--- src/cf.data.pre     2013-05-14 17:53:18 +0000
+++ src/cf.data.pre     2013-05-21 02:50:03 +0000
@@ -8701,17 +8701,23 @@
 DOC_END
 
 NAME: pipeline_prefetch
-TYPE: onoff
-LOC: Config.onoff.pipeline_prefetch
-DEFAULT: off
+TYPE: pipelinePrefetch
+LOC: Config.pipeline_max_prefetch
+DEFAULT: 0
+DEFAULT_DOC: Do not pre-parse pipelined requests.
 DOC_START
-       To boost the performance of pipelined requests to closer
-       match that of a non-proxied environment Squid can try to fetch
-       up to two requests in parallel from a pipeline.
+       HTTP clients may send a pipeline of 1+N requests to Squid using a
+       single connection, without waiting for Squid to respond to the first
+       of those requests. This option limits the number of concurrent
+       requests Squid will try to handle in parallel. If set to N, Squid
+       will try to receive and process up to 1+N requests on the same
+       connection concurrently.
 
-       Defaults to off for bandwidth management and access logging
+       Defaults to 0 (off) for bandwidth management and access logging
        reasons.
 
+       NOTE: pipelining requires persistent connections to clients.
+
        WARNING: pipelining breaks NTLM and Negotiate/Kerberos authentication.
 DOC_END
 

=== modified file 'src/client_side.cc'
--- src/client_side.cc  2013-05-23 08:18:09 +0000
+++ src/client_side.cc  2013-05-25 06:58:00 +0000
@@ -2946,17 +2946,23 @@
     }
 }
 
-static int
-connOkToAddRequest(ConnStateData * conn)
+bool
+ConnStateData::concurrentRequestQueueFilled() const
 {
-    int result = conn->getConcurrentRequestCount() < 
(Config.onoff.pipeline_prefetch ? 2 : 1);
-
-    if (!result) {
-        debugs(33, 3, HERE << conn->clientConnection << " max concurrent 
requests reached");
-        debugs(33, 5, HERE << conn->clientConnection << " defering new request 
until one is done");
+    const int existingRequestCount = getConcurrentRequestCount();
+
+    // default to the configured pipeline size.
+    // add 1 because the head of pipeline is counted in concurrent requests 
and not prefetch queue
+    const int concurrentRequestLimit = Config.pipeline_max_prefetch + 1;
+
+    // when queue filled already we cant add more.
+    if (existingRequestCount >= concurrentRequestLimit) {
+        debugs(33, 3, clientConnection << " max concurrent requests reached (" 
<< concurrentRequestLimit << ")");
+        debugs(33, 5, clientConnection << " defering new request until one is 
done");
+        return false;
     }
 
-    return result;
+    return true;
 }
 
 /**
@@ -2981,8 +2987,8 @@
         if (in.notYetUsed == 0)
             break;
 
-        /* Limit the number of concurrent requests to 2 */
-        if (!connOkToAddRequest(this)) {
+        /* Limit the number of concurrent requests */
+        if (!pipelineQueueFilled()) {
             break;
         }
 

=== modified file 'src/client_side.h'
--- src/client_side.h   2013-04-04 06:15:00 +0000
+++ src/client_side.h   2013-05-25 07:06:30 +0000
@@ -178,7 +178,7 @@
 /**
  * Manages a connection to a client.
  *
- * Multiple requests (up to 2) can be pipelined. This object is responsible 
for managing
+ * Multiple requests (up to pipeline_prefetch) can be pipelined. This object 
is responsible for managing
  * which one is currently being fulfilled and what happens to the queue if the 
current one
  * causes the client connection to be closed early.
  *
@@ -392,6 +392,7 @@
     int connReadWasError(comm_err_t flag, int size, int xerrno);
     int connFinishedWithConn(int size);
     void clientAfterReadingRequests();
+    bool concurrentRequestQueueFilled() const;
 
 #if USE_AUTH
     /// some user details that can be used to perform authentication on this 
connection

Reply via email to