******************************************************************************/
#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;
/**
* 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);
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");
if (IsDebuggerPresent())
m_Debugging = true;
#endif /* _WIN32 */
+
+ assert(m_Instance == NULL);
+ m_Instance = this;
}
/**
*/
Application::~Application(void)
{
+ m_Instance = NULL;
+
m_ShuttingDown = true;
DynamicObject::DeactivateObjects();
*/
Application::Ptr Application::GetInstance(void)
{
- return m_Instance;
+ if (m_Instance)
+ return m_Instance->GetSelf();
+ else
+ return Application::Ptr();
}
/**
/**
* 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));
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;
}
/**
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
{
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));
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;
}
*
* @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);
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. */
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)
public:
RegisterClassHelper(const String& name, DynamicObject::Factory factory)
{
- DynamicObject::RegisterClass(name, factory);
+ if (!DynamicObject::ClassExists(name))
+ DynamicObject::RegisterClass(name, factory);
}
};
*/
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)
/**
* 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];
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);
+}
+
~StreamLogger(void);
void OpenFile(const String& filename);
+
+ static void ProcessLogEntry(std::ostream& stream, const LogEntry& entry);
+
protected:
virtual void ProcessLogEntry(const LogEntry& entry);
#include <i2-icinga.h>
#ifndef _WIN32
+# include "icinga-version.h"
+# define ICINGA_VERSION GIT_MESSAGE
+
# include <ltdl.h>
#endif /* _WIN32 */
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]));
}
+
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.
*/
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;
}
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");
typedef shared_ptr<IcingaApplication> Ptr;
typedef weak_ptr<IcingaApplication> WeakPtr;
- IcingaApplication(void);
+ IcingaApplication(const Dictionary::Ptr& serializedUpdate);
int Main(const vector<String>& args);
void DumpProgramState(void);
};
+REGISTER_CLASS(IcingaApplication);
+
}
#endif /* ICINGAAPPLICATION_H */