--- /dev/null
+#include "config.h"
+#include "base/RunnersRegistry.h"
+#include <list>
+#include <map>
+
+typedef std::list<RegisteredRunner*> Runners;
+typedef std::map<RunnerRegistry, Runners*> Registries;
+
+/// all known registries
+static Registries *TheRegistries = NULL;
+
+/// returns the requested runners list, initializing structures as needed
+static Runners &
+GetRunners(const RunnerRegistry ®istryId)
+{
+ if (!TheRegistries)
+ TheRegistries = new Registries;
+
+ if (TheRegistries->find(registryId) == TheRegistries->end())
+ (*TheRegistries)[registryId] = new Runners;
+
+ return *(*TheRegistries)[registryId];
+}
+
+int
+RegisterRunner(const RunnerRegistry ®istryId, RegisteredRunner *rr)
+{
+ Runners &runners = GetRunners(registryId);
+ runners.push_back(rr);
+ return runners.size();
+}
+
+int
+ActivateRegistered(const RunnerRegistry ®istryId)
+{
+ Runners &runners = GetRunners(registryId);
+ typedef Runners::iterator RRI;
+ for (RRI i = runners.begin(); i != runners.end(); ++i)
+ (*i)->run(registryId);
+ return runners.size();
+}
+
+void
+DeactivateRegistered(const RunnerRegistry ®istryId)
+{
+ Runners &runners = GetRunners(registryId);
+ typedef Runners::iterator RRI;
+ while (!runners.empty()) {
+ delete runners.back();
+ runners.pop_back();
+ }
+}
+
+bool
+UseThisStatic(const void *)
+{
+ return true;
+}
--- /dev/null
+#ifndef SQUID_BASE_RUNNERSREGISTRY_H
+#define SQUID_BASE_RUNNERSREGISTRY_H
+
+/**
+ * This API allows virtually any module to register with a well-known registry,
+ * be activated by some central processor at some registry-specific time, and
+ * be deactiveated by some central processor at some registry-specific time.
+ *
+ * For example, main.cc may activate registered I/O modules after parsing
+ * squid.conf and deactivate them before exiting.
+ *
+ * A module in this context is code providing a functionality or service to the
+ * rest of Squid, such as src/DiskIO/Blocking, src/fs/ufs, or Cache Manager. A
+ * module must declare a RegisteredRunner child class to implement activation and
+ * deactivation logic using the run() method and destructor, respectively.
+ *
+ * This API allows the registry to determine the right [de]activation time for
+ * each group of similar modules, without knowing any module specifics.
+ *
+ */
+
+/// well-known registries
+typedef enum {
+ /// managed by main.cc; activated after parsing squid.conf and
+ /// deactivated before freeing configuration-related memory or exit()-ing
+ rrAfterConfig,
+
+ rrEnd ///< not a real registry, just a label to mark the end of enum
+} RunnerRegistry;
+
+/// a runnable registrant API
+class RegisteredRunner
+{
+public:
+ // called when this runner's registry is deactivated
+ virtual ~RegisteredRunner() {}
+
+ // called when this runner's registry is activated
+ virtual void run(const RunnerRegistry &r) = 0;
+};
+
+
+/// registers a given runner with the given registry and returns registry count
+int RegisterRunner(const RunnerRegistry ®istry, RegisteredRunner *rr);
+
+/// calls run() methods of all runners in the given registry
+int ActivateRegistered(const RunnerRegistry ®istry);
+/// deletes all runners in the given registry
+void DeactivateRegistered(const RunnerRegistry ®istry);
+
+
+/// convenience function to "use" an otherwise unreferenced static variable
+bool UseThisStatic(const void *);
+
+/// convenience macro: register one RegisteredRunner kid as early as possible
+#define RunnerRegistrationEntry(Registry, Who) \
+ static const bool Who ## _RegisteredWith_ ## Registry = \
+ RegisterRunner(Registry, new Who) > 0 && \
+ UseThisStatic(& Who ## _RegisteredWith_ ## Registry);
+
+#endif /* SQUID_BASE_RUNNERSREGISTRY_H */
#if USE_AUTH
#include "auth/Gadgets.h"
#endif
+#include "base/RunnersRegistry.h"
#include "base/Subscription.h"
#include "base/TextException.h"
#if USE_DELAY_POOLS
/* NOTREACHED */
}
+ debugs(1,2, HERE << "Doing post-config initialization\n");
+ leave_suid();
+ ActivateRegistered(rrAfterConfig);
+ enter_suid();
+
if (!opt_no_daemon && Config.workers > 0)
watch_child(argv);
#endif
if (!TheKids.someRunning() && !TheKids.shouldRestartSome()) {
+ leave_suid();
+ DeactivateRegistered(rrAfterConfig);
+ enter_suid();
+
if (TheKids.someSignaled(SIGINT) || TheKids.someSignaled(SIGTERM)) {
syslog(LOG_ALERT, "Exiting due to unexpected forced shutdown");
exit(1);
Store::Root().sync(); /* Flush log close */
StoreFileSystem::FreeAllFs();
DiskIOModule::FreeAllModules();
+ DeactivateRegistered(rrAfterConfig);
#if LEAK_CHECK_MODE && 0 /* doesn't work at the moment */
configFreeMemory();