Fix --disable-shared

Fixes #3852
This commit is contained in:
Gunnar Beutner 2013-03-15 11:19:52 +01:00
parent 9ac731ba8e
commit ee46731f41
16 changed files with 211 additions and 134 deletions

View File

@ -106,13 +106,7 @@ void ReplicationComponent::EndpointConnectedHandler(const Endpoint::Ptr& endpoin
continue; continue;
RequestMessage request = MakeObjectMessage(object, "config::ObjectUpdate", 0, true); RequestMessage request = MakeObjectMessage(object, "config::ObjectUpdate", 0, true);
EndpointManager::GetInstance()->SendUnicastMessage(m_Endpoint, endpoint, request);
EndpointManager::Ptr em = EndpointManager::GetInstance();
{
ObjectLock elock(em);
em->SendUnicastMessage(m_Endpoint, endpoint, request);
}
} }
} }
@ -190,12 +184,7 @@ void ReplicationComponent::FlushObjectHandler(double tx, const DynamicObject::Pt
return; return;
RequestMessage request = MakeObjectMessage(object, "config::ObjectUpdate", tx, true); RequestMessage request = MakeObjectMessage(object, "config::ObjectUpdate", tx, true);
EndpointManager::GetInstance()->SendMulticastMessage(m_Endpoint, request);
EndpointManager::Ptr em = EndpointManager::GetInstance();
{
ObjectLock olock(em);
em->SendMulticastMessage(m_Endpoint, request);
}
} }
void ReplicationComponent::RemoteObjectUpdateHandler(const RequestMessage& request) void ReplicationComponent::RemoteObjectUpdateHandler(const RequestMessage& request)

View File

@ -34,6 +34,7 @@ icinga2_LDADD = \
-dlopen ${top_builddir}/components/compat/libcompat.la \ -dlopen ${top_builddir}/components/compat/libcompat.la \
-dlopen ${top_builddir}/components/delegation/libdelegation.la \ -dlopen ${top_builddir}/components/delegation/libdelegation.la \
-dlopen ${top_builddir}/components/demo/libdemo.la \ -dlopen ${top_builddir}/components/demo/libdemo.la \
-dlopen ${top_builddir}/components/livestatus/liblivestatus.la \
-dlopen ${top_builddir}/components/notification/libnotification.la -dlopen ${top_builddir}/components/notification/libnotification.la
if PYTHON_USE if PYTHON_USE

View File

@ -44,6 +44,7 @@ libbase_la_SOURCES = \
process.h \ process.h \
qstring.cpp \ qstring.cpp \
qstring.h \ qstring.h \
registry.h \
ringbuffer.cpp \ ringbuffer.cpp \
ringbuffer.h \ ringbuffer.h \
script.cpp \ script.cpp \
@ -56,6 +57,7 @@ libbase_la_SOURCES = \
scriptlanguage.h \ scriptlanguage.h \
scripttask.cpp \ scripttask.cpp \
scripttask.h \ scripttask.h \
singleton.h \
socket.cpp \ socket.cpp \
socket.h \ socket.h \
stacktrace.cpp \ stacktrace.cpp \

View File

@ -439,7 +439,7 @@ ScriptTask::Ptr DynamicObject::MakeMethodTask(const String& method,
if (funcName.IsEmpty()) if (funcName.IsEmpty())
return ScriptTask::Ptr(); return ScriptTask::Ptr();
ScriptFunction::Ptr func = ScriptFunction::GetByName(funcName); ScriptFunction::Ptr func = ScriptFunctionRegistry::GetInstance()->GetItem(funcName);
if (!func) if (!func)
BOOST_THROW_EXCEPTION(invalid_argument("Function '" + funcName + "' does not exist.")); BOOST_THROW_EXCEPTION(invalid_argument("Function '" + funcName + "' does not exist."));

View File

@ -68,6 +68,14 @@ private:
static boost::mutex& GetStaticMutex(void); static boost::mutex& GetStaticMutex(void);
}; };
/**
* A registry for DynamicType objects.
*
* @ingroup base
*/
class DynamicTypeRegistry : public Registry<DynamicType::Ptr>
{ };
/** /**
* Helper class for registering DynamicObject implementation classes. * Helper class for registering DynamicObject implementation classes.
* *

View File

@ -223,6 +223,8 @@ namespace signals2 = boost::signals2;
#include "tlsstream.h" #include "tlsstream.h"
#include "asynctask.h" #include "asynctask.h"
#include "process.h" #include "process.h"
#include "singleton.h"
#include "registry.h"
#include "scriptfunction.h" #include "scriptfunction.h"
#include "scripttask.h" #include "scripttask.h"
#include "attribute.h" #include "attribute.h"

110
lib/base/registry.h Normal file
View File

@ -0,0 +1,110 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 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 REGISTRY_H
#define REGISTRY_H
namespace icinga
{
/**
* A registry.
*
* @ingroup base
*/
template<typename T>
class I2_BASE_API Registry
{
public:
typedef map<String, T, string_iless> ItemMap;
static Registry<T> *GetInstance(void)
{
return Singleton<Registry<T> >::GetInstance();
}
void Register(const String& name, const T& item)
{
bool old_item = false;
{
boost::mutex::scoped_lock lock(m_Mutex);
if (m_Items.erase(name) > 0)
old_item = true;
m_Items[name] = item;
}
if (old_item)
OnUnregistered(name);
OnRegistered(name, item);
}
void Unregister(const String& name)
{
int erased;
{
boost::mutex::scoped_lock lock(m_Mutex);
erased = m_Items.erase(name);
}
if (erased > 0)
OnUnregistered(name);
}
T GetItem(const String& name) const
{
boost::mutex::scoped_lock lock(m_Mutex);
typename ItemMap::const_iterator it;
it = m_Items.find(name);
if (it == m_Items.end())
return T();
return it->second;
}
ItemMap GetItems(void) const
{
boost::mutex::scoped_lock lock(m_Mutex);
return m_Items; /* Makes a copy of the map. */
}
static signals2::signal<void (const String&, const T&)> OnRegistered;
static signals2::signal<void (const String&)> OnUnregistered;
private:
mutable boost::mutex m_Mutex;
typename Registry<T>::ItemMap m_Items;
};
template<typename T>
signals2::signal<void (const String&, const T&)> Registry<T>::OnRegistered;
template<typename T>
signals2::signal<void (const String&)> Registry<T>::OnUnregistered;
}
#endif /* REGISTRY_H */

