Clean up the start-up process a bit

fixes #8791
This commit is contained in:
Gunnar Beutner 2015-03-18 11:12:14 +01:00
parent fec1266b1b
commit 6c96d5bc98
23 changed files with 175 additions and 142 deletions

View File

@ -161,11 +161,17 @@ int Main(void)
#endif /* _WIN32 */
Application::DeclareZonesDir(Application::GetSysconfDir() + "/icinga2/zones.d");
Application::DeclareApplicationType("icinga/IcingaApplication");
Application::DeclareRunAsUser(ICINGA_USER);
Application::DeclareRunAsGroup(ICINGA_GROUP);
Application::DeclareConcurrency(boost::thread::hardware_concurrency());
if (!ScriptGlobal::Exists("UseVfork"))
#ifdef __APPLE__
ScriptGlobal::Set("UseVfork", false);
#else /* __APPLE__ */
ScriptGlobal::Set("UseVfork", true);
#endif /* __APPLE__ */
LogSeverity logLevel = Logger::GetConsoleLogSeverity();
Logger::SetConsoleLogSeverity(LogWarning);
@ -180,6 +186,7 @@ int Main(void)
("color", "use VT100 color codes even when stdout is not a terminal")
#endif /* _WIN32 */
("define,D", po::value<std::vector<std::string> >(), "define a constant")
("app,a", po::value<std::vector<std::string> >(), "application library name (default: icinga)")
("library,l", po::value<std::vector<std::string> >(), "load a library")
("include,I", po::value<std::vector<std::string> >(), "add include search directory")
("log-level,x", po::value<std::string>(), "specify the log level for the console log");
@ -465,6 +472,15 @@ int Main(void)
return EXIT_FAILURE;
}
Logger::SetConsoleLogSeverity(LogWarning);
if (vm.count("app"))
Utility::LoadExtensionLibrary(vm["app"].as<std::string>());
else
Utility::LoadExtensionLibrary("icinga");
Logger::SetConsoleLogSeverity(logLevel);
rc = command->Run(vm, args);
}

View File

@ -18,6 +18,6 @@
add_subdirectory(plugins-contrib.d)
install(
FILES itl command-icinga.conf hangman timeperiod.conf plugins command-plugins.conf manubulon command-plugins-manubulon.conf command-nscp-local.conf nscp plugins-contrib
FILES itl command.conf command-icinga.conf hangman timeperiod.conf plugins command-plugins.conf manubulon command-plugins-manubulon.conf command-nscp-local.conf nscp plugins-contrib
DESTINATION ${CMAKE_INSTALL_DATADIR}/icinga2/include
)

20
itl/command.conf Normal file
View File

@ -0,0 +1,20 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
library "methods"

View File

@ -22,7 +22,6 @@
* configuration templates.
*/
library "methods"
include "command.conf"
include "command-icinga.conf"
include "timeperiod.conf"

View File

