]> granicus.if.org Git - icinga2/commitdiff
Refactored Application class to use DynamicObject as a base class.
authorGunnar Beutner <gunnar.beutner@netways.de>
Tue, 14 Aug 2012 10:51:51 +0000 (12:51 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Tue, 14 Aug 2012 10:51:51 +0000 (12:51 +0200)
base/application.cpp
base/application.h
base/dynamicobject.cpp
base/dynamicobject.h
base/logger.cpp
base/streamlogger.cpp
base/streamlogger.h
icinga-app/icinga.cpp
icinga/icingaapplication.cpp
icinga/icingaapplication.h

index d5255fea674e623ff23311667cb53223a37b4edf..c17edeeb55607514565122cca95457236a5a8cdb 100644 (file)
  ******************************************************************************/
 
 #include "i2-base.h"
+
 #ifndef _WIN32
 #      include <ltdl.h>
 #endif /* _WIN32 */
 
 using namespace icinga;
 
-Application::Ptr Application::m_Instance;
+Application *Application::m_Instance = NULL;
 bool Application::m_ShuttingDown = false;
 bool Application::m_Debugging = false;
 boost::thread::id Application::m_MainThreadID;
@@ -32,9 +33,12 @@ boost::thread::id Application::m_MainThreadID;
 /**
  * Constructor for the Application class.
  */
-Application::Application(void)
-       : m_PidFile(NULL)
+Application::Application(const Dictionary::Ptr& serializedUpdate)
+       : DynamicObject(serializedUpdate), m_PidFile(NULL)
 {
+       if (!IsLocal())
+               throw_exception(runtime_error("Application objects must be local."));
+
 #ifdef _WIN32
        /* disable GUI-based error messages for LoadLibrary() */
        SetErrorMode(SEM_FAILCRITICALERRORS);
@@ -42,8 +46,6 @@ Application::Application(void)
        WSADATA wsaData;
        if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
                throw_exception(Win32Exception("WSAStartup failed", WSAGetLastError()));
-#else /* _WIN32 */
-       lt_dlinit();
 #endif /* _WIN32 */
 
        char *debugging = getenv("_DEBUG");
@@ -53,6 +55,9 @@ Application::Application(void)
        if (IsDebuggerPresent())
                m_Debugging = true;
 #endif /* _WIN32 */
+
+       assert(m_Instance == NULL);
+       m_Instance = this;
 }
 
 /**
@@ -60,6 +65,8 @@ Application::Application(void)
  */
 Application::~Application(void)
 {
+       m_Instance = NULL;
+
        m_ShuttingDown = true;
 
        DynamicObject::DeactivateObjects();
@@ -78,7 +85,10 @@ Application::~Application(void)
  */
 Application::Ptr Application::GetInstance(void)
 {
-       return m_Instance;
+       if (m_Instance)
+               return m_Instance->GetSelf();
+       else
+               return Application::Ptr();
 }
 
 /**
@@ -130,20 +140,14 @@ void Application::Shutdown(void)
 /**
  * Retrieves the full path of the executable.
  *
+ * @param argv0 The first command-line argument.
  * @returns The path.
  */
-String Application::GetExePath(void) const
+String Application::GetExePath(const String& argv0)
 {
-       static String result;
-
-       if (!result.IsEmpty())
-               return result;
-
        String executablePath;
 
 #ifndef _WIN32
-       String argv0 = m_Arguments[0];
-
        char buffer[MAXPATHLEN];
        if (getcwd(buffer, sizeof(buffer)) == NULL)
                throw_exception(PosixException("getcwd failed", errno));
@@ -189,17 +193,15 @@ String Application::GetExePath(void) const
        if (realpath(executablePath.CStr(), buffer) == NULL)
                throw_exception(PosixException("realpath failed", errno));
 
-       result = buffer;
+       return buffer;
 #else /* _WIN32 */
        char FullExePath[MAXPATHLEN];
 
        if (!GetModuleFileName(NULL, FullExePath, sizeof(FullExePath)))
                throw_exception(Win32Exception("GetModuleFileName() failed", GetLastError()));
 
-       result = FullExePath;
+       return FullExePath;
 #endif /* _WIN32 */
-
-       return result;
 }
 
 /**
@@ -217,6 +219,11 @@ bool Application::IsMainThread(void)
        return (boost::this_thread::get_id() == m_MainThreadID);
 }
 
+void Application::SetMainThread(void)
+{
+       m_MainThreadID = boost::this_thread::get_id();
+}
+
 #ifndef _WIN32
 /**
  * Signal handler for SIGINT. Prepares the application for cleanly
@@ -270,12 +277,6 @@ int Application::Run(int argc, char **argv)
 {
        int result;
 
-       assert(!Application::m_Instance);
-
-       m_MainThreadID = boost::this_thread::get_id();
-
-       Application::m_Instance = GetSelf();
-
 #ifndef _WIN32
        struct sigaction sa;
        memset(&sa, 0, sizeof(sa));
@@ -294,28 +295,24 @@ int Application::Run(int argc, char **argv)
 
        DynamicObject::BeginTx();
 
-       if (IsDebugging()) {
+       try {
                result = Main(m_Arguments);
 
-               Application::m_Instance.reset();
-       } else {
-               try {
-                       result = Main(m_Arguments);
+               DynamicObject::FinishTx();
+               DynamicObject::DeactivateObjects();
 
-                       Application::m_Instance.reset();
-               } catch (const exception& ex) {
-                       Application::m_Instance.reset();
+               assert(m_Instance == NULL);
+       } catch (const exception& ex) {
+               Logger::Write(LogCritical, "base", "---");
+               Logger::Write(LogCritical, "base", "Exception: " + Utility::GetTypeName(typeid(ex)));
+               Logger::Write(LogCritical, "base", "Message: " + String(ex.what()));
 
-                       Logger::Write(LogCritical, "base", "---");
-                       Logger::Write(LogCritical, "base", "Exception: " + Utility::GetTypeName(typeid(ex)));
-                       Logger::Write(LogCritical, "base", "Message: " + String(ex.what()));
+               if (IsDebugging())
+                       throw;
 
-                       return EXIT_FAILURE;
-               }
+               return EXIT_FAILURE;
        }
 
-       DynamicObject::FinishTx();
-
        return result;
 }
 
index 8288dde17ee8a154cacf9937354e8960f0710bfd..e91af95d81249d2096335e1372440adf1dd91d3f 100644 (file)
@@ -29,12 +29,12 @@ class Component;
  *
  * @ingroup base
  */
-class I2_BASE_API Application : public Object {
+class I2_BASE_API Application : public DynamicObject {
 public:
        typedef shared_ptr<Application> Ptr;
        typedef weak_ptr<Application> WeakPtr;
 
-       Application(void);
+       Application(const Dictionary::Ptr& serializedUpdate);
        ~Application(void);
 
        static Application::Ptr GetInstance(void);
@@ -48,16 +48,18 @@ public:
        static bool IsDebugging(void);
 
        static bool IsMainThread(void);
+       static void SetMainThread(void);
 
        void UpdatePidFile(const String& filename);
        void ClosePidFile(void);
 
+       static String GetExePath(const String& argv0);
+
 protected:
        void RunEventLoop(void);
-       String GetExePath(void) const;
 
 private:
-       static Application::Ptr m_Instance; /**< The application instance. */
+       static Application *m_Instance; /**< The application instance. */
 
        static bool m_ShuttingDown; /**< Whether the application is in the process of
                                  shutting down. */
index 13d82081d6bfb42dfd6290694833a87e92c8c192..b7faafccf4381b9c2705e3554f7eeca7bf3c0cf4 100644 (file)
@@ -473,6 +473,11 @@ DynamicObject::ClassMap& DynamicObject::GetClasses(void)
        return classes;
 }
 
+bool DynamicObject::ClassExists(const String& name)
+{
+       return (GetClasses().find(name) != GetClasses().end());
+}
+
 void DynamicObject::RegisterClass(const String& type, DynamicObject::Factory factory)
 {
        if (GetObjects(type).first != GetObjects(type).second)
index 025959b2f5e629aac83dea68a5882d5e32146208..c85a006ca8076d8c10920571805819cd65a06e18 100644 (file)
@@ -151,7 +151,8 @@ class RegisterClassHelper
 public:
        RegisterClassHelper(const String& name, DynamicObject::Factory factory)
        {
-               DynamicObject::RegisterClass(name, factory);
+               if (!DynamicObject::ClassExists(name))
+                       DynamicObject::RegisterClass(name, factory);
        }
 };
 
index 632442d6a2729af6571a798875b997aaad4a66fd..edd2a3d7cb4537b3a1792fb34f1d82accaf439a3 100644 (file)
@@ -110,13 +110,20 @@ LogSeverity Logger::GetMinSeverity(void) const
  */
 void Logger::ForwardLogEntry(const LogEntry& entry)
 {
+       bool processed = false;
+
        DynamicObject::Ptr object;
        BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Logger")) {
                Logger::Ptr logger = dynamic_pointer_cast<Logger>(object);
 
                if (entry.Severity >= logger->GetMinSeverity())
                        logger->m_Impl->ProcessLogEntry(entry);
+
+               processed = true;
        }
+
+       if (!processed && entry.Severity >= LogInformation)
+               StreamLogger::ProcessLogEntry(std::cout, entry);
 }
 
 String Logger::SeverityToString(LogSeverity severity)
index fe249b30da2b6057ffa49862e8e20d2ae49345d0..c35da60da4771120aa8c8a5b5fdfdfca0e575c4c 100644 (file)
@@ -49,9 +49,10 @@ void StreamLogger::OpenFile(const String& filename)
 /**
  * Processes a log entry and outputs it to a stream.
  *
+ * @param stream The output stream.
  * @param entry The log entry.
  */
-void StreamLogger::ProcessLogEntry(const LogEntry& entry)
+void StreamLogger::ProcessLogEntry(std::ostream& stream, const LogEntry& entry)
 {
        char timestamp[100];
 
@@ -60,7 +61,18 @@ void StreamLogger::ProcessLogEntry(const LogEntry& entry)
 
        strftime(timestamp, sizeof(timestamp), "%Y/%m/%d %H:%M:%S", &tmnow);
 
-       *m_Stream << "[" << timestamp << "] "
+       stream << "[" << timestamp << "] "
                 << Logger::SeverityToString(entry.Severity) << "/" << entry.Facility << ": "
                 << entry.Message << std::endl;
 }
+
+/**
+ * Processes a log entry and outputs it to a stream.
+ *
+ * @param entry The log entry.
+ */
+void StreamLogger::ProcessLogEntry(const LogEntry& entry)
+{
+       ProcessLogEntry(*m_Stream, entry);
+}
+
index 1d7c99cfb0128944d575949ad8f8d2050b8a43c3..c06a4777c3122bd2f940b70358ebe4030d3f00f5 100644 (file)
@@ -18,6 +18,9 @@ public:
        ~StreamLogger(void);
 
        void OpenFile(const String& filename);
+
+       static void ProcessLogEntry(std::ostream& stream, const LogEntry& entry);
+
 protected:
        virtual void ProcessLogEntry(const LogEntry& entry);
 
index ce482686c3a8dc8d9516a8133b3d393206e8a55e..41b9f8b5007ceda9f8b891be61eb248036d013ad 100644 (file)
@@ -20,6 +20,9 @@
 #include <i2-icinga.h>
 
 #ifndef _WIN32
+#      include "icinga-version.h"
+#      define ICINGA_VERSION GIT_MESSAGE
+
 #      include <ltdl.h>
 #endif /* _WIN32 */
 
@@ -38,6 +41,48 @@ int main(int argc, char **argv)
        LTDL_SET_PRELOADED_SYMBOLS();
 #endif /* _WIN32 */
 
-       IcingaApplication::Ptr instance = boost::make_shared<IcingaApplication>();
-       return instance->Run(argc, argv);
+#ifndef _WIN32
+       lt_dlinit();
+#endif /* _WIN32 */
+
+       Application::SetMainThread();
+
+#ifdef _WIN32
+       Logger::Write(LogInformation, "icinga", "Icinga application loader");    
+#else /* _WIN32 */
+       Logger::Write(LogInformation, "icinga", "Icinga application loader (version: " ICINGA_VERSION ")");
+#endif  /* _WIN32 */
+
+       if (argc < 3 || strcmp(argv[1], "-c") != 0) {
+               stringstream msgbuf;
+               msgbuf << "Syntax: " << argv[0] << " -c <config-file> ...";    
+               Logger::Write(LogInformation, "base", msgbuf.str());
+               return EXIT_FAILURE;
+       }
+
+       String configFile = argv[2];
+
+       String componentDirectory = Utility::DirName(Application::GetExePath(argv[0])) + "/../lib/icinga2";
+       Component::AddSearchDir(componentDirectory);
+
+       DynamicObject::BeginTx();
+
+       /* load config file */
+       vector<ConfigItem::Ptr> configItems = ConfigCompiler::CompileFile(configFile);
+
+       Logger::Write(LogInformation, "icinga", "Executing config items...");  
+
+       BOOST_FOREACH(const ConfigItem::Ptr& item, configItems) {
+               item->Commit();
+       }
+
+       DynamicObject::FinishTx();
+
+       Application::Ptr app = Application::GetInstance();
+
+       if (!app)
+               throw_exception(runtime_error("Configuration must create an Application object."));
+
+       return app->Run(argc - 2, &(argv[2]));
 }
+
index 937fd24737a264997b1d334f6fabae57092d11c5..330e28d36f9e23dabf85a8a0e9a1d4abe7cc8d76 100644 (file)
@@ -31,8 +31,25 @@ using namespace icinga;
 const String IcingaApplication::DefaultPidPath = "icinga.pid";
 const String IcingaApplication::DefaultStatePath = "icinga.state";
 
-IcingaApplication::IcingaApplication(void)
-{ }
+IcingaApplication::IcingaApplication(const Dictionary::Ptr& serializedUpdate)
+       : Application(serializedUpdate)
+{
+       /* load cibsync config component */
+       ConfigItemBuilder::Ptr cibsyncComponentConfig = boost::make_shared<ConfigItemBuilder>();
+       cibsyncComponentConfig->SetType("Component");
+       cibsyncComponentConfig->SetName("cibsync");
+       cibsyncComponentConfig->SetLocal(true);
+       cibsyncComponentConfig->Compile()->Commit();
+       cibsyncComponentConfig.reset();
+
+       /* load convenience config component */
+       ConfigItemBuilder::Ptr convenienceComponentConfig = boost::make_shared<ConfigItemBuilder>();
+       convenienceComponentConfig->SetType("Component");
+       convenienceComponentConfig->SetName("convenience");
+       convenienceComponentConfig->SetLocal(true);
+       convenienceComponentConfig->Compile()->Commit();
+       convenienceComponentConfig.reset();
+}
 
 /**
  * The entry point for the Icinga application.
@@ -42,26 +59,13 @@ IcingaApplication::IcingaApplication(void)
  */
 int IcingaApplication::Main(const vector<String>& args)
 {
-       /* create console logger */
-       ConfigItemBuilder::Ptr consoleLogConfig = boost::make_shared<ConfigItemBuilder>();
-       consoleLogConfig->SetType("Logger");
-       consoleLogConfig->SetName("console");
-       consoleLogConfig->SetLocal(true);
-       consoleLogConfig->AddExpression("type", OperatorSet, "console");
-       consoleLogConfig->Compile()->Commit();
-       consoleLogConfig.reset();
-
-#ifdef _WIN32
-       Logger::Write(LogInformation, "icinga", "Icinga component loader");
-#else /* _WIN32 */
-       Logger::Write(LogInformation, "icinga", "Icinga component loader (version: " ICINGA_VERSION ")");
-#endif  /* _WIN32 */
+       Logger::Write(LogInformation, "icinga", "In IcingaApplication::Main()");
 
        m_StartTime = Utility::GetTime();
 
-       if (args.size() < 2) {
+       if (args.size() == 1 && args[0] == "--help") {
                stringstream msgbuf;
-               msgbuf << "Syntax: " << args[0] << " [-S] [-L logfile] [-d] [--] <config-file>";
+               msgbuf << "Syntax: " << args[0] << " ... -d";
                Logger::Write(LogInformation, "icinga", msgbuf.str());
                return EXIT_FAILURE;
        }
@@ -92,68 +96,24 @@ int IcingaApplication::Main(const vector<String>& args)
                                throw_exception(invalid_argument("Unknown option: " + arg));
                        }
                }
-
-               configFile = arg;
-
-               if (it + 1 != args.end())
-                       throw_exception(invalid_argument("Trailing command line arguments after config filename."));
-       }
-
-       if (configFile.IsEmpty())
-               throw_exception(invalid_argument("No config file was specified on the command line."));
-
-       String componentDirectory = Utility::DirName(GetExePath()) + "/../lib/icinga2";
-       Component::AddSearchDir(componentDirectory);
-
-       /* load cibsync config component */
-       ConfigItemBuilder::Ptr cibsyncComponentConfig = boost::make_shared<ConfigItemBuilder>();
-       cibsyncComponentConfig->SetType("Component");
-       cibsyncComponentConfig->SetName("cibsync");
-       cibsyncComponentConfig->SetLocal(true);
-       cibsyncComponentConfig->Compile()->Commit();
-       cibsyncComponentConfig.reset();
-
-       /* load convenience config component */
-       ConfigItemBuilder::Ptr convenienceComponentConfig = boost::make_shared<ConfigItemBuilder>();
-       convenienceComponentConfig->SetType("Component");
-       convenienceComponentConfig->SetName("convenience");
-       convenienceComponentConfig->SetLocal(true);
-       convenienceComponentConfig->Compile()->Commit();
-       convenienceComponentConfig.reset();
-
-       /* load config file */
-       vector<ConfigItem::Ptr> configItems = ConfigCompiler::CompileFile(configFile);
-
-       Logger::Write(LogInformation, "icinga", "Executing config items...");
-
-       BOOST_FOREACH(const ConfigItem::Ptr& item, configItems) {
-               item->Commit();
        }
 