View File

@ -21,52 +21,10 @@
using namespace icinga; using namespace icinga;
signals2::signal<void (const String&, const ScriptFunction::Ptr&)> ScriptFunction::OnRegistered;
signals2::signal<void (const String&)> ScriptFunction::OnUnregistered;
ScriptFunction::ScriptFunction(const Callback& function) ScriptFunction::ScriptFunction(const Callback& function)
: m_Callback(function) : m_Callback(function)
{ } { }
/**
* @threadsafety Always.
*/
void ScriptFunction::Register(const String& name, const ScriptFunction::Ptr& function)
{
boost::mutex::scoped_lock lock(GetMutex());
InternalGetFunctions()[name] = function;
OnRegistered(name, function);
}
/**
* @threadsafety Always.
*/
void ScriptFunction::Unregister(const String& name)
{
boost::mutex::scoped_lock lock(GetMutex());
InternalGetFunctions().erase(name);
OnUnregistered(name);
}
/**
* @threadsafety Always.
*/
ScriptFunction::Ptr ScriptFunction::GetByName(const String& name)
{
boost::mutex::scoped_lock lock(GetMutex());
map<String, ScriptFunction::Ptr>::iterator it;
it = InternalGetFunctions().find(name);
if (it == InternalGetFunctions().end())
return ScriptFunction::Ptr();
return it->second;
}
/** /**
* @threadsafety Always. * @threadsafety Always.
*/ */
@ -74,31 +32,3 @@ void ScriptFunction::Invoke(const ScriptTask::Ptr& task, const vector<Value>& ar
{ {
m_Callback(task, arguments); m_Callback(task, arguments);
} }
/**
* @threadsafety Always.
*/
map<String, ScriptFunction::Ptr> ScriptFunction::GetFunctions(void)
{
boost::mutex::scoped_lock lock(GetMutex());
return InternalGetFunctions(); /* makes a copy of the map */
}
/**
* @threadsafety Caller must hold the mutex returned by GetMutex().
*/
map<String, ScriptFunction::Ptr>& ScriptFunction::InternalGetFunctions(void)
{
static map<String, ScriptFunction::Ptr> functions;
return functions;
}
/**
* @threadsafety Always.
*/
boost::mutex& ScriptFunction::GetMutex(void)
{
static boost::mutex mtx;
return mtx;
}

View File

@ -40,26 +40,22 @@ public:
explicit ScriptFunction(const Callback& function); explicit ScriptFunction(const Callback& function);
static void Register(const String& name, const ScriptFunction::Ptr& function);
static void Unregister(const String& name);
static ScriptFunction::Ptr GetByName(const String& name);
static map<String, ScriptFunction::Ptr> GetFunctions(void);
static signals2::signal<void (const String&, const ScriptFunction::Ptr&)> OnRegistered;
static signals2::signal<void (const String&)> OnUnregistered;
private: private:
Callback m_Callback; Callback m_Callback;
static map<String, ScriptFunction::Ptr>& InternalGetFunctions(void);
static boost::mutex& GetMutex(void);
void Invoke(const shared_ptr<ScriptTask>& task, const vector<Value>& arguments); void Invoke(const shared_ptr<ScriptTask>& task, const vector<Value>& arguments);
friend class ScriptTask; friend class ScriptTask;
}; };
/**
* A registry for script functions.
*
* @ingroup base
*/
class I2_BASE_API ScriptFunctionRegistry : public Registry<ScriptFunction::Ptr>
{ };
/** /**
* Helper class for registering ScriptFunction implementation classes. * Helper class for registering ScriptFunction implementation classes.
* *
@ -70,10 +66,8 @@ class RegisterFunctionHelper
public: public:
RegisterFunctionHelper(const String& name, const ScriptFunction::Callback& function) RegisterFunctionHelper(const String& name, const ScriptFunction::Callback& function)
{ {
if (!ScriptFunction::GetByName(name)) { ScriptFunction::Ptr func = boost::make_shared<ScriptFunction>(function);
ScriptFunction::Ptr func = boost::make_shared<ScriptFunction>(function); ScriptFunctionRegistry::GetInstance()->Register(name, func);
ScriptFunction::Register(name, func);
}
} }
}; };

View File

@ -27,7 +27,7 @@ ScriptInterpreter::ScriptInterpreter(const Script::Ptr&)
ScriptInterpreter::~ScriptInterpreter(void) ScriptInterpreter::~ScriptInterpreter(void)
{ {
BOOST_FOREACH(const String& function, m_SubscribedFunctions) { BOOST_FOREACH(const String& function, m_SubscribedFunctions) {
ScriptFunction::Unregister(function); ScriptFunctionRegistry::GetInstance()->Unregister(function);
} }
} }
@ -38,7 +38,7 @@ void ScriptInterpreter::SubscribeFunction(const String& name)
m_SubscribedFunctions.insert(name); m_SubscribedFunctions.insert(name);
ScriptFunction::Ptr sf = boost::make_shared<ScriptFunction>(boost::bind(&ScriptInterpreter::ProcessCall, this, _1, name, _2)); ScriptFunction::Ptr sf = boost::make_shared<ScriptFunction>(boost::bind(&ScriptInterpreter::ProcessCall, this, _1, name, _2));
ScriptFunction::Register(name, sf); ScriptFunctionRegistry::GetInstance()->Register(name, sf);
} }
void ScriptInterpreter::UnsubscribeFunction(const String& name) void ScriptInterpreter::UnsubscribeFunction(const String& name)
@ -46,5 +46,5 @@ void ScriptInterpreter::UnsubscribeFunction(const String& name)
ObjectLock olock(this); ObjectLock olock(this);
m_SubscribedFunctions.erase(name); m_SubscribedFunctions.erase(name);
ScriptFunction::Unregister(name); ScriptFunctionRegistry::GetInstance()->Unregister(name);
} }

57
lib/base/singleton.h Normal file
View File

@ -0,0 +1,57 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 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 SINGLETON_H
#define SINGLETON_H
namespace icinga
{
/**
* A singleton.
*
* @ingroup base
*/
template<typename T>
class I2_BASE_API Singleton
{
public:
static T *GetInstance(void)
{
/* FIXME: This relies on static initializers being atomic. */
static boost::mutex mutex;
boost::mutex::scoped_lock lock(mutex);
if (!m_Instance)
m_Instance = new T();
return m_Instance;
}
private:
friend T *T::GetInstance(void);
static T *m_Instance;
};
template<typename T>
T *Singleton<T>::m_Instance = NULL;
}
#endif /* SINGLETON_H */

