]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Run helpers on-demand
authorAmos Jeffries <squid3@treenet.co.nz>
Wed, 16 Dec 2009 03:46:59 +0000 (16:46 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Wed, 16 Dec 2009 03:46:59 +0000 (16:46 +1300)
For some config backwards compatibility the maximum is kept as a single
integer first parameter to the *children directives.

Default setting changes:

 Instead of starting N helpers on startup and each reconfigure this
 makes the default zero and the configured value a maximum cap.
 The default maximum is raised from 5 to 20 for all helpers except
 for dnsservers where the maximum is raised to the old documented
 maximum of 32.

Obsoleted settings:
 url_rewrite_concurrency
  - replaced by the concurrency=N option now available on all *_children
    directives (including auth_param X children).
    To avoid compile problems this directive had to be fully dropped.

 auth_param X concurrency N
  - as above. However the option was able to be retained, as deprecated
    for future removal as well.

Behavior changes:

Whenever a request needs to use a helper and there are none available
immediately Squid tests to see if its okay to start a new one. Then does so.

The "helpers dying too fast" warnings and Squid closing has been modified
Squid will now not care about dying helpers if there are more that
startup=N active. If the death causes less than startup=N to be running
and is hit twice in less than 30 seconds will cause the warning message
to be doisplayed and Squid to abort same as before.

NP: that with startup=0 (the new default) helpers dying before or after
their first use will not crash Squid. But may result in a loop of
hung/failed requests and WILL result in a great many helper-failed
warnings in cache.log.

If needed we can bump the startup default back to 1 to avoid all that.
Or add a special check to kill squid if helpers die during startup and
provide a clearer log message "Foo helper is dying before we can finish
starting it" etc.

TODO: the current patch has no way to dynamically decrease the number of
      helpers. Only a reconfigure or helper dying can do that.

29 files changed:
doc/release-notes/release-3.2.sgml
helpers/log_daemon/file/log_file_daemon.cc
src/HelperChildConfig.cc [new file with mode: 0644]
src/HelperChildConfig.h [new file with mode: 0644]
src/Makefile.am
src/adaptation/ecap/MessageRep.cc
src/auth/basic/auth_basic.cc
src/auth/basic/auth_basic.h
src/auth/digest/auth_digest.cc
src/auth/digest/auth_digest.h
src/auth/negotiate/auth_negotiate.cc
src/auth/negotiate/auth_negotiate.h
src/auth/ntlm/auth_ntlm.cc
src/auth/ntlm/auth_ntlm.h
src/cache_cf.cc
src/cf.data.depend
src/cf.data.pre
src/dns.cc
src/external_acl.cc
src/globals.h
src/helper.cc
src/helper.h
src/icmp/Makefile.am
src/main.cc
src/redirect.cc
src/structs.h
src/tests/stub_HelperChildConfig.cc [new file with mode: 0644]
src/tests/stub_helper.cc
src/tests/stub_tools.cc

index 641b072d0733663cdd5a04ef3c1e59480a266610..76335e959927677cfd07cc79e711b5e460c67096 100644 (file)
@@ -320,12 +320,22 @@ This section gives a thorough account of those changes in three categories:
        <tag>acl random</tag>
        <p>New type <em>random</em>. Pseudo-randomly match requests based on a configured probability.
 
+       <tag>auth_param</tag>
+       <p>New options for Basic, Digest, NTLM, Negotiate <em>children</em> settings.
+          <em>startup=N</em> determins minimum number of helper processes used.
+          <em>idle=N</em> determines how many helper to retain as buffer against sudden traffic loads.
+
        <tag>deny_info</tag>
        <p>Support URL format tags. For dynamically generated URL in denial redirect.
 
        <tag>external_acl_type</tag>
-       <p>New format tag <em>%SRCEUI48</em> EUI-48 / MAC address of client from ARP lookup.
-       <p>New format tag <em>%SRCEUI64</em> EUI-64 of clients with SLAAC address.
+       <p>New format tags and option parameters:
+       <p><em>%SRCEUI48</em> EUI-48 / MAC address of client from ARP lookup.
+       <p><em>%SRCEUI64</em> EUI-64 of clients with SLAAC address.
+       <p><em>children-max=N</em> determins maximum number of helper processes used.
+       <p><em>children-startup=N</em> determins minimum number of helper processes used.
+       <p><em>children-idle=N</em> determines how many helper to retain as buffer against sudden traffic loads.
+       <p>Deprecated <em>children=N</em> in favor of <em>children-max=N</em>.
 
        <tag>logformat</tag>
        <p><em>%sn</em> Unique sequence number per log line. Ported from 2.7
@@ -335,6 +345,12 @@ This section gives a thorough account of those changes in three categories:
        <tag>windows_ipaddrchangemonitor</tag>
        <p>Now only available to be set in Windows builds.
 
+       <tag>url_rewrite_children</tag>
+       <tag>New options <em>startup=N</em>, <em>idle=N</em>, <em>concurrency=N</em>
+       <p>startup=N allow finer tuning of how many helpers are started initially.
+       <p>idle=N allow fine tuning of how many helper to retain as buffer against sudden traffic loads.
+       <p>concurrency=N was previously called url_rewrite_concurrency as a distinct directive.
+
 </descrip>
 
 
@@ -344,6 +360,9 @@ This section gives a thorough account of those changes in three categories:
        <tag>ftp_list_width</tag>
        <p>Obsolete.
 
+       <tag>url_rewrite_concurrency</tag>
+       <p>Replaced by url_rewrite_children ... concurrency=N option.
+
 </descrip>
 
 
index 9552d82ef50be9487871d187d55628a37b5ae66d..3e86312385e6c7de7c3ded669e7f05771bd05fc7 100644 (file)
@@ -114,6 +114,28 @@ main(int argc, char *argv[])
         case 'L':
             if (buf[1] != '\0') {
                 fprintf(fp, "%s", buf + 1);
+                /* try to detect the 32-bit file too big write error and rotate */
+                int err = ferror(fp);
+                clearerr(fp);
+                if (err < 0) {
+                    /* file too big - recover by rotating the logs and starting a new one.
+                     * out of device space - recover by rotating and hoping that rotation count drops a big one.
+                     */
+                    if (err == EFBIG || err == ENOSPC) {
+                        fprintf(stderr, "WARNING: %s writing %s. Attempting to recover via a log rotation.\n",strerror(err),argv[1]);
+                        fclose(fp);
+                        rotate(argv[1], rotate_count);
+                        fp = fopen(argv[1], "a");
+                        if (fp == NULL) {
+                            perror("fopen");
+                            exit(1);
+                        }
+                        fprintf(fp, "%s", buf + 1);
+                    } else {
+                        perror("fprintf");
+                        exit(1);
+                    }
+                }
             }
             if (!do_buffer)
                 fflush(fp);
diff --git a/src/HelperChildConfig.cc b/src/HelperChildConfig.cc
new file mode 100644 (file)
index 0000000..8986f62
--- /dev/null
@@ -0,0 +1,89 @@
+#include "config.h"
+#include "HelperChildConfig.h"
+#include "globals.h"
+
+#include <string.h>
+
+HelperChildConfig::HelperChildConfig() :
+        n_max(0),
+        n_startup(1),
+        n_idle(1),
+        concurrency(1),
+        n_running(0),
+        n_active(0)
+{}
+
+HelperChildConfig::HelperChildConfig(const unsigned int m, const unsigned int s, const unsigned int i, const unsigned int cc) :
+        n_max(m),
+        n_startup(s),
+        n_idle(i),
+        concurrency(cc),
+        n_running(0),
+        n_active(0)
+{}
+
+HelperChildConfig::~HelperChildConfig()
+{}
+
+HelperChildConfig &
+HelperChildConfig::operator =(const HelperChildConfig &rhs)
+{
+    memcpy(this, &rhs, sizeof(HelperChildConfig));
+    return *this;
+}
+
+const int
+HelperChildConfig::needNew() const {
+    /* during the startup and reconfigure use our special amount... */
+    if (starting_up || reconfiguring) return n_startup;
+
+    /* keep a minimum of n_idle helpers free... */
+    if ( (n_active + n_idle) < n_max) return n_idle;
+
+    /* dont ever start more than n_max processes. */
+    return (n_max - n_active);
+}
+
+void
+HelperChildConfig::parseConfig()
+{
+    char const *token = strtok(NULL, w_space);
+
+    if (!token)
+        self_destruct();
+
+    /* starts with a bare number for the max... back-compatible */
+    n_max = atoi(token);
+
+    if (n_max < 1)
+        self_destruct();
+
+    /* Parse extension options */
+    for (; (token = strtok(NULL, w_space)) ;) {
+        if (strncmp(token, "startup=", 8) == 0) {
+            n_startup = atoi(token + 8);
+        } else if (strncmp(token, "idle=", 5) == 0) {
+            n_idle = atoi(token + 5);
+            if (n_idle < 1) {
+                debugs(0,0,"WARNING OVERIDE: Using idle=0 for helpers causes request failures. Overiding to use idle=1 instead.");
+                n_idle = 1;
+            }
+        } else if (strncmp(token, "concurrency=", 12) == 0) {
+            concurrency = atoi(token + 12);
+        } else {
+            self_destruct();
+        }
+    }
+
+    /* simple sanity. */
+
+    if (n_startup > n_max) {
+        debugs(0,0,"WARNING OVERIDE: Capping startup=" << n_startup << " to the defined maximum (" << n_max <<")");
+        n_startup = n_max;
+    }
+
+    if (n_idle > n_max) {
+        debugs(0,0,"WARNING OVERIDE: Capping idle=" << n_idle << " to the defined maximum (" << n_max <<")");
+        n_idle = n_max;
+    }
+}
diff --git a/src/HelperChildConfig.h b/src/HelperChildConfig.h
new file mode 100644 (file)
index 0000000..73bc38d
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef _SQUID_SRC_HELPERCHILDCONFIG_H
+#define _SQUID_SRC_HELPERCHILDCONFIG_H
+
+/**
+ * Contains statistics of a particular type of child helper.
+ *
+ * Some derived from a helper children configuration option,
+ * some from runtime stats on the currently active children.
+ */
+class HelperChildConfig {
+public:
+    HelperChildConfig();
+    HelperChildConfig(const unsigned int m, const unsigned int s, const unsigned int i, const unsigned int cc);
+    ~HelperChildConfig();
+    HelperChildConfig &operator =(const HelperChildConfig &rhs);
+
+    /*
+     * When new helpers are needed call this to find out how many more
+     * we are allowed to start.
+     * \retval 0       No more helpers may be started right now.
+     * \retval N < 0   Error. No more helpers may be started.
+     * \retval N       N more helpers may be started immediately.
+     */
+    const int needNew() const;
+    void parseConfig();
+
+    /* values from squid.conf */
+public:
+
+    /** maximum child process limits. How many of this helper the system can cope with */
+    unsigned int n_max;
+
+    /**
+     * Number of children to kick off at startup.
+     * set via the startup=N option.
+     *
+     * By default if undefined 1 will be started immediately for use.
+     * The minimum/idle amount will be scheduled for starting as soon as possible after startup is completed.
+     */
+    unsigned int n_startup;
+
+    /**
+     * Number of helper children to keep available as a buffer against sudden bursts of requests.
+     * set via the idle=N option. May be zero.
+     *
+     * The default value for backward compatibility the default for this is the same as maximum children.
+     * For now the actual number of idle children is only reduced by a reconfigure operation. This may change.
+     */
+    unsigned int n_idle;
+
+    /**
+     * How many concurrent requests each child helper may be capable of handling.
+     * Default: 1  - no concurrency possible.
+     */
+    unsigned int concurrency;
+
+    /* derived from active operations */
+public:
+
+    /**
+     * Total helper children objects currently existing.
+     * Produced as a side effect of starting children or their stopping.
+     */
+    unsigned int n_running;
+
+    /**
+     * Count of helper children active (not shutting down).
+     * This includes both idle and in-use children.
+     */
+    unsigned int n_active;
+};
+
+/* Legacy parser interface */
+#define parse_HelperChildConfig(c)     (c)->parseConfig()
+#define dump_HelperChildConfig(e,n,c)  storeAppendPrintf((e), "\n%s %d startup=%d idle=%d\n", (n), (c).n_max, (c).n_startup, (c).n_idle)
+#define free_HelperChildConfig(dummy)  // NO.
+
+#endif /* _SQUID_SRC_HELPERCHILDCONFIG_H */
index d8c057ac0cda469542b19f5387d40b018c60486e..914d9377c5d4b1c7789fbb945d79973a28e12ab9 100644 (file)
@@ -330,6 +330,8 @@ squid_SOURCES = \
        gopher.cc \
        helper.cc \
        helper.h \
+       HelperChildConfig.h \
+       HelperChildConfig.cc \
        hier_code.h \
        HierarchyLogEntry.h \
        $(HTCPSOURCE) \
@@ -600,6 +602,7 @@ recv_announce_SOURCES = recv-announce.cc SquidNew.cc
 ## mem.cc wants ClientInfo.h
 ## libbase.la wants cbdata.*
 ## libbase.la wants MemBuf.*
+## structs.h wants HelperChildConfig.* (stub it)
 ufsdump_SOURCES = \
        ClientInfo.h \
        cbdata.h \
@@ -624,6 +627,8 @@ ufsdump_SOURCES = \
        ufsdump.cc \
        dlink.h \
        dlink.cc \
+       HelperChildConfig.h \
+       tests/stub_HelperChildConfig.cc \
        HttpRequestMethod.cc \
        RemovalPolicy.cc \
        squid.h \
@@ -938,6 +943,7 @@ tests_testHttpReply_SOURCES=\
        Packer.h \
        Packer.cc \
        tests/stub_cache_manager.cc \
+       tests/stub_HelperChildConfig.cc \
        tests/stub_StatHist.cc \
        tests/stub_store.cc \
        SquidString.h \
@@ -962,6 +968,8 @@ tests_testHttpReply_DEPENDENCIES= $(SQUID_CPPUNIT_LA) \
 tests_testAuth_SOURCES = \
        tests/testAuth.cc tests/testMain.cc  tests/testAuth.h \
        ConfigParser.cc \
+       HelperChildConfig.h \
+       HelperChildConfig.cc \
        tests/stub_acl.cc tests/stub_cache_cf.cc \
        tests/stub_helper.cc cbdata.cc String.cc \
        tests/stub_store.cc HttpHeaderTools.cc HttpHeader.cc mem.cc ClientInfo.h \
@@ -1023,6 +1031,8 @@ tests_testACLMaxUserIP_SOURCES= \
        ClientInfo.h \
        ConfigParser.cc \
        ETag.cc \
+       HelperChildConfig.h \
+       HelperChildConfig.cc \
        HttpHeader.cc \
        HttpHeaderTools.cc \
        HttpHdrContRange.cc \
@@ -1127,6 +1137,8 @@ tests_testCacheManager_SOURCES = \
        gopher.cc \
        hier_code.h \
        helper.cc \
+       HelperChildConfig.h \
+       HelperChildConfig.cc \
        $(HTCPSOURCE) \
        http.cc \
        HttpBody.cc \
@@ -1234,7 +1246,8 @@ tests_testDiskIO_SOURCES = \
        tests/testDiskIO.cc \
        tests/testDiskIO.h \
        tests/testMain.cc \
-       tests/stub_cache_manager.cc
+       tests/stub_cache_manager.cc \
+       tests/stub_HelperChildConfig.cc
 nodist_tests_testDiskIO_SOURCES= \
        $(SWAP_TEST_GEN_SOURCES) \
        SquidMath.cc \
@@ -1304,6 +1317,8 @@ tests_testEvent_SOURCES = \
        gopher.cc \
        hier_code.h \
        helper.cc \
+       HelperChildConfig.h \
+       HelperChildConfig.cc \
        $(HTCPSOURCE) \
        http.cc \
        HttpBody.cc \
@@ -1453,6 +1468,8 @@ tests_testEventLoop_SOURCES = \
        ftp.cc \
        gopher.cc \
        helper.cc \
+       HelperChildConfig.h \
+       HelperChildConfig.cc \
        hier_code.h \
        $(HTCPSOURCE) \
        http.cc \
@@ -1592,6 +1609,8 @@ tests_test_http_range_SOURCES = \
        ftp.cc \
        gopher.cc \
        helper.cc \
+       HelperChildConfig.h \
+       HelperChildConfig.cc \
        hier_code.h \
        $(HTCPSOURCE) \
        http.cc \
@@ -1747,6 +1766,8 @@ tests_testHttpRequest_SOURCES = \
        ftp.cc \
        gopher.cc \
        helper.cc \
+       HelperChildConfig.h \
+       HelperChildConfig.cc \
        hier_code.h \
        $(HTCPSOURCE) \
        http.cc \
@@ -1908,6 +1929,7 @@ tests_testStore_SOURCES= \
        tests/TestSwapDir.cc \
        tests/TestSwapDir.h \
        tests/stub_fd.cc \
+       tests/stub_HelperChildConfig.cc \
        tests/stub_HttpReply.cc \
        tests/stub_cache_manager.cc \
        $(STORE_TEST_SOURCES)
@@ -1940,6 +1962,7 @@ tests_testString_SOURCES = \
        tests/testString.cc \
        tests/testString.h \
        tests/stub_cache_manager.cc \
+       tests/stub_HelperChildConfig.cc \
        time.cc
 nodist_tests_testString_SOURCES = \
        $(TESTSOURCES)
@@ -2012,6 +2035,7 @@ tests_testUfs_SOURCES = \
        tests/testMain.cc \
        tests/testUfs.h \
        tests/stub_cache_manager.cc \
+       tests/stub_HelperChildConfig.cc \
        $(SWAP_TEST_SOURCES)
 nodist_tests_testUfs_SOURCES = \
        $(SWAP_TEST_GEN_SOURCES) \
@@ -2032,6 +2056,7 @@ tests_testCoss_SOURCES = \
        tests/testMain.cc \
        tests/testCoss.h \
        tests/stub_cache_manager.cc \
+       tests/stub_HelperChildConfig.cc \
        $(SWAP_TEST_SOURCES)
 nodist_tests_testCoss_SOURCES = \
        swap_log_op.cc \
@@ -2111,6 +2136,8 @@ tests_testURL_SOURCES = \
        ftp.cc \
        gopher.cc \
        helper.cc \
+       HelperChildConfig.h \
+       HelperChildConfig.cc \
        hier_code.h \
        $(HTCPSOURCE) \
        http.cc \
index f494d2d3b27422e8caa9eca07016240a67e00053..ac50b731ee7a0fb79364b07d717e352b81dd8bf5 100644 (file)
@@ -142,6 +142,8 @@ Adaptation::Ecap::FirstLineRep::protocol() const
         return protocolCacheObj;
     case PROTO_INTERNAL:
         return protocolInternal;
+    case PROTO_ICY:
+        return Name();
     case PROTO_NONE:
         return Name();
 
index bc67847427cb48f481a57f0b9e58d53be34e5382..ef1bf15c23da67c0db0eaa3529cbf9fac7696c98 100644 (file)
@@ -88,9 +88,7 @@ basicScheme::done()
     if (!shutting_down)
         return;
 
-    if (basicauthenticators)
-        helperFree(basicauthenticators);
-
+    delete basicauthenticators;
     basicauthenticators = NULL;
 
     /* XXX Reinstate auth shutdown for dynamic schemes? */
@@ -106,7 +104,7 @@ AuthBasicConfig::active() const
 bool
 AuthBasicConfig::configured() const
 {
-    if ((authenticate != NULL) && (authenticateChildren != 0) &&
+    if ((authenticate != NULL) && (authenticateChildren.n_max != 0) &&
             (basicAuthRealm != NULL)) {
         debugs(29, 9, HERE << "returning configured");
         return true;
@@ -303,16 +301,15 @@ AuthBasicConfig::dump(StoreEntry * entry, const char *name, AuthConfig * scheme)
     storeAppendPrintf(entry, "\n");
 
     storeAppendPrintf(entry, "%s basic realm %s\n", name, basicAuthRealm);
-    storeAppendPrintf(entry, "%s basic children %d\n", name, authenticateChildren);
+    storeAppendPrintf(entry, "%s basic children %d startup=%d idle=%d\n", name, authenticateChildren.n_max, authenticateChildren.n_startup, authenticateChildren.n_idle);
     storeAppendPrintf(entry, "%s basic concurrency %d\n", name, authenticateConcurrency);
     storeAppendPrintf(entry, "%s basic credentialsttl %d seconds\n", name, (int) credentialsTTL);
     storeAppendPrintf(entry, "%s basic casesensitive %s\n", name, casesensitive ? "on" : "off");
 }
 
-AuthBasicConfig::AuthBasicConfig()
+AuthBasicConfig::AuthBasicConfig() : authenticateChildren(20,0,1,1)
 {
     /* TODO: move into initialisation list */
-    authenticateChildren = 5;
     credentialsTTL = 2 * 60 * 60;      /* two hours */
     basicAuthRealm = xstrdup("Squid proxy-caching web server");
 }
@@ -333,7 +330,7 @@ AuthBasicConfig::parse(AuthConfig * scheme, int n_configured, char *param_str)
 
         requirePathnameExists("auth_param basic program", authenticate->key);
     } else if (strcasecmp(param_str, "children") == 0) {
-        parse_int(&authenticateChildren);
+        authenticateChildren.parseConfig();
     } else if (strcasecmp(param_str, "concurrency") == 0) {
         parse_int(&authenticateConcurrency);
     } else if (strcasecmp(param_str, "realm") == 0) {
@@ -607,13 +604,13 @@ AuthBasicConfig::init(AuthConfig * scheme)
         authbasic_initialised = 1;
 
         if (basicauthenticators == NULL)
-            basicauthenticators = helperCreate("basicauthenticator");
+            basicauthenticators = new helper("basicauthenticator");
 
         basicauthenticators->cmdline = authenticate;
 
-        basicauthenticators->n_to_start = authenticateChildren;
+        basicauthenticators->childs = authenticateChildren;
 
-        basicauthenticators->concurrency = authenticateConcurrency;
+        basicauthenticators->childs.concurrency = authenticateConcurrency;
 
         basicauthenticators->ipc_type = IPC_STREAM;
 
index 26001b57a66d95f5c124497e05966a6c1bcc6c3f..079addb13c771c5476f00a29a0a3ec68a60136cd 100644 (file)
@@ -107,6 +107,8 @@ private:
 
 MEMPROXY_CLASS_INLINE(AuthBasicUserRequest);
 
+#include "HelperChildConfig.h"
+
 /* configuration runtime data */
 
 class AuthBasicConfig : public AuthConfig
@@ -125,7 +127,7 @@ public:
     virtual void parse(AuthConfig *, int, char *);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
-    int authenticateChildren;
+    HelperChildConfig authenticateChildren;
     int authenticateConcurrency;
     char *basicAuthRealm;
     wordlist *authenticate;
index bf0add93133a7740d6eb3abb5764d32dd59fcf0d..909ce9829870ea49a7b50f7369e223ef5d03e487 100644 (file)
@@ -512,10 +512,8 @@ digestScheme::done()
         return;
     }
 
-    if (digestauthenticators) {
-        helperFree(digestauthenticators);
-        digestauthenticators = NULL;
-    }
+    delete digestauthenticators;
+    digestauthenticators = NULL;
 
     authDigestUserShutdown();
     authenticateDigestNonceShutdown();
@@ -534,9 +532,9 @@ AuthDigestConfig::dump(StoreEntry * entry, const char *name, AuthConfig * scheme
         list = list->next;
     }
 
-    storeAppendPrintf(entry, "\n%s %s realm %s\n%s %s children %d\n%s %s nonce_max_count %d\n%s %s nonce_max_duration %d seconds\n%s %s nonce_garbage_interval %d seconds\n",
+    storeAppendPrintf(entry, "\n%s %s realm %s\n%s %s children %d startup=%d idle=%d\n%s %s nonce_max_count %d\n%s %s nonce_max_duration %d seconds\n%s %s nonce_garbage_interval %d seconds\n",
                       name, "digest", digestAuthRealm,
-                      name, "digest", authenticateChildren,
+                      name, "digest", authenticateChildren.n_max, authenticateChildren.n_startup, authenticateChildren.n_idle,
                       name, "digest", noncemaxuses,
                       name, "digest", (int) noncemaxduration,
                       name, "digest", (int) nonceGCInterval);
@@ -552,7 +550,7 @@ bool
 AuthDigestConfig::configured() const
 {
     if ((authenticate != NULL) &&
-            (authenticateChildren != 0) &&
+            (authenticateChildren.n_max != 0) &&
             (digestAuthRealm != NULL) && (noncemaxduration > -1))
         return true;
 
@@ -873,11 +871,11 @@ AuthDigestConfig::init(AuthConfig * scheme)
         authdigest_initialised = 1;
 
         if (digestauthenticators == NULL)
-            digestauthenticators = helperCreate("digestauthenticator");
+            digestauthenticators = new helper("digestauthenticator");
 
         digestauthenticators->cmdline = authenticate;
 
-        digestauthenticators->n_to_start = authenticateChildren;
+        digestauthenticators->childs = authenticateChildren;
 
         digestauthenticators->ipc_type = IPC_STREAM;
 
@@ -906,11 +904,9 @@ AuthDigestConfig::done()
     safe_free(digestAuthRealm);
 }
 
-
-AuthDigestConfig::AuthDigestConfig()
+AuthDigestConfig::AuthDigestConfig() : authenticateChildren(20,0,1,1)
 {
     /* TODO: move into initialisation list */
-    authenticateChildren = 5;
     /* 5 minutes */
     nonceGCInterval = 5 * 60;
     /* 30 minutes */
@@ -934,7 +930,7 @@ AuthDigestConfig::parse(AuthConfig * scheme, int n_configured, char *param_str)
 
         requirePathnameExists("auth_param digest program", authenticate->key);
     } else if (strcasecmp(param_str, "children") == 0) {
-        parse_int(&authenticateChildren);
+        authenticateChildren.parseConfig();
     } else if (strcasecmp(param_str, "realm") == 0) {
         parse_eol(&digestAuthRealm);
     } else if (strcasecmp(param_str, "nonce_garbage_interval") == 0) {
index 02c69773c0b652f75e75ff2a53b1585b91f2b15e..feb25fd36b58f1d7474eba8fc2e883c005ccec0b 100644 (file)
@@ -134,6 +134,8 @@ struct _digest_nonce_h : public hash_link {
     } flags;
 };
 
+#include "HelperChildConfig.h"
+
 /* configuration runtime data */
 
 class AuthDigestConfig : public AuthConfig
@@ -151,7 +153,7 @@ public:
     virtual void parse(AuthConfig *, int, char *);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
-    int authenticateChildren;
+    HelperChildConfig authenticateChildren;
     char *digestAuthRealm;
     wordlist *authenticate;
     time_t nonceGCInterval;
index 948422083cd30787733e28fb46ed0e72947625ed..16772fb62680da1f799bcd5e088a9f749b3598f4 100644 (file)
@@ -112,9 +112,7 @@ negotiateScheme::done()
     if (!shutting_down)
         return;
 
-    if (negotiateauthenticators)
-        helperStatefulFree(negotiateauthenticators);
-
+    delete negotiateauthenticators;
     negotiateauthenticators = NULL;
 
     debugs(29, 2, "negotiateScheme::done: Negotiate authentication Shutdown.");
@@ -138,13 +136,13 @@ AuthNegotiateConfig::dump(StoreEntry * entry, const char *name, AuthConfig * sch
         list = list->next;
     }
 
-    storeAppendPrintf(entry, "\n%s negotiate children %d\n",
-                      name, authenticateChildren);
+    storeAppendPrintf(entry, "\n%s negotiate children %d startup=%d idle=%d\n",
+                      name, authenticateChildren.n_max, authenticateChildren.n_startup, authenticateChildren.n_idle);
     storeAppendPrintf(entry, "%s %s keep_alive %s\n", name, "negotiate", keep_alive ? "on" : "off");
 
 }
 
-AuthNegotiateConfig::AuthNegotiateConfig() : authenticateChildren(5), keep_alive(1)
+AuthNegotiateConfig::AuthNegotiateConfig() : authenticateChildren(20,0,1,1), keep_alive(1)
 { }
 
 void
@@ -158,7 +156,7 @@ AuthNegotiateConfig::parse(AuthConfig * scheme, int n_configured, char *param_st
 
         requirePathnameExists("auth_param negotiate program", authenticate->key);
     } else if (strcasecmp(param_str, "children") == 0) {
-        parse_int(&authenticateChildren);
+        authenticateChildren.parseConfig();
     } else if (strcasecmp(param_str, "keep_alive") == 0) {
         parse_onoff(&keep_alive);
     } else {
@@ -195,7 +193,7 @@ AuthNegotiateConfig::init(AuthConfig * scheme)
         authnegotiate_initialised = 1;
 
         if (negotiateauthenticators == NULL)
-            negotiateauthenticators = helperStatefulCreate("negotiateauthenticator");
+            negotiateauthenticators = new statefulhelper("negotiateauthenticator");
 
         if (!proxy_auth_cache)
             proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
@@ -204,7 +202,7 @@ AuthNegotiateConfig::init(AuthConfig * scheme)
 
         negotiateauthenticators->cmdline = authenticate;
 
-        negotiateauthenticators->n_to_start = authenticateChildren;
+        negotiateauthenticators->childs = authenticateChildren;
 
         negotiateauthenticators->ipc_type = IPC_STREAM;
 
@@ -232,7 +230,7 @@ AuthNegotiateConfig::active() const
 bool
 AuthNegotiateConfig::configured() const
 {
-    if ((authenticate != NULL) && (authenticateChildren != 0)) {
+    if ((authenticate != NULL) && (authenticateChildren.n_max != 0)) {
         debugs(29, 9, "AuthNegotiateConfig::configured: returning configured");
         return true;
     }
index e28f518e521af314c1c29ad81df90dcf9b0e162f..74bd5a48d26ee7d648df5f5130dda623ce4eb3b8 100644 (file)
@@ -110,6 +110,8 @@ private:
 
 MEMPROXY_CLASS_INLINE(AuthNegotiateUserRequest);
 
+#include "HelperChildConfig.h"
+
 /* configuration runtime data */
 
 /// \ingroup AuthNegotiateAPI
@@ -128,7 +130,7 @@ public:
     virtual void parse(AuthConfig *, int, char *);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
-    int authenticateChildren;
+    HelperChildConfig authenticateChildren;
     int keep_alive;
     wordlist *authenticate;
 };
index a2b119bf3e2461f243422201daf05e595e598e48..85fe175c072d5b9151bc38b6ead50c259c06544d 100644 (file)
@@ -93,9 +93,7 @@ ntlmScheme::done()
     if (!shutting_down)
         return;
 
-    if (ntlmauthenticators)
-        helperStatefulFree(ntlmauthenticators);
-
+    delete ntlmauthenticators;
     ntlmauthenticators = NULL;
 
     debugs(29, 2, "ntlmScheme::done: NTLM authentication Shutdown.");
@@ -120,13 +118,13 @@ AuthNTLMConfig::dump(StoreEntry * entry, const char *name, AuthConfig * scheme)
         list = list->next;
     }
 
-    storeAppendPrintf(entry, "\n%s ntlm children %d\n",
-                      name, authenticateChildren);
+    storeAppendPrintf(entry, "\n%s ntlm children %d startup=%d idle=%d\n",
+                      name, authenticateChildren.n_max, authenticateChildren.n_startup, authenticateChildren.n_idle);
     storeAppendPrintf(entry, "%s %s keep_alive %s\n", name, "ntlm", keep_alive ? "on" : "off");
 
 }
 
-AuthNTLMConfig::AuthNTLMConfig() : authenticateChildren(5), keep_alive(1)
+AuthNTLMConfig::AuthNTLMConfig() : authenticateChildren(20,0,1,1), keep_alive(1)
 { }
 
 void
@@ -140,7 +138,7 @@ AuthNTLMConfig::parse(AuthConfig * scheme, int n_configured, char *param_str)
 
         requirePathnameExists("auth_param ntlm program", authenticate->key);
     } else if (strcasecmp(param_str, "children") == 0) {
-        parse_int(&authenticateChildren);
+        authenticateChildren.parseConfig();
     } else if (strcasecmp(param_str, "keep_alive") == 0) {
         parse_onoff(&keep_alive);
     } else {
@@ -175,7 +173,7 @@ AuthNTLMConfig::init(AuthConfig * scheme)
         authntlm_initialised = 1;
 
         if (ntlmauthenticators == NULL)
-            ntlmauthenticators = helperStatefulCreate("ntlmauthenticator");
+            ntlmauthenticators = new statefulhelper("ntlmauthenticator");
 
         if (!proxy_auth_cache)
             proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
@@ -184,7 +182,7 @@ AuthNTLMConfig::init(AuthConfig * scheme)
 
         ntlmauthenticators->cmdline = authenticate;
 
-        ntlmauthenticators->n_to_start = authenticateChildren;
+        ntlmauthenticators->childs = authenticateChildren;
 
         ntlmauthenticators->ipc_type = IPC_STREAM;
 
@@ -212,7 +210,7 @@ AuthNTLMConfig::active() const
 bool
 AuthNTLMConfig::configured() const
 {
-    if ((authenticate != NULL) && (authenticateChildren != 0)) {
+    if ((authenticate != NULL) && (authenticateChildren.n_max != 0)) {
         debugs(29, 9, "AuthNTLMConfig::configured: returning configured");
         return true;
     }
index e26cba601809b872cf205a8f912173fb3cc87f78..5e43c9140b4480df71595dcdd7c90b6ca07a2c35 100644 (file)
@@ -96,6 +96,8 @@ private:
 
 MEMPROXY_CLASS_INLINE(AuthNTLMUserRequest);
 
+#include "HelperChildConfig.h"
+
 /* configuration runtime data */
 
 class AuthNTLMConfig : public AuthConfig
@@ -113,7 +115,7 @@ public:
     virtual void parse(AuthConfig *, int, char *);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
-    int authenticateChildren;
+    HelperChildConfig authenticateChildren;
     int keep_alive;
     wordlist *authenticate;
 };
index c3e56e08b36a8f5472eb138eabc38158037c493b..e35b9413eb2dba64bd0c30d35658764fa86cc1a9 100644 (file)
@@ -472,14 +472,14 @@ configDoConfigure(void)
 
 #if USE_DNSSERVERS
 
-    if (Config.dnsChildren < 1)
+    if (Config.dnsChildren.n_max < 1)
         fatal("No dnsservers allocated");
 
 #endif
 
     if (Config.Program.redirect) {
-        if (Config.redirectChildren < 1) {
-            Config.redirectChildren = 0;
+        if (Config.redirectChildren.n_max < 1) {
+            Config.redirectChildren.n_max = 0;
             wordlistDestroy(&Config.Program.redirect);
         }
     }
index c09aa8749b2cd5235131ef727fae8968c7937b0e..8215ce395135879d088aded6d2f8d0f187b72231 100644 (file)
@@ -19,6 +19,7 @@ delay_pool_rates      delay_class
 denyinfo               acl
 eol
 externalAclHelper      auth_param
+HelperChildConfig
 hostdomain             cache_peer
 hostdomaintype         cache_peer
 http_header_access
index ef12b4582e8e75f4611a2d0756bdd447255517f0..b20b455c549b52e2b0bf9b41f925a90ba6f04c57 100644 (file)
@@ -130,13 +130,20 @@ DOC_START
        translate the HTTP iso-latin-1 charset to UTF-8 before sending the
        username & password to the helper.
 
-       "children" numberofchildren
-       The number of authenticator processes to spawn. If you start too few
+       "children" numberofchildren [startup=N] [idle=N]
+       The maximum number of authenticator processes to spawn. If you start too few
        Squid will have to wait for them to process a backlog of credential
        verifications, slowing it down. When password verifications are
        done via a (slow) network you are likely to need lots of
        authenticator processes.
-       auth_param basic children 5
+
+       The startup= and idle= options permit some skew in the exact amount
+       run. A minimum of startup=N will begin during startup and reconfigure
+       and Squid will start more in groups of up to idle=N in an attempt to meet
+       traffic needs and to keep idle=N free above those traffic needs up to
+       the maximum.
+
+       auth_param basic children 20 startup=0 idle=1
 
        "concurrency" concurrency
        The number of concurrent requests the helper can process.
@@ -198,13 +205,20 @@ DOC_START
        translate the HTTP iso-latin-1 charset to UTF-8 before sending the
        username & password to the helper.
 
-       "children" numberofchildren
-       The number of authenticator processes to spawn (no default).
+       "children" numberofchildren [startup=N] [idle=N]
+       The maximum number of authenticator processes to spawn (default 5).
        If you start too few Squid will have to wait for them to
        process a backlog of H(A1) calculations, slowing it down.
        When the H(A1) calculations are done via a (slow) network
        you are likely to need lots of authenticator processes.
-       auth_param digest children 5
+
+       The startup= and idle= options permit some skew in the exact amount
+       run. A minimum of startup=N will begin during startup and reconfigure
+       and Squid will start more in groups of up to idle=N in an attempt to meet
+       traffic needs and to keep idle=N free above those traffic needs up to
+       the maximum.
+
+       auth_param digest children 20 startup=0 idle=1
 
        "realm" realmstring
        Specifies the realm name which is to be reported to the
@@ -254,15 +268,21 @@ DOC_START
 
        auth_param ntlm program @DEFAULT_PREFIX@/bin/ntlm_auth
 
-       "children" numberofchildren
-       The number of authenticator processes to spawn (no default).
+       "children" numberofchildren [startup=N] [idle=N]
+       The maximum number of authenticator processes to spawn (default 5).
        If you start too few Squid will have to wait for them to
        process a backlog of credential verifications, slowing it
        down. When credential verifications are done via a (slow)
        network you are likely to need lots of authenticator
        processes.
 
-       auth_param ntlm children 5
+       The startup= and idle= options permit some skew in the exact amount
+       run. A minimum of startup=N will begin during startup and reconfigure
+       and Squid will start more in groups of up to idle=N in an attempt to meet
+       traffic needs and to keep idle=N free above those traffic needs up to
+       the maximum.
+
+       auth_param ntlm children 20 startup=0 idle=1
 
        "keep_alive" on|off
        If you experience problems with PUT/POST requests when using the
@@ -289,14 +309,21 @@ DOC_START
 
        auth_param negotiate program @DEFAULT_PREFIX@/bin/ntlm_auth --helper-protocol=gss-spnego
 
-       "children" numberofchildren
-       The number of authenticator processes to spawn (no default).
+       "children" numberofchildren [startup=N] [idle=N]
+       The maximum number of authenticator processes to spawn (default 5).
        If you start too few Squid will have to wait for them to
        process a backlog of credential verifications, slowing it
        down. When crendential verifications are done via a (slow)
        network you are likely to need lots of authenticator
        processes.
-       auth_param negotiate children 5
+
+       The startup= and idle= options permit some skew in the exact amount
+       run. A minimum of startup=N will begin during startup and reconfigure
+       and Squid will start more in groups of up to idle=N in an attempt to meet
+       traffic needs and to keep idle=N free above those traffic needs up to
+       the maximum.
+
+       auth_param negotiate children 20 startup=0 idle=1
 
        "keep_alive" on|off
        If you experience problems with PUT/POST requests when using the
@@ -312,22 +339,22 @@ DOC_START
 
 #Recommended minimum configuration per scheme:
 #auth_param negotiate program <uncomment and complete this line to activate>
-#auth_param negotiate children 5
+#auth_param negotiate children 20 startup=0 idle=1
 #auth_param negotiate keep_alive on
 #
 #auth_param ntlm program <uncomment and complete this line to activate>
-#auth_param ntlm children 5
+#auth_param ntlm children 20 startup=0 idle=1
 #auth_param ntlm keep_alive on
 #
 #auth_param digest program <uncomment and complete this line>
-#auth_param digest children 5
+#auth_param digest children 20 startup=0 idle=1
 #auth_param digest realm Squid proxy-caching web server
 #auth_param digest nonce_garbage_interval 5 minutes
 #auth_param digest nonce_max_duration 30 minutes
 #auth_param digest nonce_max_count 50
 #
 #auth_param basic program <uncomment and complete this line>
-#auth_param basic children 5
+#auth_param basic children 5 stratup=5 idle=1
 #auth_param basic realm Squid proxy-caching web server
 #auth_param basic credentialsttl 2 hours
 DOC_END
@@ -390,14 +417,24 @@ DOC_START
          negative_ttl=n
                        TTL for cached negative lookups (default same
                        as ttl)
-         children=n    Number of acl helper processes spawn to service
-                       external acl lookups of this type. (default 5)
+         children-max=n
+                       Maximum number of acl helper processes spawned to service
+                       external acl lookups of this type. (default 20)
+         children-startup=n
+                       Minimum number of acl helper processes to spawn during
+                       startup and reconfigure to service external acl lookups
+                       of this type. (default 0)
+         children-idle=n
+                       Number of acl helper processes to keep ahead of traffic
+                       loads. Squid will spawn this many at once whenever load
+                       rises above the capabilities of existing processes.
+                       Up to the value of children-max. (default 1)
          concurrency=n concurrency level per process. Only used with helpers
                        capable of processing more than one query at a time.
-         cache=n       result cache size, 0 is unbounded (default)
+         cache=n       limit the result cache size, default is unbounded.
          grace=n       Percentage remaining of TTL where a refresh of a
                        cached entry should be initiated without needing to
-                       wait for a new reply. (default 0 for no grace period)
+                       wait for a new reply. (default is for no grace period)
          protocol=2.5  Compatibility mode for Squid-2.5 external acl helpers
          ipv4 / ipv6   IP-mode used to communicate to this helper.
                        For compatability with older configurations and helpers
@@ -3158,21 +3195,36 @@ DOC_START
 DOC_END
 
 NAME: url_rewrite_children redirect_children
-TYPE: int
-DEFAULT: 5
+TYPE: HelperChildConfig
+DEFAULT: 20 startup=0 idle=1 concurrency=0
 LOC: Config.redirectChildren
 DOC_START
-       The number of redirector processes to spawn. If you start
-       too few Squid will have to wait for them to process a backlog of
-       URLs, slowing it down. If you start too many they will use RAM
-       and other system resources.
-DOC_END
+       The maximum number of redirector processes to spawn. If you limit
+       it too few Squid will have to wait for them to process a backlog of
+       URLs, slowing it down. If you allow too many they will use RAM
+       and other system resources noticably.
+       
+       The startup= and idle= options allow some measure of skew in your
+       tuning.
+       
+               startup=
+       
+       Sets a minimum of how many processes are to be spawned when Squid
+       starts or reconfigures. When set to zero the first request will
+       cause spawning of the first child process to handle it.
+       
+       Starting too few will cause an initial slowdown in traffic as Squid
+       attempts to simultaneously spawn enough processes to cope.
+       
+               idle=
+       
+       Sets a minimum of how many processes Squid is to try and keep available
+       at all times. When traffic begins to rise above what the existing
+       processes can handle this many more will be spawned up to the maximum
+       configured. A minimum setting of 1 is required.
+
+               concurrency=
 
-NAME: url_rewrite_concurrency redirect_concurrency
-TYPE: int
-DEFAULT: 0
-LOC: Config.redirectConcurrency
-DOC_START
        The number of requests each redirector helper can handle in
        parallel. Defaults to 0 which indicates the redirector
        is a old-style single threaded redirector.
@@ -6133,17 +6185,35 @@ DOC_START
 DOC_END
 
 NAME: dns_children
-TYPE: int
+TYPE: HelperChildConfig
 IFDEF: USE_DNSSERVERS
-DEFAULT: 5
+DEFAULT: 32 startup=1 idle=1
 LOC: Config.dnsChildren
 DOC_START
-       The number of processes spawn to service DNS name lookups.
-       For heavily loaded caches on large servers, you should
-       probably increase this value to at least 10.  The maximum
-       is 32.  The default is 5.
-
-       You must have at least one dnsserver process.
+       The maximum number of processes spawn to service DNS name lookups.
+       If you limit it too few Squid will have to wait for them to process
+       a backlog of requests, slowing it down. If you allow too many they
+       will use RAM and other system resources noticably.
+       The maximum this may be safely set to is 32.
+       
+       The startup= and idle= options allow some measure of skew in your
+       tuning.
+       
+               startup=
+       
+       Sets a minimum of how many processes are to be spawned when Squid
+       starts or reconfigures. When set to zero the first request will
+       cause spawning of the first child process to handle it.
+       
+       Starting too few will cause an initial slowdown in traffic as Squid
+       attempts to simultaneously spawn enough processes to cope.
+       
+               idle=
+       
+       Sets a minimum of how many processes Squid is to try and keep available
+       at all times. When traffic begins to rise above what the existing
+       processes can handle this many more will be spawned up to the maximum
+       configured. A minimum setting of 1 is required.
 DOC_END
 
 NAME: dns_retransmit_interval
@@ -6154,7 +6224,6 @@ IFDEF: !USE_DNSSERVERS
 DOC_START
        Initial retransmit interval for DNS queries. The interval is
        doubled each time all configured DNS servers have been tried.
-
 DOC_END
 
 NAME: dns_timeout
index dd29635324e9321fc0b0bff373a5b1b676380b39..085eeb1f7d03b89d7713ec2ec8c7b6b306b7cd3b 100644 (file)
@@ -73,9 +73,9 @@ dnsInit(void)
         return;
 
     if (dnsservers == NULL)
-        dnsservers = helperCreate("dnsserver");
+        dnsservers = new helper("dnsserver");
 
-    dnsservers->n_to_start = Config.dnsChildren;
+    dnsservers->childs = Config.dnsChildren;
 
     dnsservers->ipc_type = IPC_STREAM;
 
@@ -107,8 +107,7 @@ dnsShutdown(void)
     if (!shutting_down)
         return;
 
-    helperFree(dnsservers);
-
+    delete dnsservers;
     dnsservers = NULL;
 }
 
@@ -119,7 +118,11 @@ dnsSubmit(const char *lookup, HLPCB * callback, void *data)
     static time_t first_warn = 0;
     snprintf(buf, 256, "%s\n", lookup);
 
-    if (dnsservers->stats.queue_size >= dnsservers->n_running * 2) {
+    if (dnsservers->stats.queue_size >= dnsservers->childs.n_active && dnsservers->childs.needNew() > 0) {
+        helperOpenServers(dnsservers);
+    }
+
+    if (dnsservers->stats.queue_size >= dnsservers->childs.n_running * 2) {
         if (first_warn == 0)
             first_warn = squid_curtime;
 
index 90ff036841da45e62bf74a551191eb24aec06d76..2addc11b6e48bc616b921b233e2f1373a4af7d76 100644 (file)
@@ -107,9 +107,7 @@ public:
 
     wordlist *cmdline;
 
-    int children;
-
-    int concurrency;
+    HelperChildConfig children;
 
     helper *theHelper;
 
@@ -210,7 +208,7 @@ free_external_acl(void *data)
 
     if (p->theHelper) {
         helperShutdown(p->theHelper);
-        helperFree(p->theHelper);
+        delete p->theHelper;
         p->theHelper = NULL;
     }
 
@@ -295,11 +293,12 @@ parse_externalAclHelper(external_acl ** list)
     /* set defaults */
     a->ttl = DEFAULT_EXTERNAL_ACL_TTL;
     a->negative_ttl = -1;
-    a->children = DEFAULT_EXTERNAL_ACL_CHILDREN;
+    a->children.n_max = DEFAULT_EXTERNAL_ACL_CHILDREN;
+    a->children.n_startup = a->children.n_max;
+    a->children.n_idle = 99999999; // big to detect if the user sets their own.
     a->local_addr.SetLocalhost();
     a->quote = external_acl::QUOTE_METHOD_URL;
 
-
     token = strtok(NULL, w_space);
 
     if (!token)
@@ -316,9 +315,16 @@ parse_externalAclHelper(external_acl ** list)
         } else if (strncmp(token, "negative_ttl=", 13) == 0) {
             a->negative_ttl = atoi(token + 13);
         } else if (strncmp(token, "children=", 9) == 0) {
-            a->children = atoi(token + 9);
+            a->children.n_max = atoi(token + 9);
+            debugs(0, 0, "WARNING: external_acl_type option children=N has been deprecated in favor of children-max=N and children-startup=N");
+        } else if (strncmp(token, "children-max=", 13) == 0) {
+            a->children.n_max = atoi(token + 13);
+        } else if (strncmp(token, "children-startup=", 17) == 0) {
+            a->children.n_startup = atoi(token + 17);
+        } else if (strncmp(token, "children-idle=", 14) == 0) {
+            a->children.n_idle = atoi(token + 14);
         } else if (strncmp(token, "concurrency=", 12) == 0) {
-            a->concurrency = atoi(token + 12);
+            a->children.concurrency = atoi(token + 12);
         } else if (strncmp(token, "cache=", 6) == 0) {
             a->cache_size = atoi(token + 6);
         } else if (strncmp(token, "grace=", 6) == 0) {
@@ -351,6 +357,11 @@ parse_externalAclHelper(external_acl ** list)
         token = strtok(NULL, w_space);
     }
 
+    /* our default idle is huge on purpose, make it sane when we know whether the user has set their own. */
+    if (a->children.n_idle > a->children.n_max - a->children.n_startup)
+        a->children.n_idle = max(1, (int)(a->children.n_max - a->children.n_startup));
+
+
     if (a->negative_ttl == -1)
         a->negative_ttl = a->ttl;
 
@@ -483,11 +494,17 @@ dump_externalAclHelper(StoreEntry * sentry, const char *name, const external_acl
         if (node->grace)
             storeAppendPrintf(sentry, " grace=%d", node->grace);
 
-        if (node->children != DEFAULT_EXTERNAL_ACL_CHILDREN)
-            storeAppendPrintf(sentry, " children=%d", node->children);
+        if (node->children.n_max != DEFAULT_EXTERNAL_ACL_CHILDREN)
+            storeAppendPrintf(sentry, " children-max=%d", node->children.n_max);
 
-        if (node->concurrency)
-            storeAppendPrintf(sentry, " concurrency=%d", node->concurrency);
+        if (node->children.n_startup != 1)
+            storeAppendPrintf(sentry, " children-startup=%d", node->children.n_startup);
+
+        if (node->children.n_idle != (node->children.n_max + node->children.n_startup) )
+            storeAppendPrintf(sentry, " children-idle=%d", node->children.n_idle);
+
+        if (node->children.concurrency)
+            storeAppendPrintf(sentry, " concurrency=%d", node->children.concurrency);
 
         if (node->cache)
             storeAppendPrintf(sentry, " cache=%d", node->cache_size);
@@ -744,7 +761,7 @@ aclMatchExternal(external_acl_data *acl, ACLFilledChecklist *ch)
             debugs(82, 2, "aclMatchExternal: \"" << key << "\": entry=@" <<
                    entry << ", age=" << (entry ? (long int) squid_curtime - entry->date : 0));
 
-            if (acl->def->theHelper->stats.queue_size <= acl->def->theHelper->n_running) {
+            if (acl->def->theHelper->stats.queue_size <= (int)acl->def->theHelper->childs.n_active) {
                 debugs(82, 2, "aclMatchExternal: \"" << key << "\": queueing a call.");
                 ch->changeState (ExternalACLLookup::Instance());
 
@@ -1331,7 +1348,7 @@ ACLExternal::ExternalAclLookup(ACLChecklist *checklist, ACLExternal * me, EAH *
     } else {
         /* Check for queue overload */
 
-        if (def->theHelper->stats.queue_size >= def->theHelper->n_running) {
+        if (def->theHelper->stats.queue_size >= (int)def->theHelper->childs.n_running) {
             debugs(82, 1, "externalAclLookup: '" << def->name << "' queue overload (ch=" << ch << ")");
             cbdataFree(state);
             callback(callback_data, entry);
@@ -1407,13 +1424,11 @@ externalAclInit(void)
             p->cache = hash_create((HASHCMP *) strcmp, hashPrime(1024), hash4);
 
         if (!p->theHelper)
-            p->theHelper = helperCreate(p->name);
+            p->theHelper = new helper(p->name);
 
         p->theHelper->cmdline = p->cmdline;
 
-        p->theHelper->n_to_start = p->children;
-
-        p->theHelper->concurrency = p->concurrency;
+        p->theHelper->childs = p->children;
 
         p->theHelper->ipc_type = IPC_TCP_SOCKET;
 
index 96be90fac9dedeb3245e43b7fff411f56d7d3d47..38a38de7f3207a54b0b9749855c6a61211bb7617 100644 (file)
@@ -118,6 +118,7 @@ extern "C" {
 //MOVED:snmp_core.cc    extern IpAddress theOutSNMPAddr;
 
     extern struct timeval squid_start;
+    extern int starting_up;    /* 1 */
     extern int shutting_down;  /* 0 */
     extern int reconfiguring;  /* 0 */
     extern unsigned long store_swap_size;      /* 0 */
index cda398af78841ea6b2e4771fe31039d5cddcbb5a..a327b653f5137aae4396d2ef89e774cb50e2d48b 100644 (file)
@@ -68,9 +68,9 @@ static void StatefulEnqueue(statefulhelper * hlp, helper_stateful_request * r);
 static bool helperStartStats(StoreEntry *sentry, void *hlp, const char *label);
 
 
-CBDATA_TYPE(helper);
+CBDATA_CLASS_INIT(helper);
 CBDATA_TYPE(helper_server);
-CBDATA_TYPE(statefulhelper);
+CBDATA_CLASS_INIT(statefulhelper);
 CBDATA_TYPE(helper_stateful_server);
 
 void
@@ -101,10 +101,10 @@ helperOpenServers(helper * hlp)
     else
         shortname = xstrdup(progname);
 
-    /* dont ever start more than hlp->n_to_start processes. */
-    int need_new = hlp->n_to_start - hlp->n_active;
+    /* figure out how many new child are actually needed. */
+    int need_new = hlp->childs.needNew();
 
-    debugs(84, 1, "helperOpenServers: Starting " << need_new << "/" << hlp->n_to_start << " '" << shortname << "' processes");
+    debugs(84, 1, "helperOpenServers: Starting " << need_new << "/" << hlp->childs.n_max << " '" << shortname << "' processes");
 
     if (need_new < 1) {
         debugs(84, 1, "helperOpenServers: No '" << shortname << "' processes needed.");
@@ -140,8 +140,8 @@ helperOpenServers(helper * hlp)
             continue;
         }
 
-        hlp->n_running++;
-        hlp->n_active++;
+        hlp->childs.n_running++;
+        hlp->childs.n_active++;
         CBDATA_INIT_TYPE(helper_server);
         srv = cbdataAlloc(helper_server);
         srv->hIpc = hIpc;
@@ -153,7 +153,7 @@ helperOpenServers(helper * hlp)
         srv->rbuf = (char *)memAllocBuf(BUF_8KB, &srv->rbuf_sz);
         srv->wqueue = new MemBuf;
         srv->roffset = 0;
-        srv->requests = (helper_request **)xcalloc(hlp->concurrency ? hlp->concurrency : 1, sizeof(*srv->requests));
+        srv->requests = (helper_request **)xcalloc(hlp->childs.concurrency ? hlp->childs.concurrency : 1, sizeof(*srv->requests));
         srv->parent = cbdataReference(hlp);
         dlinkAddTail(srv, &srv->link, &hlp->servers);
 
@@ -207,11 +207,10 @@ helperStatefulOpenServers(statefulhelper * hlp)
     else
         shortname = xstrdup(progname);
 
-    /* dont ever start more than hlp->n_to_start processes. */
-    /* n_active are the helpers which have not been shut down. */
-    int need_new = hlp->n_to_start - hlp->n_active;
+    /* figure out haw mant new helpers are needed. */
+    int need_new = hlp->childs.needNew();
 
-    debugs(84, 1, "helperOpenServers: Starting " << need_new << "/" << hlp->n_to_start << " '" << shortname << "' processes");
+    debugs(84, 1, "helperOpenServers: Starting " << need_new << "/" << hlp->childs.n_max << " '" << shortname << "' processes");
 
     if (need_new < 1) {
         debugs(84, 1, "helperStatefulOpenServers: No '" << shortname << "' processes needed.");
@@ -249,8 +248,8 @@ helperStatefulOpenServers(statefulhelper * hlp)
             continue;
         }
 
-        hlp->n_running++;
-        hlp->n_active++;
+        hlp->childs.n_running++;
+        hlp->childs.n_active++;
         CBDATA_INIT_TYPE(helper_stateful_server);
         helper_stateful_server *srv = cbdataAlloc(helper_stateful_server);
         srv->hIpc = hIpc;
@@ -404,7 +403,7 @@ helperStats(StoreEntry * sentry, helper * hlp, const char *label)
     storeAppendPrintf(sentry, "program: %s\n",
                       hlp->cmdline->key);
     storeAppendPrintf(sentry, "number active: %d of %d (%d shutting down)\n",
-                      hlp->n_active, hlp->n_to_start, (hlp->n_running - hlp->n_active) );
+                      hlp->childs.n_active, hlp->childs.n_max, (hlp->childs.n_running - hlp->childs.n_active) );
     storeAppendPrintf(sentry, "requests sent: %d\n",
                       hlp->stats.requests);
     storeAppendPrintf(sentry, "replies received: %d\n",
@@ -457,7 +456,7 @@ helperStatefulStats(StoreEntry * sentry, statefulhelper * hlp, const char *label
     storeAppendPrintf(sentry, "program: %s\n",
                       hlp->cmdline->key);
     storeAppendPrintf(sentry, "number active: %d of %d (%d shutting down)\n",
-                      hlp->n_active, hlp->n_to_start, (hlp->n_running - hlp->n_active) );
+                      hlp->childs.n_active, hlp->childs.n_max, (hlp->childs.n_running - hlp->childs.n_active) );
     storeAppendPrintf(sentry, "requests sent: %d\n",
                       hlp->stats.requests);
     storeAppendPrintf(sentry, "replies received: %d\n",
@@ -524,8 +523,8 @@ helperShutdown(helper * hlp)
             continue;
         }
 
-        hlp->n_active--;
-        assert(hlp->n_active >= 0);
+        assert(hlp->childs.n_active > 0);
+        hlp->childs.n_active--;
         srv->flags.shutdown = 1;       /* request it to shut itself down */
 
         if (srv->flags.closing) {
@@ -592,8 +591,8 @@ helperStatefulShutdown(statefulhelper * hlp)
             continue;
         }
 
-        hlp->n_active--;
-        assert(hlp->n_active >= 0);
+        assert(hlp->childs.n_active > 0);
+        hlp->childs.n_active--;
         srv->flags.shutdown = 1;       /* request it to shut itself down */
 
         if (srv->flags.busy) {
@@ -648,57 +647,14 @@ helperStatefulShutdown(statefulhelper * hlp)
     }
 }
 
-
-helper *
-helperCreate(const char *name)
-{
-    helper *hlp;
-    CBDATA_INIT_TYPE(helper);
-    hlp = cbdataAlloc(helper);
-    hlp->id_name = name;
-    return hlp;
-}
-
-statefulhelper *
-helperStatefulCreate(const char *name)
-{
-    statefulhelper *hlp;
-    CBDATA_INIT_TYPE(statefulhelper);
-    hlp = cbdataAlloc(statefulhelper);
-    hlp->id_name = name;
-    return hlp;
-}
-
-
-void
-helperFree(helper * hlp)
+helper::~helper()
 {
-    if (!hlp)
-        return;
-
-    /* note, don't free hlp->name, it probably points to static memory */
-    if (hlp->queue.head)
-        debugs(84, 0, "WARNING: freeing " << hlp->id_name << " helper with " <<
-               hlp->stats.queue_size << " requests queued");
-
-    cbdataFree(hlp);
-}
-
-void
-helperStatefulFree(statefulhelper * hlp)
-{
-    if (!hlp)
-        return;
+    /* note, don't free id_name, it probably points to static memory */
 
-    /* note, don't free hlp->name, it probably points to static memory */
-    if (hlp->queue.head)
-        debugs(84, 0, "WARNING: freeing " << hlp->id_name << " helper with " <<
-               hlp->stats.queue_size << " requests queued");
-
-    cbdataFree(hlp);
+    if (queue.head)
+        debugs(84, 0, "WARNING: freeing " << id_name << " helper with " << stats.queue_size << " requests queued");
 }
 
-
 /* ====================================================================== */
 /* LOCAL FUNCTIONS */
 /* ====================================================================== */
@@ -709,7 +665,7 @@ helperServerFree(int fd, void *data)
     helper_server *srv = (helper_server *)data;
     helper *hlp = srv->parent;
     helper_request *r;
-    int i, concurrency = hlp->concurrency;
+    int i, concurrency = hlp->childs.concurrency;
 
     if (!concurrency)
         concurrency = 1;
@@ -748,24 +704,21 @@ helperServerFree(int fd, void *data)
 
     dlinkDelete(&srv->link, &hlp->servers);
 
-    hlp->n_running--;
-
-    assert(hlp->n_running >= 0);
+    assert(hlp->childs.n_running > 0);
+    hlp->childs.n_running--;
 
     if (!srv->flags.shutdown) {
-        hlp->n_active--;
-        assert(hlp->n_active >= 0);
-        debugs(84, 0, "WARNING: " << hlp->id_name << " #" << srv->index + 1 <<
-               " (FD " << fd << ") exited");
+        assert(hlp->childs.n_active > 0);
+        hlp->childs.n_active--;
+        debugs(84, DBG_CRITICAL, "WARNING: " << hlp->id_name << " #" << srv->index + 1 << " (FD " << fd << ") exited");
 
-        if (hlp->n_active < hlp->n_to_start / 2) {
-            debugs(80, 0, "Too few " << hlp->id_name << " processes are running");
+        if (hlp->childs.needNew() > 0) {
+            debugs(80, 1, "Too few " << hlp->id_name << " processes are running (need " << hlp->childs.needNew() << "/" << hlp->childs.n_max << ")");
 
-            if (hlp->last_restart > squid_curtime - 30)
+            if (hlp->childs.n_active < hlp->childs.n_startup && hlp->last_restart > squid_curtime - 30)
                 fatalf("The %s helpers are crashing too rapidly, need help!\n", hlp->id_name);
 
-            debugs(80, 0, "Starting new helpers");
-
+            debugs(80, 1, "Starting new helpers");
             helperOpenServers(hlp);
         }
     }
@@ -810,23 +763,21 @@ helperStatefulServerFree(int fd, void *data)
 
     dlinkDelete(&srv->link, &hlp->servers);
 
-    hlp->n_running--;
-
-    assert(hlp->n_running >= 0);
+    assert(hlp->childs.n_running > 0);
+    hlp->childs.n_running--;
 
     if (!srv->flags.shutdown) {
-        hlp->n_active--;
-        assert( hlp->n_active >= 0);
+        assert( hlp->childs.n_active > 0);
+        hlp->childs.n_active--;
         debugs(84, 0, "WARNING: " << hlp->id_name << " #" << srv->index + 1 << " (FD " << fd << ") exited");
 
-        if (hlp->n_active <= hlp->n_to_start / 2) {
-            debugs(80, 0, "Too few " << hlp->id_name << " processes are running");
+        if (hlp->childs.needNew() > 0) {
+            debugs(80, 1, "Too few " << hlp->id_name << " processes are running (need " << hlp->childs.needNew() << "/" << hlp->childs.n_max << ")");
 
-            if (hlp->last_restart > squid_curtime - 30)
+            if (hlp->childs.n_active < hlp->childs.n_startup && hlp->last_restart > squid_curtime - 30)
                 fatalf("The %s helpers are crashing too rapidly, need help!\n", hlp->id_name);
 
-            debugs(80, 0, "Starting new helpers");
-
+            debugs(80, 1, "Starting new helpers");
             helperStatefulOpenServers(hlp);
         }
     }
@@ -893,7 +844,7 @@ helperHandleRead(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, voi
 
         *t++ = '\0';
 
-        if (hlp->concurrency) {
+        if (hlp->childs.concurrency) {
             i = strtol(msg, &msg, 10);
 
             while (*msg && xisspace(*msg))
@@ -1040,7 +991,14 @@ Enqueue(helper * hlp, helper_request * r)
     dlinkAddTail(r, link, &hlp->queue);
     hlp->stats.queue_size++;
 
-    if (hlp->stats.queue_size < hlp->n_running)
+    /* do this first so idle=N has a chance to grow the child pool before it hits critical. */
+    if (hlp->childs.needNew() > 0) {
+        debugs(84, 0, "Starting new " << hlp->id_name << " helpers...");
+        helperOpenServers(hlp);
+        return;
+    }
+
+    if (hlp->stats.queue_size < (int)hlp->childs.n_running)
         return;
 
     if (squid_curtime - hlp->last_queue_warn < 600)
@@ -1051,15 +1009,12 @@ Enqueue(helper * hlp, helper_request * r)
 
     hlp->last_queue_warn = squid_curtime;
 
-    debugs(84, 0, "WARNING: All " << hlp->id_name << " processes are busy.");
+    debugs(84, 0, "WARNING: All " << hlp->childs.n_active << "/" << hlp->childs.n_max << " " << hlp->id_name << " processes are busy.");
     debugs(84, 0, "WARNING: " << hlp->stats.queue_size << " pending requests queued");
+    debugs(84, 0, "WARNING: Consider increasing the number of " << hlp->id_name << " processes in your config file.");
 
-
-    if (hlp->stats.queue_size > hlp->n_running * 2)
+    if (hlp->stats.queue_size > (int)hlp->childs.n_running * 2)
         fatalf("Too many queued %s requests", hlp->id_name);
-
-    debugs(84, 1, "Consider increasing the number of " << hlp->id_name << " processes in your config file.");
-
 }
 
 static void
@@ -1069,10 +1024,17 @@ StatefulEnqueue(statefulhelper * hlp, helper_stateful_request * r)
     dlinkAddTail(r, link, &hlp->queue);
     hlp->stats.queue_size++;
 
-    if (hlp->stats.queue_size < hlp->n_running)
+    /* do this first so idle=N has a chance to grow the child pool before it hits critical. */
+    if (hlp->childs.needNew() > 0) {
+        debugs(84, 0, "Starting new " << hlp->id_name << " helpers...");
+        helperStatefulOpenServers(hlp);
+        return;
+    }
+
+    if (hlp->stats.queue_size < (int)hlp->childs.n_running)
         return;
 
-    if (hlp->stats.queue_size > hlp->n_running * 2)
+    if (hlp->stats.queue_size > (int)hlp->childs.n_running * 2)
         fatalf("Too many queued %s requests", hlp->id_name);
 
     if (squid_curtime - hlp->last_queue_warn < 600)
@@ -1083,11 +1045,9 @@ StatefulEnqueue(statefulhelper * hlp, helper_stateful_request * r)
 
     hlp->last_queue_warn = squid_curtime;
 
-    debugs(84, 0, "WARNING: All " << hlp->id_name << " processes are busy.");
-
+    debugs(84, 0, "WARNING: All " << hlp->childs.n_active << "/" << hlp->childs.n_max << " " << hlp->id_name << " processes are busy.");
     debugs(84, 0, "WARNING: " << hlp->stats.queue_size << " pending requests queued");
-    debugs(84, 1, "Consider increasing the number of " << hlp->id_name << " processes in your config file.");
-
+    debugs(84, 0, "WARNING: Consider increasing the number of " << hlp->id_name << " processes in your config file.");
 }
 
 static helper_request *
@@ -1129,7 +1089,7 @@ GetFirstAvailable(helper * hlp)
     helper_server *srv;
     helper_server *selected = NULL;
 
-    if (hlp->n_running == 0)
+    if (hlp->childs.n_running == 0)
         return NULL;
 
     /* Find "least" loaded helper (approx) */
@@ -1157,7 +1117,7 @@ GetFirstAvailable(helper * hlp)
     if (!selected)
         return NULL;
 
-    if (selected->stats.pending >= (hlp->concurrency ? hlp->concurrency : 1))
+    if (selected->stats.pending >= (hlp->childs.concurrency ? hlp->childs.concurrency : 1))
         return NULL;
 
     return selected;
@@ -1168,9 +1128,9 @@ StatefulGetFirstAvailable(statefulhelper * hlp)
 {
     dlink_node *n;
     helper_stateful_server *srv = NULL;
-    debugs(84, 5, "StatefulGetFirstAvailable: Running servers " << hlp->n_running);
+    debugs(84, 5, "StatefulGetFirstAvailable: Running servers " << hlp->childs.n_running);
 
-    if (hlp->n_running == 0)
+    if (hlp->childs.n_running == 0)
         return NULL;
 
     for (n = hlp->servers.head; n != NULL; n = n->next) {
@@ -1238,7 +1198,7 @@ helperDispatch(helper_server * srv, helper_request * r)
         return;
     }
 
-    for (slot = 0; slot < (hlp->concurrency ? hlp->concurrency : 1); slot++) {
+    for (slot = 0; slot < (hlp->childs.concurrency ? hlp->childs.concurrency : 1); slot++) {
         if (!srv->requests[slot]) {
             ptr = &srv->requests[slot];
             break;
@@ -1253,7 +1213,7 @@ helperDispatch(helper_server * srv, helper_request * r)
     if (srv->wqueue->isNull())
         srv->wqueue->init();
 
-    if (hlp->concurrency)
+    if (hlp->childs.concurrency)
         srv->wqueue->Printf("%d %s", slot, r->buf);
     else
         srv->wqueue->append(r->buf, strlen(r->buf));
index f860b9305e430f2d46454dc94bbd51f86eb13810..6460c4d0996e5350effc0631ed93d85a27d24121 100644 (file)
 #include "squid.h"
 #include "cbdata.h"
 #include "ip/IpAddress.h"
+#include "HelperChildConfig.h"
 
 class helper_request;
 
-typedef struct _helper helper;
-
-typedef struct _helper_stateful statefulhelper;
-
-typedef struct _helper_server helper_server;
-
-typedef struct _helper_stateful_server helper_stateful_server;
-
 typedef struct _helper_flags helper_flags;
 
 typedef struct _helper_stateful_flags helper_stateful_flags;
 
 typedef void HLPSCB(void *, void *lastserver, char *buf);
 
-struct _helper {
+class helper {
+public:
+    inline helper(const char *name) : cmdline(NULL), id_name(name) {};
+    ~helper();
+
+public:
     wordlist *cmdline;
     dlink_list servers;
     dlink_list queue;
     const char *id_name;
-    int n_to_start;           ///< Configuration setting of how many helper children should be running
-    int n_running;            ///< Total helper children objects currently existing
-    int n_active;             ///< Count of helper children active (not shutting down)
+    HelperChildConfig childs;    ///< Configuration settings for number running.
     int ipc_type;
     IpAddress addr;
-    unsigned int concurrency;
     time_t last_queue_warn;
     time_t last_restart;
 
-    struct {
+    struct _stats {
         int requests;
         int replies;
         int queue_size;
         int avg_svc_time;
     } stats;
+
+private:
+    CBDATA_CLASS2(helper);
 };
 
-struct _helper_stateful {
-    wordlist *cmdline;
-    dlink_list servers;
-    dlink_list queue;
-    const char *id_name;
-    int n_to_start;           ///< Configuration setting of how many helper children should be running
-    int n_running;            ///< Total helper children objects currently existing
-    int n_active;             ///< Count of helper children active (not shutting down)
-    int ipc_type;
-    IpAddress addr;
+class statefulhelper : public helper {
+public:
+    inline statefulhelper(const char *name) : helper(name) {};
+    inline ~statefulhelper() {};
+
+public:
     MemAllocator *datapool;
     HLPSAVAIL *IsAvailable;
     HLPSONEQ *OnEmptyQueue;
-    time_t last_queue_warn;
-    time_t last_restart;
 
-    struct {
-        int requests;
-        int replies;
-        int queue_size;
-        int avg_svc_time;
-    } stats;
+private:
+    CBDATA_CLASS2(statefulhelper);
 };
 
-struct _helper_server {
+/*
+ * Fields shared between stateless and stateful helper servers.
+ */
+class HelperServerBase {
+public:
     int index;
     int pid;
     IpAddress addr;
     int rfd;
     int wfd;
-    MemBuf *wqueue;
-    MemBuf *writebuf;
+    void *hIpc;
+
     char *rbuf;
     size_t rbuf_sz;
     size_t roffset;
 
     struct timeval dispatch_time;
-
     struct timeval answer_time;
 
     dlink_node link;
+};
+
+class helper_server : public HelperServerBase {
+public:
+    MemBuf *wqueue;
+    MemBuf *writebuf;
+
     helper *parent;
     helper_request **requests;
 
@@ -129,29 +127,15 @@ struct _helper_server {
         int uses;
         unsigned int pending;
     } stats;
-
-    void *hIpc;
 };
 
 class helper_stateful_request;
 
-struct _helper_stateful_server {
-    int index;
-    int pid;
-    IpAddress addr;
-    int rfd;
-    int wfd;
+class helper_stateful_server : public HelperServerBase {
+public:
     /* MemBuf wqueue; */
     /* MemBuf writebuf; */
-    char *rbuf;
-    size_t rbuf_sz;
-    size_t roffset;
 
-    struct timeval dispatch_time;
-
-    struct timeval answer_time;
-
-    dlink_node link;
     statefulhelper *parent;
     helper_stateful_request *request;
 
@@ -168,7 +152,6 @@ struct _helper_stateful_server {
         int releases;
     } stats;
     void *data;                        /* State data used by the calling routines */
-    void *hIpc;
 };
 
 class helper_request
@@ -207,13 +190,8 @@ SQUIDCEXTERN void helperStats(StoreEntry * sentry, helper * hlp, const char *lab
 SQUIDCEXTERN void helperStatefulStats(StoreEntry * sentry, statefulhelper * hlp, const char *label = NULL);
 SQUIDCEXTERN void helperShutdown(helper * hlp);
 SQUIDCEXTERN void helperStatefulShutdown(statefulhelper * hlp);
-SQUIDCEXTERN helper *helperCreate(const char *);
-SQUIDCEXTERN statefulhelper *helperStatefulCreate(const char *);
-SQUIDCEXTERN void helperFree(helper *);
-SQUIDCEXTERN void helperStatefulFree(statefulhelper *);
 SQUIDCEXTERN void helperStatefulReleaseServer(helper_stateful_server * srv);
 SQUIDCEXTERN void *helperStatefulServerGetData(helper_stateful_server * srv);
 
 
-
 #endif /* SQUID_HELPER_H */
index 7974864038c34cab6f60a66676dd13e94e83969d..b637923da684b3253ed022910b54b882c3b69d1d 100644 (file)
@@ -55,7 +55,8 @@ nodist_pinger_SOURCES = \
        $(top_builddir)/src/globals.cc \
        $(top_srcdir)/src/time.cc \
        $(top_srcdir)/src/SquidConfig.cc \
-       $(top_srcdir)/src/SquidNew.cc
+       $(top_srcdir)/src/SquidNew.cc \
+       $(top_srcdir)/src/tests/stub_HelperChildConfig.cc
 
 pinger_LDFLAGS = $(LIBADD_DL)
 pinger_LDADD=\
index 5ef34a034cbd6b9276975460798da0a6330dcac0..d9af2f3b88d697354cc552b4088e2e4bf2ce7a04 100644 (file)
@@ -1370,6 +1370,9 @@ SquidMain(int argc, char **argv)
 
     mainLoop.setTimeService(&time_engine);
 
+    /* at this point we are finished the synchronous startup. */
+    starting_up = 0;
+
     mainLoop.run();
 
     if (mainLoop.errcount == 10)
index 04bbe8a08a2140a5549899953e6be5f0276bd4fe..028f83e5adfa37c94fe4e0cd6c2d984b6efa9f32 100644 (file)
@@ -194,13 +194,11 @@ redirectInit(void)
         return;
 
     if (redirectors == NULL)
-        redirectors = helperCreate("redirector");
+        redirectors = new helper("redirector");
 
     redirectors->cmdline = Config.Program.redirect;
 
-    redirectors->n_to_start = Config.redirectChildren;
-
-    redirectors->concurrency = Config.redirectConcurrency;
+    redirectors->childs = Config.redirectChildren;
 
     redirectors->ipc_type = IPC_STREAM;
 
@@ -223,7 +221,6 @@ redirectShutdown(void)
     if (!shutting_down)
         return;
 
-    helperFree(redirectors);
-
+    delete redirectors;
     redirectors = NULL;
 }
index 02cf57ab4feee997a85edd717bac71f0db625681..d9dafb6903bb14105bd87a3c707a0e2b3750ae73 100644 (file)
@@ -128,6 +128,8 @@ struct relist {
 #include "ip/QosConfig.h"
 #endif
 
+#include "HelperChildConfig.h"
+
 /* forward decl for SquidConfig, see RemovalPolicy.h */
 
 class RemovalPolicySettings;
@@ -301,11 +303,10 @@ struct SquidConfig {
     } Program;
 #if USE_DNSSERVERS
 
-    int dnsChildren;
+    HelperChildConfig dnsChildren;
 #endif
 
-    int redirectChildren;
-    int redirectConcurrency;
+    HelperChildConfig redirectChildren;
     time_t authenticateGCInterval;
     time_t authenticateTTL;
     time_t authenticateIpTTL;
diff --git a/src/tests/stub_HelperChildConfig.cc b/src/tests/stub_HelperChildConfig.cc
new file mode 100644 (file)
index 0000000..151035d
--- /dev/null
@@ -0,0 +1,52 @@
+#include "config.h"
+#include "HelperChildConfig.h"
+#include "globals.h"
+
+#include <string.h>
+
+HelperChildConfig::HelperChildConfig() :
+        n_max(0),
+        n_startup(1),
+        n_idle(1),
+        concurrency(1),
+        n_running(0),
+        n_active(0)
+{}
+
+HelperChildConfig::HelperChildConfig(const unsigned int m, const unsigned int s, const unsigned int i, const unsigned int cc) :
+        n_max(m),
+        n_startup(s),
+        n_idle(i),
+        concurrency(cc),
+        n_running(0),
+        n_active(0)
+{}
+
+HelperChildConfig::~HelperChildConfig()
+{}
+
+HelperChildConfig &
+HelperChildConfig::operator =(const HelperChildConfig &rhs)
+{
+    memcpy(this, &rhs, sizeof(HelperChildConfig));
+    return *this;
+}
+
+const int
+HelperChildConfig::needNew() const {
+    /* during the startup and reconfigure use our special amount... */
+    if (starting_up || reconfiguring) return n_startup;
+
+    /* keep a minimum of n_idle helpers free... */
+    if ( (n_active + n_idle) < n_max) return n_idle;
+
+    /* dont ever start more than n_max processes. */
+    return (n_max - n_active);
+}
+
+void
+HelperChildConfig::parseConfig()
+{
+    fprintf(stderr, "HelperChildConfig::parseConfig not implemented.");
+    exit(1);
+}
index b5d14bbcd979f9c733085f0daf17a2d74ab82484..b526262bb32aee050238e783a25e1ea0408148ca 100644 (file)
@@ -47,29 +47,12 @@ helperStatefulSubmit(statefulhelper * hlp, const char *buf, HLPSCB * callback, v
     fatal("Not implemented");
 }
 
-void
-helperStatefulFree(statefulhelper * hlp)
-{
-    fatal("Not implemented");
-}
-
-void
-helperFree(helper * hlp)
+helper::~helper()
 {
     fatal("Not implemented");
 }
 
-CBDATA_TYPE(helper);
-
-helper *
-helperCreate(const char *name)
-{
-    helper *hlp;
-    CBDATA_INIT_TYPE(helper);
-    hlp = cbdataAlloc(helper);
-    hlp->id_name = name;
-    return hlp;
-}
+CBDATA_CLASS_INIT(helper);
 
 void
 helperStats(StoreEntry * sentry, helper * hlp, const char *label)
@@ -127,17 +110,7 @@ helperStatefulReleaseServer(helper_stateful_server * srv)
     fatal("Not implemented");
 }
 
-CBDATA_TYPE(statefulhelper);
-
-statefulhelper *
-helperStatefulCreate(const char *name)
-{
-    statefulhelper *hlp;
-    CBDATA_INIT_TYPE(statefulhelper);
-    hlp = cbdataAlloc(statefulhelper);
-    hlp->id_name = name;
-    return hlp;
-}
+CBDATA_CLASS_INIT(statefulhelper);
 
 /*
  * DO NOT MODIFY:
index f43dd772922b5bfb25de7f3fd0a9a791f07e242e..2e94e7d8289df2a2f7f2b23003c2a0cf4380b5b8 100644 (file)
@@ -31,7 +31,7 @@
  *
  */
 
-#include "squid.h"
+#include "config.h"
 
 int
 percent(int a, int b)
@@ -43,5 +43,6 @@ percent(int a, int b)
 void
 death(int sig)
 {
-    fatal ("Not implemented");
+    fprintf(stderr, "Not implemented");
+    exit(1);
 }