/* Basic Scheme */
static AUTHSSTATS authenticateBasicStats;
-helper *basicauthenticators = nullptr;
+Helper::ClientPointer basicauthenticators;
static int authbasic_initialised = 0;
helperShutdown(basicauthenticators);
}
- delete basicauthenticators;
basicauthenticators = nullptr;
if (authenticateProgram)
authbasic_initialised = 1;
if (basicauthenticators == nullptr)
- basicauthenticators = new helper("basicauthenticator");
+ basicauthenticators = helper::Make("basicauthenticator");
basicauthenticators->cmdline = authenticateProgram;
} // namespace Basic
} // namespace Auth
-extern helper *basicauthenticators;
+extern Helper::ClientPointer basicauthenticators;
#endif /* HAVE_AUTH_MODULE_BASIC */
#endif /* __AUTH_BASIC_H__ */
static AUTHSSTATS authenticateDigestStats;
-helper *digestauthenticators = nullptr;
+Helper::ClientPointer digestauthenticators;
static hash_table *digest_nonce_cache;
authdigest_initialised = 1;
if (digestauthenticators == nullptr)
- digestauthenticators = new helper("digestauthenticator");
+ digestauthenticators = helper::Make("digestauthenticator");
digestauthenticators->cmdline = authenticateProgram;
if (!shutting_down)
return;
- delete digestauthenticators;
digestauthenticators = nullptr;
if (authenticateProgram)
/* strings */
#define QOP_AUTH "auth"
-extern helper *digestauthenticators;
+extern Helper::ClientPointer digestauthenticators;
#endif /* HAVE_AUTH_MODULE_DIGEST */
#endif
static AUTHSSTATS authenticateNegotiateStats;
-statefulhelper *negotiateauthenticators = nullptr;
+Helper::StatefulClientPointer negotiateauthenticators;
static int authnegotiate_initialised = 0;
if (!shutting_down)
return;
- delete negotiateauthenticators;
negotiateauthenticators = nullptr;
if (authenticateProgram)
authnegotiate_initialised = 1;
if (negotiateauthenticators == nullptr)
- negotiateauthenticators = new statefulhelper("negotiateauthenticator");
+ negotiateauthenticators = statefulhelper::Make("negotiateauthenticator");
if (!proxy_auth_cache)
proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
} // namespace Negotiate
} // namespace Auth
-extern statefulhelper *negotiateauthenticators;
+extern Helper::StatefulClientPointer negotiateauthenticators;
#endif /* HAVE_AUTH_MODULE_NEGOTIATE */
#endif
/* NTLM Scheme */
static AUTHSSTATS authenticateNTLMStats;
-statefulhelper *ntlmauthenticators = nullptr;
+Helper::StatefulClientPointer ntlmauthenticators;
static int authntlm_initialised = 0;
static hash_table *proxy_auth_cache = nullptr;
if (!shutting_down)
return;
- delete ntlmauthenticators;
ntlmauthenticators = nullptr;
if (authenticateProgram)
authntlm_initialised = 1;
if (ntlmauthenticators == nullptr)
- ntlmauthenticators = new statefulhelper("ntlmauthenticator");
+ ntlmauthenticators = statefulhelper::Make("ntlmauthenticator");
if (!proxy_auth_cache)
proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
} // namespace Ntlm
} // namespace Auth
-extern statefulhelper *ntlmauthenticators;
+extern Helper::StatefulClientPointer ntlmauthenticators;
#endif /* HAVE_AUTH_MODULE_NTLM */
#endif
Helper::ChildConfig children;
- helper *theHelper;
+ helper::Pointer theHelper;
hash_table *cache;
if (theHelper) {
helperShutdown(theHelper);
- delete theHelper;
theHelper = nullptr;
}
p->cache = hash_create((HASHCMP *) strcmp, hashPrime(1024), hash4);
if (!p->theHelper)
- p->theHelper = new helper("external_acl_type");
+ p->theHelper = helper::Make("external_acl_type");
p->theHelper->cmdline = p->cmdline;
static IOCB helperHandleRead;
static IOCB helperStatefulHandleRead;
static void Enqueue(helper * hlp, Helper::Xaction *);
-static helper_server *GetFirstAvailable(const helper * hlp);
-static helper_stateful_server *StatefulGetFirstAvailable(statefulhelper * hlp);
+static helper_server *GetFirstAvailable(const helper::Pointer &);
+static helper_stateful_server *StatefulGetFirstAvailable(const statefulhelper::Pointer &);
static void helperDispatch(helper_server * srv, Helper::Xaction * r);
static void helperStatefulDispatch(helper_stateful_server * srv, Helper::Xaction * r);
-static void helperKickQueue(helper * hlp);
-static void helperStatefulKickQueue(statefulhelper * hlp);
+static void helperKickQueue(const helper::Pointer &);
+static void helperStatefulKickQueue(const statefulhelper::Pointer &);
static void helperStatefulServerDone(helper_stateful_server * srv);
static void StatefulEnqueue(statefulhelper * hlp, Helper::Xaction * r);
-CBDATA_CLASS_INIT(helper);
CBDATA_CLASS_INIT(helper_server);
-CBDATA_CLASS_INIT(statefulhelper);
CBDATA_CLASS_INIT(helper_stateful_server);
InstanceIdDefinitions(HelperServerBase, "Hlpr");
-- parent->childs.n_running;
assert(requests.empty());
- cbdataReferenceDone(parent);
}
void
-- parent->childs.n_running;
assert(requests.empty());
-
- cbdataReferenceDone(parent);
}
void
-helperOpenServers(helper * hlp)
+helperOpenServers(const helper::Pointer &hlp)
{
char *s;
char *progname;
srv->nextRequestId = 0;
srv->replyXaction = nullptr;
srv->ignoreToEom = false;
- srv->parent = cbdataReference(hlp);
+ srv->parent = hlp;
dlinkAddTail(srv, &srv->link, &hlp->servers);
if (rfd == wfd) {
* helperStatefulOpenServers: create the stateful child helper processes
*/
void
-helperStatefulOpenServers(statefulhelper * hlp)
+helperStatefulOpenServers(const statefulhelper::Pointer &hlp)
{
char *shortname;
const char *args[HELPER_MAX_ARGS+1]; // save space for a NULL terminator
srv->writePipe->fd = wfd;
srv->rbuf = (char *)memAllocBuf(ReadBufSize, &srv->rbuf_sz);
srv->roffset = 0;
- srv->parent = cbdataReference(hlp);
+ srv->parent = hlp;
srv->reservationStart = 0;
dlinkAddTail(srv, &srv->link, &hlp->servers);
/// handles helperSubmit() and helperStatefulSubmit() failures
static void
-SubmissionFailure(helper *hlp, HLPCB *callback, void *data)
+SubmissionFailure(const helper::Pointer &hlp, HLPCB *callback, void *data)
{
auto result = Helper::Error;
if (!hlp) {
}
void
-helperSubmit(helper * hlp, const char *buf, HLPCB * callback, void *data)
+helperSubmit(const helper::Pointer &hlp, const char *buf, HLPCB * callback, void *data)
{
if (!hlp || !hlp->trySubmit(buf, callback, data))
SubmissionFailure(hlp, callback, data);
/// Submit request or callback the caller with a Helper::Error error.
/// If the reservation is not set then reserves a new helper.
void
-helperStatefulSubmit(statefulhelper * hlp, const char *buf, HLPCB * callback, void *data, const Helper::ReservationId & reservation)
+helperStatefulSubmit(const statefulhelper::Pointer &hlp, const char *buf, HLPCB * callback, void *data, const Helper::ReservationId & reservation)
{
if (!hlp || !hlp->trySubmit(buf, callback, data, reservation))
SubmissionFailure(hlp, callback, data);
return queueFull() && !(childs.needNew() || GetFirstAvailable(this));
}
+helper::Pointer
+helper::Make(const char *name)
+{
+ return new helper(name);
+}
+
+statefulhelper::Pointer
+statefulhelper::Make(const char *name)
+{
+ return new statefulhelper(name);
+}
+
void
-helperShutdown(helper * hlp)
+helperShutdown(const helper::Pointer &hlp)
{
dlink_node *link = hlp->servers.head;
}
void
-helperStatefulShutdown(statefulhelper * hlp)
+helperStatefulShutdown(const statefulhelper::Pointer &hlp)
{
dlink_node *link = hlp->servers.head;
helper_stateful_server *srv;
void
helper_server::HelperServerClosed(helper_server *srv)
{
- helper *hlp = srv->getParent();
+ const auto hlp = srv->parent;
bool needsNewServers = false;
hlp->handleKilledServer(srv, needsNewServers);
}
// XXX: Almost duplicates helper_server::HelperServerClosed() because helperOpenServers() is not a virtual method of the `helper` class
-// TODO: Fix the `helper` class hierarchy to use CbdataParent and virtual functions.
+// TODO: Fix the `helper` class hierarchy to use virtual functions.
void
helper_stateful_server::HelperServerClosed(helper_stateful_server *srv)
{
- statefulhelper *hlp = static_cast<statefulhelper *>(srv->getParent());
+ const auto hlp = srv->parent;
bool needsNewServers = false;
hlp->handleKilledServer(srv, needsNewServers);
/// Calls back with a pointer to the buffer with the helper output
static void
-helperReturnBuffer(helper_server * srv, helper * hlp, char * msg, size_t msgSize, char * msgEnd)
+helperReturnBuffer(helper_server * srv, const helper::Pointer &hlp, char * msg, size_t msgSize, char * msgEnd)
{
if (Helper::Xaction *r = srv->replyXaction) {
const bool hasSpace = r->reply.accumulate(msg, msgSize);
helperHandleRead(const Comm::ConnectionPointer &conn, char *, size_t len, Comm::Flag flag, int, void *data)
{
helper_server *srv = (helper_server *)data;
- helper *hlp = srv->parent;
+ const auto hlp = srv->parent;
assert(cbdataReferenceValid(data));
/* Bail out early on Comm::ERR_CLOSING - close handlers will tidy up for us */
{
char *t = nullptr;
helper_stateful_server *srv = (helper_stateful_server *)data;
- statefulhelper *hlp = srv->parent;
+ const auto hlp = srv->parent;
assert(cbdataReferenceValid(data));
/* Bail out early on Comm::ERR_CLOSING - close handlers will tidy up for us */
}
static helper_server *
-GetFirstAvailable(const helper * hlp)
+GetFirstAvailable(const helper::Pointer &hlp)
{
dlink_node *n;
helper_server *srv;
}
static helper_stateful_server *
-StatefulGetFirstAvailable(statefulhelper * hlp)
+StatefulGetFirstAvailable(const statefulhelper::Pointer &hlp)
{
dlink_node *n;
helper_stateful_server *srv = nullptr;
static void
helperDispatch(helper_server * srv, Helper::Xaction * r)
{
- helper *hlp = srv->parent;
+ const auto hlp = srv->parent;
const uint64_t reqId = ++srv->nextRequestId;
if (!cbdataReferenceValid(r->request.data)) {
static void
helperStatefulDispatch(helper_stateful_server * srv, Helper::Xaction * r)
{
- statefulhelper *hlp = srv->parent;
+ const auto hlp = srv->parent;
if (!cbdataReferenceValid(r->request.data)) {
debugs(84, DBG_IMPORTANT, "ERROR: helperStatefulDispatch: invalid callback data");
srv->requests.push_back(r);
srv->dispatch_time = current_time;
AsyncCall::Pointer call = commCbCall(5,5, "helperStatefulDispatchWriteDone",
- CommIoCbPtrFun(helperStatefulDispatchWriteDone, hlp));
+ CommIoCbPtrFun(helperStatefulDispatchWriteDone, srv));
Comm::Write(srv->writePipe, r->request.buf, strlen(r->request.buf), call, nullptr);
debugs(84, 5, "helperStatefulDispatch: Request sent to " <<
hlp->id_name << " #" << srv->index << ", " <<
}
static void
-helperKickQueue(helper * hlp)
+helperKickQueue(const helper::Pointer &hlp)
{
Helper::Xaction *r;
helper_server *srv;
}
static void
-helperStatefulKickQueue(statefulhelper * hlp)
+helperStatefulKickQueue(const statefulhelper::Pointer &hlp)
{
Helper::Xaction *r;
helper_stateful_server *srv;
#include "base/AsyncCall.h"
#include "base/InstanceId.h"
+#include "base/RefCount.h"
#include "cbdata.h"
#include "comm/forward.h"
#include "dlink.h"
* If an overloaded helper has been overloaded for 3+ minutes, an attempt to use
* it results in on-persistent-overload action, which may kill worker.
*/
-class helper
+class helper: public RefCountable
{
- CBDATA_CLASS(helper);
-
public:
+ using Pointer = RefCount<helper>;
+
+ /// \returns a newly created instance of the named helper
/// \param name admin-visible helper category (with this process lifetime)
- inline helper(const char *name) :
- cmdline(nullptr),
- id_name(name),
- ipc_type(0),
- droppedRequests(0),
- overloadStart(0),
- last_queue_warn(0),
- last_restart(0),
- timeout(0),
- retryTimedOut(false),
- retryBrokenHelper(false),
- eom('\n') {
- memset(&stats, 0, sizeof(stats));
- }
+ static Pointer Make(const char *name);
+
~helper();
/// \returns next request in the queue, or nil.
void handleFewerServers(bool madeProgress);
public:
- wordlist *cmdline;
+ wordlist *cmdline = nullptr;
dlink_list servers;
std::queue<Helper::Xaction *> queue;
- const char *id_name;
+ const char *id_name = nullptr;
Helper::ChildConfig childs; ///< Configuration settings for number running.
- int ipc_type;
+ int ipc_type = 0;
Ip::Address addr;
- unsigned int droppedRequests; ///< requests not sent during helper overload
- time_t overloadStart; ///< when the helper became overloaded (zero if it is not)
- time_t last_queue_warn;
- time_t last_restart;
- time_t timeout; ///< Requests timeout
- bool retryTimedOut; ///< Whether the timed-out requests must retried
- bool retryBrokenHelper; ///< Whether the requests must retried on BH replies
+ unsigned int droppedRequests = 0; ///< requests not sent during helper overload
+ time_t overloadStart = 0; ///< when the helper became overloaded (zero if it is not)
+ time_t last_queue_warn = 0;
+ time_t last_restart = 0;
+ time_t timeout = 0; ///< Requests timeout
+ bool retryTimedOut = false; ///< Whether the timed-out requests must retried
+ bool retryBrokenHelper = false; ///< Whether the requests must retried on BH replies
SBuf onTimedOutResponse; ///< The response to use when helper response timedout
- char eom; ///< The char which marks the end of (response) message, normally '\n'
+ char eom = '\n'; ///< The char which marks the end of (response) message, normally '\n'
struct _stats {
- int requests;
- int replies;
- int timedout;
- int queue_size;
- int avg_svc_time;
+ int requests = 0;
+ int replies = 0;
+ int timedout = 0;
+ int queue_size = 0;
+ int avg_svc_time = 0;
} stats;
protected:
- friend void helperSubmit(helper * hlp, const char *buf, HLPCB * callback, void *data);
+ friend void helperSubmit(const helper::Pointer &, const char *buf, HLPCB * callback, void *data);
+
+ /// \param name admin-visible helper category (with this process lifetime)
+ explicit helper(const char *name): id_name(name) {}
+
bool queueFull() const;
bool overloaded() const;
void syncQueueStats();
class statefulhelper : public helper
{
- CBDATA_CLASS(statefulhelper);
-
public:
+ using Pointer = RefCount<statefulhelper>;
typedef std::unordered_map<Helper::ReservationId, helper_stateful_server *> Reservations;
- inline statefulhelper(const char *name) : helper(name) {}
inline ~statefulhelper() {}
public:
+ static Pointer Make(const char *name);
+
/// reserve the given server
void reserveServer(helper_stateful_server * srv);
void cancelReservation(const Helper::ReservationId reservation);
private:
- friend void helperStatefulSubmit(statefulhelper * hlp, const char *buf, HLPCB * callback, void *data, const Helper::ReservationId & reservation);
+ friend void helperStatefulSubmit(const statefulhelper::Pointer &, const char *buf, HLPCB *, void *cbData, const Helper::ReservationId &);
+
+ explicit statefulhelper(const char *name): helper(name) {}
/// \return the previously reserved server (if the reservation is still valid) or nil
helper_stateful_server *findServer(const Helper::ReservationId & reservation);
/// dequeues and sends a Helper::Unknown answer to all queued requests
virtual void dropQueued();
- /// the helper object that created this server
- virtual helper *getParent() const = 0;
-
public:
/// Helper program identifier; does not change when contents do,
/// including during assignment
MemBuf *wqueue;
MemBuf *writebuf;
- helper *parent;
+ helper::Pointer parent;
/// The helper request Xaction object for the current reply .
/// A helper reply may be distributed to more than one of the retrieved
/*HelperServerBase API*/
bool reserved() override {return false;}
void dropQueued() override;
- helper *getParent() const override {return parent;}
/// Read timeout handler
static void requestTimeout(const CommTimeoutCbParams &io);
/* HelperServerBase API */
bool reserved() override {return reservationId.reserved();}
- helper *getParent() const override {return parent;}
/// close handler to handle exited server processes
static void HelperServerClosed(helper_stateful_server *srv);
- statefulhelper *parent;
+ statefulhelper::Pointer parent;
// Reservations temporary lock the server for an exclusive "client" use. The
// client keeps the reservation ID as a proof of her reservation. If a
time_t reservationStart; ///< when the last `reservation` was made
};
-/* helper.c */
-void helperOpenServers(helper * hlp);
-void helperStatefulOpenServers(statefulhelper * hlp);
-void helperSubmit(helper * hlp, const char *buf, HLPCB * callback, void *data);
-void helperStatefulSubmit(statefulhelper * hlp, const char *buf, HLPCB * callback, void *data, uint64_t reservation);
-void helperShutdown(helper * hlp);
-void helperStatefulShutdown(statefulhelper * hlp);
+void helperOpenServers(const helper::Pointer &);
+void helperStatefulOpenServers(const statefulhelper::Pointer &);
+void helperSubmit(const helper::Pointer &, const char *buf, HLPCB *, void *cbData);
+void helperStatefulSubmit(const statefulhelper::Pointer &, const char *buf, HLPCB *, void *cbData, uint64_t reservation);
+void helperShutdown(const helper::Pointer &);
+void helperStatefulShutdown(const statefulhelper::Pointer &);
#endif /* SQUID_HELPER_H */
#ifndef SQUID_SRC_HELPER_FORWARD_H
#define SQUID_SRC_HELPER_FORWARD_H
+#include "base/forward.h"
+
class helper;
class statefulhelper;
class Reply;
class Request;
+using ClientPointer = RefCount<helper>;
+using StatefulClientPointer = RefCount<statefulhelper>;
+
} // namespace Helper
typedef void HLPCB(void *, const Helper::Reply &);
static HLPCB redirectHandleReply;
static HLPCB storeIdHandleReply;
-static helper *redirectors = nullptr;
-static helper *storeIds = nullptr;
+static helper::Pointer redirectors;
+static helper::Pointer storeIds;
static OBJH redirectStats;
static OBJH storeIdStats;
static int redirectorBypassed = 0;
}
static void
-constructHelperQuery(const char *name, helper *hlp, HLPCB *replyHandler, ClientHttpRequest * http, HLPCB *handler, void *data, Format::Format *requestExtrasFmt)
+constructHelperQuery(const char *name, const helper::Pointer &hlp, HLPCB *replyHandler, ClientHttpRequest * http, HLPCB *handler, void *data, Format::Format *requestExtrasFmt)
{
char buf[MAX_REDIRECTOR_REQUEST_STRLEN];
int sz;
if (Config.Program.redirect) {
if (redirectors == nullptr)
- redirectors = new helper("redirector");
+ redirectors = helper::Make("redirector");
redirectors->cmdline = Config.Program.redirect;
if (Config.Program.store_id) {
if (storeIds == nullptr)
- storeIds = new helper("store_id");
+ storeIds = helper::Make("store_id");
storeIds->cmdline = Config.Program.store_id;
if (!shutting_down)
return;
- delete redirectors;
redirectors = nullptr;
- delete storeIds;
storeIds = nullptr;
delete redirectorExtrasFmt;
/// pending Ssl::Helper requests (to all certificate generator helpers combined)
static Ssl::GeneratorRequests TheGeneratorRequests;
-helper *Ssl::Helper::ssl_crtd = nullptr;
+helper::Pointer Ssl::Helper::ssl_crtd = nullptr;
void Ssl::Helper::Init()
{
if (!found)
return;
- ssl_crtd = new helper("sslcrtd_program");
+ ssl_crtd = helper::Make("sslcrtd_program");
ssl_crtd->childs.updateLimits(Ssl::TheConfig.ssl_crtdChildren);
ssl_crtd->ipc_type = IPC_STREAM;
// The crtd messages may contain the eol ('\n') character. We are
return;
helperShutdown(ssl_crtd);
wordlistDestroy(&ssl_crtd->cmdline);
- delete ssl_crtd;
ssl_crtd = nullptr;
}
}
#endif //USE_SSL_CRTD
-helper *Ssl::CertValidationHelper::ssl_crt_validator = nullptr;
+helper::Pointer Ssl::CertValidationHelper::ssl_crt_validator = nullptr;
void Ssl::CertValidationHelper::Init()
{
if (!found)
return;
- ssl_crt_validator = new helper("ssl_crt_validator");
+ ssl_crt_validator = helper::Make("ssl_crt_validator");
ssl_crt_validator->childs.updateLimits(Ssl::TheConfig.ssl_crt_validator_Children);
ssl_crt_validator->ipc_type = IPC_STREAM;
// The crtd messages may contain the eol ('\n') character. We are
return;
helperShutdown(ssl_crt_validator);
wordlistDestroy(&ssl_crt_validator->cmdline);
- delete ssl_crt_validator;
ssl_crt_validator = nullptr;
// CertValidationHelper::HelperCache is a static member, it is not good policy to
/// Submit crtd message to external crtd server.
static void Submit(CrtdMessage const & message, HLPCB * callback, void *data);
private:
- static helper * ssl_crtd; ///< helper for management of ssl_crtd.
+ static ::Helper::ClientPointer ssl_crtd; ///< helper for management of ssl_crtd.
};
#endif
/// Submit crtd request message to external crtd server.
static void Submit(const Ssl::CertValidationRequest &, const Callback &);
private:
- static helper * ssl_crt_validator; ///< helper for management of ssl_crtd.
+ static ::Helper::ClientPointer ssl_crt_validator; ///< helper for management of ssl_crtd.
public:
typedef ClpMap<SBuf, CertValidationResponse::Pointer, CertValidationResponse::MemoryUsedByResponse> CacheType;
static CacheType *HelperCache; ///< cache for cert validation helper
#define STUB_API "helper.cc"
#include "tests/STUB.h"
-void helperSubmit(helper *, const char *, HLPCB *, void *) STUB
-void helperStatefulSubmit(statefulhelper *, const char *, HLPCB *, void *, uint64_t) STUB
+void helperSubmit(const helper::Pointer &, const char *, HLPCB *, void *) STUB
+void helperStatefulSubmit(const statefulhelper::Pointer &, const char *, HLPCB *, void *, const Helper::ReservationId &) STUB
helper::~helper() STUB
-CBDATA_CLASS_INIT(helper);
void helper::packStatsInto(Packable *, const char *) const STUB
-void helperShutdown(helper *) STUB
-void helperStatefulShutdown(statefulhelper *) STUB
-void helperOpenServers(helper *) STUB
-void helperStatefulOpenServers(statefulhelper *) STUB
-CBDATA_CLASS_INIT(statefulhelper);
+void helperShutdown(const helper::Pointer &) STUB
+void helperStatefulShutdown(const statefulhelper::Pointer &) STUB
+void helperOpenServers(const helper::Pointer &) STUB
+void helperStatefulOpenServers(const statefulhelper::Pointer &) STUB