View File

@ -210,14 +210,3 @@ void ConfigCompiler::AddIncludeSearchDir(const String& dir)
m_IncludeSearchDirs.push_back(dir); m_IncludeSearchDirs.push_back(dir);
} }
void ConfigCompiler::RegisterConfigFragment(const String& name, const String& fragment)
{
GetConfigFragments()[name] = fragment;
}
map<String, String>& ConfigCompiler::GetConfigFragments(void)
{
static map<String, String> fragments;
return fragments;
}

View File

@ -58,9 +58,6 @@ public:
size_t ReadInput(char *buffer, size_t max_bytes); size_t ReadInput(char *buffer, size_t max_bytes);
void *GetScanner(void) const; void *GetScanner(void) const;
static void RegisterConfigFragment(const String& name, const String& fragment);
static map<String, String>& GetConfigFragments(void);
private: private:
String m_Path; String m_Path;
istream *m_Input; istream *m_Input;
@ -75,6 +72,9 @@ private:
void DestroyScanner(void); void DestroyScanner(void);
}; };
class ConfigFragmentRegistry : public Registry<String>
{ };
/** /**
* Helper class for registering config fragments. * Helper class for registering config fragments.
* *
@ -85,7 +85,7 @@ class RegisterConfigFragmentHelper
public: public:
RegisterConfigFragmentHelper(const String& name, const String& fragment) RegisterConfigFragmentHelper(const String& name, const String& fragment)
{ {
ConfigCompiler::RegisterConfigFragment(name, fragment); ConfigFragmentRegistry::GetInstance()->Register(name, fragment);
} }
}; };

View File

@ -122,7 +122,7 @@ void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary,
String validator = ruleList->GetValidator(); String validator = ruleList->GetValidator();
if (!validator.IsEmpty()) { if (!validator.IsEmpty()) {
ScriptFunction::Ptr func = ScriptFunction::GetByName(validator); ScriptFunction::Ptr func = ScriptFunctionRegistry::GetInstance()->GetItem(validator);
if (!func) if (!func)
BOOST_THROW_EXCEPTION(invalid_argument("Validator function '" + validator + "' does not exist.")); BOOST_THROW_EXCEPTION(invalid_argument("Validator function '" + validator + "' does not exist."));
@ -203,7 +203,7 @@ void ConfigType::ValidateArray(const Array::Ptr& array,
String validator = ruleList->GetValidator(); String validator = ruleList->GetValidator();
if (!validator.IsEmpty()) { if (!validator.IsEmpty()) {
ScriptFunction::Ptr func = ScriptFunction::GetByName(validator); ScriptFunction::Ptr func = ScriptFunctionRegistry::GetInstance()->GetItem(validator);
if (!func) if (!func)
BOOST_THROW_EXCEPTION(invalid_argument("Validator function '" + validator + "' does not exist.")); BOOST_THROW_EXCEPTION(invalid_argument("Validator function '" + validator + "' does not exist."));

View File

@ -399,8 +399,8 @@ void EndpointManager::RequestTimerHandler(void)
map<String, PendingRequest>::iterator it; map<String, PendingRequest>::iterator it;
for (it = m_Requests.begin(); it != m_Requests.end(); ++it) { for (it = m_Requests.begin(); it != m_Requests.end(); ++it) {
if (it->second.HasTimedOut()) { if (it->second.HasTimedOut()) {
it->second.Callback(GetSelf(), Endpoint::Ptr(), it->second.Callback(Endpoint::Ptr(), it->second.Request,
it->second.Request, ResponseMessage(), true); ResponseMessage(), true);
m_Requests.erase(it); m_Requests.erase(it);
@ -424,17 +424,12 @@ void EndpointManager::ProcessResponseMessage(const Endpoint::Ptr& sender,
if (it == m_Requests.end()) if (it == m_Requests.end())
return; return;
it->second.Callback(GetSelf(), sender, it->second.Request, message, false); it->second.Callback(sender, it->second.Request, message, false);
m_Requests.erase(it); m_Requests.erase(it);
} }
EndpointManager::Ptr EndpointManager::GetInstance(void) EndpointManager *EndpointManager::GetInstance(void)
{ {
static EndpointManager::Ptr instance; return Singleton<EndpointManager>::GetInstance();
if (!instance)
instance = boost::make_shared<EndpointManager>();
return instance;
} }

View File

@ -36,7 +36,7 @@ public:
EndpointManager(void); EndpointManager(void);
static EndpointManager::Ptr GetInstance(void); static EndpointManager *GetInstance(void);
void SetIdentity(const String& identity); void SetIdentity(const String& identity);
String GetIdentity(void) const; String GetIdentity(void) const;
@ -53,14 +53,14 @@ public:
void SendMulticastMessage(const RequestMessage& message); void SendMulticastMessage(const RequestMessage& message);
void SendMulticastMessage(const Endpoint::Ptr& sender, const RequestMessage& message); void SendMulticastMessage(const Endpoint::Ptr& sender, const RequestMessage& message);
typedef function<void(const EndpointManager::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> APICallback; typedef function<void(const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> APICallback;
void SendAPIMessage(const Endpoint::Ptr& sender, const Endpoint::Ptr& recipient, RequestMessage& message, void SendAPIMessage(const Endpoint::Ptr& sender, const Endpoint::Ptr& recipient, RequestMessage& message,
const APICallback& callback, double timeout = 30); const APICallback& callback, double timeout = 30);
void ProcessResponseMessage(const Endpoint::Ptr& sender, const ResponseMessage& message); void ProcessResponseMessage(const Endpoint::Ptr& sender, const ResponseMessage& message);
signals2::signal<void (const EndpointManager::Ptr&, const Endpoint::Ptr&)> OnNewEndpoint; signals2::signal<void (const Endpoint::Ptr&)> OnNewEndpoint;
private: private:
String m_Identity; String m_Identity;
@ -84,7 +84,7 @@ private:
{ {
double Timeout; double Timeout;
RequestMessage Request; RequestMessage Request;
function<void(const EndpointManager::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> Callback; function<void(const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> Callback;
bool HasTimedOut(void) const bool HasTimedOut(void) const
{ {