]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Added RunnersRegistry, an API to register and, later, run a group of actions.
authorAlex Rousskov <rousskov@measurement-factory.com>
Fri, 9 Sep 2011 16:16:43 +0000 (10:16 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Fri, 9 Sep 2011 16:16:43 +0000 (10:16 -0600)
Useful for keeping general initialization/cleanup management code (e.g.,
main.cc) independent from specific initialization/cleanup code (e.g.,
Store file systems or memory cache) during staged initialization and
cleaning.

Designed with Rock Store needs in mind. Currently unused. Should eventually be
used for most modules initialization and cleanup, removing main.cc dependency
on those modules and perfecting [de]initialization order.

src/base/Makefile.am
src/base/RunnersRegistry.cc [new file with mode: 0644]
src/base/RunnersRegistry.h [new file with mode: 0644]
src/main.cc

index 408d20984bf2807d1057a67cec83990fcb9727dc..cd38376cebb3ce50effa1cedaa11bce6d560ff69 100644 (file)
@@ -15,6 +15,8 @@ libbase_la_SOURCES = \
        TidyPointer.h \
        CbcPointer.h \
        InstanceId.h \
+       RunnersRegistry.cc \
+       RunnersRegistry.h \
        Subscription.h \
        TextException.cc \
        TextException.h
diff --git a/src/base/RunnersRegistry.cc b/src/base/RunnersRegistry.cc
new file mode 100644 (file)
index 0000000..87ac733
--- /dev/null
@@ -0,0 +1,58 @@
+#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 &registryId)
+{
+    if (!TheRegistries)
+        TheRegistries = new Registries;
+
+    if (TheRegistries->find(registryId) == TheRegistries->end())
+        (*TheRegistries)[registryId] = new Runners;
+
+    return *(*TheRegistries)[registryId];
+}
+
+int
+RegisterRunner(const RunnerRegistry &registryId, RegisteredRunner *rr)
+{
+    Runners &runners = GetRunners(registryId);
+    runners.push_back(rr);
+    return runners.size();
+}
+
+int
+ActivateRegistered(const RunnerRegistry &registryId)
+{
+    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 &registryId)
+{
+    Runners &runners = GetRunners(registryId);
+    typedef Runners::iterator RRI;
+    while (!runners.empty()) {
+        delete runners.back();
+        runners.pop_back();
+    }
+}
+
+bool
+UseThisStatic(const void *)
+{
+    return true;
+}
diff --git a/src/base/RunnersRegistry.h b/src/base/RunnersRegistry.h
new file mode 100644 (file)
index 0000000..06e68e6
--- /dev/null
@@ -0,0 +1,61 @@
+#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 &registry, RegisteredRunner *rr);
+
+/// calls run() methods of all runners in the given registry
+int ActivateRegistered(const RunnerRegistry &registry);
+/// deletes all runners in the given registry
+void DeactivateRegistered(const RunnerRegistry &registry);
+
+
+/// 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 */
index f56501bcdb2bc88abc376b7d894d37cd448c53a1..13e1efe0abb3f7e16b9e7cdb8a9f613df5f082c8 100644 (file)
@@ -47,6 +47,7 @@
 #if USE_AUTH
 #include "auth/Gadgets.h"
 #endif
+#include "base/RunnersRegistry.h"
 #include "base/Subscription.h"
 #include "base/TextException.h"
 #if USE_DELAY_POOLS
@@ -1427,6 +1428,11 @@ SquidMain(int argc, char **argv)
         /* 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);
 
@@ -1785,6 +1791,10 @@ watch_child(char *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);
@@ -1884,6 +1894,7 @@ SquidShutdown()
     Store::Root().sync();              /* Flush log close */
     StoreFileSystem::FreeAllFs();
     DiskIOModule::FreeAllModules();
+    DeactivateRegistered(rrAfterConfig);
 #if LEAK_CHECK_MODE && 0 /* doesn't work at the moment */
 
     configFreeMemory();