<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
<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>
<tag>ftp_list_width</tag>
<p>Obsolete.
+ <tag>url_rewrite_concurrency</tag>
+ <p>Replaced by url_rewrite_children ... concurrency=N option.
+
</descrip>
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);
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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 */
gopher.cc \
helper.cc \
helper.h \
+ HelperChildConfig.h \
+ HelperChildConfig.cc \
hier_code.h \
HierarchyLogEntry.h \
$(HTCPSOURCE) \
## 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 \
ufsdump.cc \
dlink.h \
dlink.cc \
+ HelperChildConfig.h \
+ tests/stub_HelperChildConfig.cc \
HttpRequestMethod.cc \
RemovalPolicy.cc \
squid.h \
Packer.h \
Packer.cc \
tests/stub_cache_manager.cc \
+ tests/stub_HelperChildConfig.cc \
tests/stub_StatHist.cc \
tests/stub_store.cc \
SquidString.h \
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 \
ClientInfo.h \
ConfigParser.cc \
ETag.cc \
+ HelperChildConfig.h \
+ HelperChildConfig.cc \
HttpHeader.cc \
HttpHeaderTools.cc \
HttpHdrContRange.cc \
gopher.cc \
hier_code.h \
helper.cc \
+ HelperChildConfig.h \
+ HelperChildConfig.cc \
$(HTCPSOURCE) \
http.cc \
HttpBody.cc \
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 \
gopher.cc \
hier_code.h \
helper.cc \
+ HelperChildConfig.h \
+ HelperChildConfig.cc \
$(HTCPSOURCE) \
http.cc \
HttpBody.cc \
ftp.cc \
gopher.cc \
helper.cc \
+ HelperChildConfig.h \
+ HelperChildConfig.cc \
hier_code.h \
$(HTCPSOURCE) \
http.cc \
ftp.cc \
gopher.cc \
helper.cc \
+ HelperChildConfig.h \
+ HelperChildConfig.cc \
hier_code.h \
$(HTCPSOURCE) \
http.cc \
ftp.cc \
gopher.cc \
helper.cc \
+ HelperChildConfig.h \
+ HelperChildConfig.cc \
hier_code.h \
$(HTCPSOURCE) \
http.cc \
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)
tests/testString.cc \
tests/testString.h \
tests/stub_cache_manager.cc \
+ tests/stub_HelperChildConfig.cc \
time.cc
nodist_tests_testString_SOURCES = \
$(TESTSOURCES)
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) \
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 \
ftp.cc \
gopher.cc \
helper.cc \
+ HelperChildConfig.h \
+ HelperChildConfig.cc \
hier_code.h \
$(HTCPSOURCE) \
http.cc \
return protocolCacheObj;
case PROTO_INTERNAL:
return protocolInternal;
+ case PROTO_ICY:
+ return Name();
case PROTO_NONE:
return Name();
if (!shutting_down)
return;
- if (basicauthenticators)
- helperFree(basicauthenticators);
-
+ delete basicauthenticators;
basicauthenticators = NULL;
/* XXX Reinstate auth shutdown for dynamic schemes? */
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;
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");
}
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) {
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;
MEMPROXY_CLASS_INLINE(AuthBasicUserRequest);
+#include "HelperChildConfig.h"
+
/* configuration runtime data */
class AuthBasicConfig : public AuthConfig
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;
return;
}
- if (digestauthenticators) {
- helperFree(digestauthenticators);
- digestauthenticators = NULL;
- }
+ delete digestauthenticators;
+ digestauthenticators = NULL;
authDigestUserShutdown();
authenticateDigestNonceShutdown();
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);
AuthDigestConfig::configured() const
{
if ((authenticate != NULL) &&
- (authenticateChildren != 0) &&
+ (authenticateChildren.n_max != 0) &&
(digestAuthRealm != NULL) && (noncemaxduration > -1))
return true;
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;
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 */
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) {
} flags;
};
+#include "HelperChildConfig.h"
+
/* configuration runtime data */
class AuthDigestConfig : public AuthConfig
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;
if (!shutting_down)
return;
- if (negotiateauthenticators)
- helperStatefulFree(negotiateauthenticators);
-
+ delete negotiateauthenticators;
negotiateauthenticators = NULL;
debugs(29, 2, "negotiateScheme::done: Negotiate authentication Shutdown.");
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
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 {
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);
negotiateauthenticators->cmdline = authenticate;
- negotiateauthenticators->n_to_start = authenticateChildren;
+ negotiateauthenticators->childs = authenticateChildren;
negotiateauthenticators->ipc_type = IPC_STREAM;
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;
}
MEMPROXY_CLASS_INLINE(AuthNegotiateUserRequest);
+#include "HelperChildConfig.h"
+
/* configuration runtime data */
/// \ingroup AuthNegotiateAPI
virtual void parse(AuthConfig *, int, char *);
virtual void registerWithCacheManager(void);
virtual const char * type() const;
- int authenticateChildren;
+ HelperChildConfig authenticateChildren;
int keep_alive;
wordlist *authenticate;
};
if (!shutting_down)
return;
- if (ntlmauthenticators)
- helperStatefulFree(ntlmauthenticators);
-
+ delete ntlmauthenticators;
ntlmauthenticators = NULL;
debugs(29, 2, "ntlmScheme::done: NTLM authentication Shutdown.");
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
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 {
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);
ntlmauthenticators->cmdline = authenticate;
- ntlmauthenticators->n_to_start = authenticateChildren;
+ ntlmauthenticators->childs = authenticateChildren;
ntlmauthenticators->ipc_type = IPC_STREAM;
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;
}
MEMPROXY_CLASS_INLINE(AuthNTLMUserRequest);
+#include "HelperChildConfig.h"
+
/* configuration runtime data */
class AuthNTLMConfig : public AuthConfig
virtual void parse(AuthConfig *, int, char *);
virtual void registerWithCacheManager(void);
virtual const char * type() const;
- int authenticateChildren;
+ HelperChildConfig authenticateChildren;
int keep_alive;
wordlist *authenticate;
};
#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);
}
}
denyinfo acl
eol
externalAclHelper auth_param
+HelperChildConfig
hostdomain cache_peer
hostdomaintype cache_peer
http_header_access
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.
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
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
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
#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
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
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.
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
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
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;
if (!shutting_down)
return;
- helperFree(dnsservers);
-
+ delete dnsservers;
dnsservers = NULL;
}
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;
wordlist *cmdline;
- int children;
-
- int concurrency;
+ HelperChildConfig children;
helper *theHelper;
if (p->theHelper) {
helperShutdown(p->theHelper);
- helperFree(p->theHelper);
+ delete p->theHelper;
p->theHelper = NULL;
}
/* 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)
} 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) {
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;
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);
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());
} 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);
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;
//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 */
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
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.");
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;
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);
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.");
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;
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",
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",
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) {
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) {
}
}
-
-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 */
/* ====================================================================== */
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;
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);
}
}
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);
}
}
*t++ = '\0';
- if (hlp->concurrency) {
+ if (hlp->childs.concurrency) {
i = strtol(msg, &msg, 10);
while (*msg && xisspace(*msg))
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)
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
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)
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 *
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) */
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;
{
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) {
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;
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));
#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;
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;
int releases;
} stats;
void *data; /* State data used by the calling routines */
- void *hIpc;
};
class helper_request
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 */
$(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=\
mainLoop.setTimeService(&time_engine);
+ /* at this point we are finished the synchronous startup. */
+ starting_up = 0;
+
mainLoop.run();
if (mainLoop.errcount == 10)
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;
if (!shutting_down)
return;
- helperFree(redirectors);
-
+ delete redirectors;
redirectors = NULL;
}
#include "ip/QosConfig.h"
#endif
+#include "HelperChildConfig.h"
+
/* forward decl for SquidConfig, see RemovalPolicy.h */
class RemovalPolicySettings;
} Program;
#if USE_DNSSERVERS
- int dnsChildren;
+ HelperChildConfig dnsChildren;
#endif
- int redirectChildren;
- int redirectConcurrency;
+ HelperChildConfig redirectChildren;
time_t authenticateGCInterval;
time_t authenticateTTL;
time_t authenticateIpTTL;
--- /dev/null
+#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);
+}
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)
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:
*
*/
-#include "squid.h"
+#include "config.h"
int
percent(int a, int b)
void
death(int sig)
{
- fatal ("Not implemented");
+ fprintf(stderr, "Not implemented");
+ exit(1);
}