@ -521,8 +521,7 @@ void Application::DisplayInfoMessage(std::ostream& os, bool skipVersion)
<< " State path: " << GetStatePath() << "\n"
<< " Objects path: " << GetObjectsPath() << "\n"
<< " Vars path: " << GetVarsPath() << "\n"
<< " PID path: " << GetPidPath() << "\n"
<< " Application type: " << GetApplicationType() << "\n";
<< " PID path: " << GetPidPath() << "\n";
#ifndef _WIN32
os << "\n"
@ -1231,27 +1230,6 @@ void Application::DeclarePidPath(const String& path)
ScriptGlobal::Set("PidPath", path);
}
/**
* Retrieves the name of the Application type.
*
* @returns The name.
*/
String Application::GetApplicationType(void)
{
return ScriptGlobal::Get("ApplicationType");
}
/**
* Sets the name of the Application type.
*
* @param path The new type name.
*/
void Application::DeclareApplicationType(const String& type)
{
if (!ScriptGlobal::Exists("ApplicationType"))
ScriptGlobal::Set("ApplicationType", type);
}
/**
* Retrieves the name of the user.
*

View File

@ -115,9 +115,6 @@ public:
static String GetPidPath(void);
static void DeclarePidPath(const String& path);
static String GetApplicationType(void);
static void DeclareApplicationType(const String& type);
static String GetRunAsUser(void);
static void DeclareRunAsUser(const String& user);

View File

@ -129,7 +129,7 @@ static char *ConsoleCompleteHelper(const char *word, int state)
Value value;
try {
Expression *expr = ConfigCompiler::CompileText("temp", pword);
Expression *expr = ConfigCompiler::CompileText("temp", pword, false);
if (expr)
value = expr->Evaluate(l_ScriptFrame);
@ -253,7 +253,7 @@ incomplete:
try {
lines[fileName] = command;
expr = ConfigCompiler::CompileText(fileName, command);
expr = ConfigCompiler::CompileText(fileName, command, false);
if (expr) {
Value result = expr->Evaluate(l_ScriptFrame);

View File

@ -43,23 +43,6 @@ static po::variables_map g_AppParams;
REGISTER_CLICOMMAND("daemon", DaemonCommand);
static String LoadAppType(const String& typeSpec)
{
Log(LogInformation, "cli")
<< "Loading application type: " << typeSpec;
String::SizeType index = typeSpec.FindFirstOf('/');
if (index == String::NPos)
return typeSpec;
String library = typeSpec.SubStr(0, index);
Utility::LoadExtensionLibrary(library);
return typeSpec.SubStr(index + 1);
}
#ifndef _WIN32
static void SigHupHandler(int)
{
@ -225,13 +208,6 @@ int DaemonCommand::Run(const po::variables_map& vm, const std::vector<std::strin
if (!vm.count("validate"))
Logger::DisableTimestamp(false);
if (!ScriptGlobal::Exists("UseVfork"))
#ifdef __APPLE__
ScriptGlobal::Set("UseVfork", false);
#else /* __APPLE__ */
ScriptGlobal::Set("UseVfork", true);
#endif /* __APPLE__ */
Log(LogInformation, "cli")
<< "Icinga application loader (version: " << Application::GetVersion()
#ifdef I2_DEBUG
@ -239,8 +215,6 @@ int DaemonCommand::Run(const po::variables_map& vm, const std::vector<std::strin
#endif /* I2_DEBUG */
<< ")";
String appType = LoadAppType(Application::GetApplicationType());
if (!vm.count("validate") && !vm.count("reload-internal")) {
pid_t runningpid = Application::ReadPidFile(Application::GetPidPath());
if (runningpid > 0) {
@ -256,7 +230,7 @@ int DaemonCommand::Run(const po::variables_map& vm, const std::vector<std::strin
else if (!vm.count("no-config"))
configs.push_back(Application::GetSysconfDir() + "/icinga2/icinga2.conf");
if (!DaemonUtility::LoadConfigFiles(configs, appType, Application::GetObjectsPath(), Application::GetVarsPath()))
if (!DaemonUtility::LoadConfigFiles(configs, Application::GetObjectsPath(), Application::GetVarsPath()))
return EXIT_FAILURE;
if (vm.count("validate")) {

View File

@ -99,30 +99,15 @@ bool DaemonUtility::ValidateConfigFiles(const std::vector<std::string>& configs,
if (!success)
return false;
String name, fragment;
BOOST_FOREACH(boost::tie(name, fragment), ConfigFragmentRegistry::GetInstance()->GetItems()) {
Expression *expression = ConfigCompiler::CompileText(name, fragment);
success = ExecuteExpression(expression);
delete expression;
if (!success)
return false;
}
return true;
}
bool DaemonUtility::LoadConfigFiles(const std::vector<std::string>& configs, const String& appType,
const String& objectsFile, const String& varsfile)
bool DaemonUtility::LoadConfigFiles(const std::vector<std::string>& configs,
const String& objectsFile, const String& varsfile)
{
if (!DaemonUtility::ValidateConfigFiles(configs, objectsFile))
return false;
ConfigItemBuilder::Ptr builder = new ConfigItemBuilder();
builder->SetType(appType);
builder->SetName("application");
ConfigItem::Ptr item = builder->Compile();
item->Register();
bool result = ConfigItem::CommitItems();
if (!result)

View File

@ -34,7 +34,7 @@ class I2_CLI_API DaemonUtility
{
public:
static bool ValidateConfigFiles(const std::vector<std::string>& configs, const String& objectsFile = String());
static bool LoadConfigFiles(const std::vector<std::string>& configs, const String& appType, const String& objectsFile = String(), const String& varsfile = String());
static bool LoadConfigFiles(const std::vector<std::string>& configs, const String& objectsFile = String(), const String& varsfile = String());
};
}

View File

@ -229,16 +229,6 @@ bool RepositoryUtility::AddObject(const std::vector<String>& object_paths, const
change->Set("attrs", attrs);
if (check_config) {
String fname, fragment;
BOOST_FOREACH(boost::tie(fname, fragment), ConfigFragmentRegistry::GetInstance()->GetItems()) {
Expression *expression = ConfigCompiler::CompileText(fname, fragment);
if (expression) {
ScriptFrame frame;
expression->Evaluate(frame);
delete expression;
}
}
ConfigType::Ptr ctype = ConfigType::GetByName(type);
if (!ctype)

View File

@ -157,8 +157,7 @@ bool TroubleshootCommand::GeneralInfo(InfoLog& log, const boost::program_options
<< "\tState path: " << Application::GetStatePath() << '\n'
<< "\tObjects path: " << Application::GetObjectsPath() << '\n'
<< "\tVars path: " << Application::GetVarsPath() << '\n'
<< "\tPID path: " << Application::GetPidPath() << '\n'
<< "\tApplication type: " << Application::GetApplicationType() << "\n";
<< "\tPID path: " << Application::GetPidPath() << '\n';
InfoLogLine(log)
<< '\n';

View File

@ -98,7 +98,7 @@ String ConfigCompiler::GetZone(void) const
void ConfigCompiler::CollectIncludes(std::vector<Expression *>& expressions, const String& file, const String& zone)
{
expressions.push_back(CompileFile(file, zone));
expressions.push_back(CompileFile(file, true, zone));
}
/**
@ -192,7 +192,7 @@ void ConfigCompiler::CompileHelper(void)
* @param stream The input stream.
* @returns Configuration items.
*/
Expression *ConfigCompiler::CompileStream(const String& path, std::istream *stream, const String& zone)
Expression *ConfigCompiler::CompileStream(const String& path, std::istream *stream, bool async, const String& zone)
{
CONTEXT("Compiling configuration stream with name '" + path + "'");
@ -200,10 +200,19 @@ Expression *ConfigCompiler::CompileStream(const String& path, std::istream *stre
ConfigCompiler* ctx = new ConfigCompiler(path, stream, zone);
boost::shared_future<boost::shared_ptr<Expression> > ftr = boost::shared_future<boost::shared_ptr<Expression> >(ctx->m_Promise.get_future());
if (async) {
boost::shared_future<boost::shared_ptr<Expression> > ftr = boost::shared_future<boost::shared_ptr<Expression> >(ctx->m_Promise.get_future());
Utility::QueueAsyncCallback(boost::bind(&ConfigCompiler::CompileHelper, ctx));
return new FutureExpression(ftr);
Utility::QueueAsyncCallback(boost::bind(&ConfigCompiler::CompileHelper, ctx));
return new FutureExpression(ftr);
} else {
try {
return ctx->Compile();
} catch (...) {
delete ctx;
throw;
}
}
}
/**
@ -212,7 +221,7 @@ Expression *ConfigCompiler::CompileStream(const String& path, std::istream *stre
* @param path The path.
* @returns Configuration items.
*/
Expression *ConfigCompiler::CompileFile(const String& path, const String& zone)
Expression *ConfigCompiler::CompileFile(const String& path, bool async, const String& zone)
{
CONTEXT("Compiling configuration file '" + path + "'");
@ -228,7 +237,7 @@ Expression *ConfigCompiler::CompileFile(const String& path, const String& zone)
Log(LogInformation, "ConfigCompiler")
<< "Compiling config file: " << path;
return CompileStream(path, stream, zone);
return CompileStream(path, stream, async, zone);
}
/**
@ -238,10 +247,10 @@ Expression *ConfigCompiler::CompileFile(const String& path, const String& zone)
* @param text The text.
* @returns Configuration items.
*/
Expression *ConfigCompiler::CompileText(const String& path, const String& text, const String& zone)
Expression *ConfigCompiler::CompileText(const String& path, const String& text, bool async, const String& zone)
{
std::stringstream *stream = new std::stringstream(text);
return CompileStream(path, stream, zone);
return CompileStream(path, stream, async, zone);
}
/**
@ -257,8 +266,3 @@ void ConfigCompiler::AddIncludeSearchDir(const String& dir)
m_IncludeSearchDirs.push_back(dir);
}
ConfigFragmentRegistry *ConfigFragmentRegistry::GetInstance(void)
{
return Singleton<ConfigFragmentRegistry>::GetInstance();
}

View File

@ -79,9 +79,9 @@ public:
Expression *Compile(void);
static Expression *CompileStream(const String& path, std::istream *stream, const String& zone = String());
static Expression *CompileFile(const String& path, const String& zone = String());
static Expression *CompileText(const String& path, const String& text, const String& zone = String());
static Expression *CompileStream(const String& path, std::istream *stream, bool async = true, const String& zone = String());
static Expression *CompileFile(const String& path, bool async = true, const String& zone = String());
static Expression *CompileText(const String& path, const String& text, bool async = true, const String& zone = String());
static void AddIncludeSearchDir(const String& dir);
@ -137,22 +137,6 @@ public:
std::stack<Expression *> m_FTerm;
};
class I2_CONFIG_API ConfigFragmentRegistry : public Registry<ConfigFragmentRegistry, String>
{
public:
static ConfigFragmentRegistry *GetInstance(void);
};
#define REGISTER_CONFIG_FRAGMENT(id, name, fragment) \
namespace { \
void RegisterConfigFragment(void) \
{ \
icinga::ConfigFragmentRegistry::GetInstance()->Register(name, fragment); \
} \
\
INITIALIZE_ONCE(RegisterConfigFragment); \
}
}
#endif /* CONFIGCOMPILER_H */

View File

@ -0,0 +1,40 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef CONFIGFRAGMENT_H
#define CONFIGFRAGMENT_H
#include "config/configcompiler.hpp"
#include "base/initialize.hpp"
#include "base/debug.hpp"
#define REGISTER_CONFIG_FRAGMENT(id, name, fragment) \
namespace { \
void RegisterConfigFragment(void) \
{ \
icinga::Expression *expression = icinga::ConfigCompiler::CompileText(name, fragment, false); \
icinga::ScriptFrame frame; \
expression->Evaluate(frame); \
delete expression; \
} \
\
INITIALIZE_ONCE(RegisterConfigFragment); \
}
#endif /* CONFIGFRAGMENT_H */

View File

@ -45,9 +45,8 @@ using namespace icinga;
boost::mutex ConfigItem::m_Mutex;
ConfigItem::TypeMap ConfigItem::m_Items;
ConfigItem::ItemList ConfigItem::m_UnnamedItems;
ConfigItem::ItemList ConfigItem::m_CommittedItems;
REGISTER_SCRIPTFUNCTION(__commit, &ConfigItem::ScriptCommit);
REGISTER_SCRIPTFUNCTION(commit_objects, &ConfigItem::ScriptCommit);
/**
* Constructor for the ConfigItem class.
@ -200,11 +199,6 @@ DynamicObject::Ptr ConfigItem::Commit(bool discard)
dobj->SetName(name);
dobj->OnConfigLoaded();
{
boost::mutex::scoped_lock lock(m_Mutex);
m_CommittedItems.push_back(this);
}
Dictionary::Ptr persistentItem = new Dictionary();
persistentItem->Set("type", GetType());
@ -319,11 +313,6 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq)
std::vector<ConfigItem::Ptr> new_items;
{
boost::mutex::scoped_lock lock(m_Mutex);
new_items.swap(m_CommittedItems);
}
std::set<String> types;
BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) {
@ -442,8 +431,15 @@ bool ConfigItem::ScriptCommit(void)
{
WorkQueue upq(25000, Application::GetConcurrency());
if (!CommitNewItems(upq))
if (!CommitNewItems(upq)) {
upq.ReportExceptions("ConfigItem");
boost::mutex::scoped_lock lock(m_Mutex);
m_Items.clear();
m_UnnamedItems.clear();
return false;
}
BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) {
BOOST_FOREACH(const DynamicObject::Ptr& object, type->GetObjects()) {
@ -458,6 +454,18 @@ bool ConfigItem::ScriptCommit(void)
}
}
upq.Join();
if (upq.HasExceptions()) {
upq.ReportExceptions("ConfigItem");
boost::mutex::scoped_lock lock(m_Mutex);
m_Items.clear();
m_UnnamedItems.clear();
return false;
}
return true;
}

View File

@ -92,7 +92,6 @@ private:
typedef std::vector<ConfigItem::Ptr> ItemList;
static ItemList m_UnnamedItems;
static ItemList m_CommittedItems;
static ConfigItem::Ptr GetObjectUnlocked(const String& type,
const String& name);

View File

@ -18,9 +18,10 @@
mkclass_target(hello.ti hello.thpp)
mkembedconfig_target(hello-type.conf hello-type.cpp)
mkembedconfig_target(hello-app.conf hello-app.cpp)
set(hello_SOURCES
hello.cpp hello.thpp hello-type.cpp
hello.cpp hello.thpp hello-type.cpp hello-app.cpp
)
if(ICINGA2_UNITY_BUILD)

20
lib/hello/hello-app.conf Normal file
View File

@ -0,0 +1,20 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
object Hello "app" { }

View File

@ -39,6 +39,7 @@ mkclass_target(usergroup.ti usergroup.thpp)
mkclass_target(user.ti user.thpp)
mkembedconfig_target(icinga-type.conf icinga-type.cpp)
mkembedconfig_target(icinga-app.conf icinga-app.cpp)
set(icinga_SOURCES
api.cpp apievents.cpp checkable.cpp checkable.thpp checkable-dependency.cpp checkable-downtime.cpp checkable-event.cpp
@ -51,7 +52,7 @@ set(icinga_SOURCES
notification.thpp notification-apply.cpp objectutils.cpp perfdatavalue.cpp perfdatavalue.thpp pluginutility.cpp scheduleddowntime.cpp
scheduleddowntime.thpp scheduleddowntime-apply.cpp service-apply.cpp checkable-check.cpp checkable-comment.cpp
service.cpp service.thpp servicegroup.cpp servicegroup.thpp checkable-notification.cpp timeperiod.cpp timeperiod.thpp
user.cpp user.thpp usergroup.cpp usergroup.thpp icinga-type.cpp
user.cpp user.thpp usergroup.cpp usergroup.thpp icinga-type.cpp icinga-app.cpp
)
if(ICINGA2_UNITY_BUILD)

View File

@ -0,0 +1,20 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
object IcingaApplication "app" { }

View File

@ -79,8 +79,6 @@ struct GlobalConfigFixture {
BOOST_MESSAGE( "Preparing config objects...");
/* start the Icinga application and load the configuration */
Application::DeclareApplicationType("icinga/IcingaApplication");
Application::DeclareSysconfDir("etc");
Application::DeclareLocalStateDir("var");
@ -90,7 +88,7 @@ struct GlobalConfigFixture {
std::vector<std::string> configs;
configs.push_back(TestConfig);
DaemonUtility::LoadConfigFiles(configs, "IcingaApplication", "icinga2.debug", "icinga2.vars");
DaemonUtility::LoadConfigFiles(configs, "icinga2.debug", "icinga2.vars");
/* ignore config errors */
ConfigItem::ActivateItems();

View File

@ -50,7 +50,7 @@ int main(int argc, char **argv)
fprintf(outfp, "/* This file has been automatically generated\n"
" from the input file \"%s\". */\n\n", argv[1]);
fputs("#include \"config/configcompiler.hpp\"\n\nstatic const char g_ConfigFragment[] = {\n", outfp);
fputs("#include \"config/configfragment.hpp\"\n\nstatic const char g_ConfigFragment[] = {\n", outfp);
fputc('\t', outfp);
cols = 0;