-       DynamicObject::Ptr icingaConfig = DynamicObject::GetObject("Application", "icinga");
-
-       if (!icingaConfig)
-               throw_exception(runtime_error("Configuration must contain an 'Application' object named 'icinga'."));
-
-       if (!icingaConfig->IsLocal())
-               throw_exception(runtime_error("'icinga' application object must be 'local'."));
-
-       m_CertificateFile = icingaConfig->Get("cert");
-       m_CAFile = icingaConfig->Get("ca");
-       m_Node = icingaConfig->Get("node");
-       m_Service = icingaConfig->Get("service");
+       m_CertificateFile = Get("cert");
+       m_CAFile = Get("ca");
+       m_Node = Get("node");
+       m_Service = Get("service");
 
-       m_PidPath = icingaConfig->Get("pidpath");
+       m_PidPath = Get("pidpath");
        if (m_PidPath.IsEmpty())
                m_PidPath = DefaultPidPath;
 
-       m_StatePath = icingaConfig->Get("statepath");
+       m_StatePath = Get("statepath");
        if (m_StatePath.IsEmpty())
                m_StatePath = DefaultStatePath;
 
-       m_Macros = icingaConfig->Get("macros");
+       m_Macros = Get("macros");
 
-       String logpath = icingaConfig->Get("logpath");
+       String logpath = Get("logpath");
        if (!logpath.IsEmpty()) {
                ConfigItemBuilder::Ptr fileLogConfig = boost::make_shared<ConfigItemBuilder>();
                fileLogConfig->SetType("Logger");
index 91947d9975b415ae87bab54241d27f3dfcd22f7b..2045e1a4c8ff26866a4e45f04729aa14fa3e2d8f 100644 (file)
@@ -34,7 +34,7 @@ public:
        typedef shared_ptr<IcingaApplication> Ptr;
        typedef weak_ptr<IcingaApplication> WeakPtr;
 
-       IcingaApplication(void);
+       IcingaApplication(const Dictionary::Ptr& serializedUpdate);
 
        int Main(const vector<String>& args);
 
@@ -69,6 +69,8 @@ private:
        void DumpProgramState(void);
 };
 
+REGISTER_CLASS(IcingaApplication);
+
 }
 
 #endif /* ICINGAAPPLICATION_H */