mirror of https://github.com/Icinga/icinga2.git
Fine-grained locks (WIP, Part 8).
This commit is contained in:
parent
5e91f6c54d
commit
4306c6c07a
|
@ -186,6 +186,12 @@ do
|
||||||
automake --add-missing --gnu $am_opt
|
automake --add-missing --gnu $am_opt
|
||||||
echo "Running autoconf ..."
|
echo "Running autoconf ..."
|
||||||
autoconf
|
autoconf
|
||||||
|
|
||||||
|
if ! patch --dry-run -p0 < libtool-pch.patch >/dev/null; then
|
||||||
|
echo "Warning: Libtool patch did not apply cleanly."
|
||||||
|
else
|
||||||
|
patch -p0 < libtool-pch.patch
|
||||||
|
fi
|
||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
|
@ -63,27 +63,26 @@ void CheckerComponent::CheckThreadProc(void)
|
||||||
vector<Service::Ptr> services;
|
vector<Service::Ptr> services;
|
||||||
Service::Ptr service;
|
Service::Ptr service;
|
||||||
|
|
||||||
{
|
boost::mutex::scoped_lock lock(m_Mutex);
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
|
||||||
|
|
||||||
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
|
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
|
||||||
CheckTimeView& idx = boost::get<1>(m_IdleServices);
|
CheckTimeView& idx = boost::get<1>(m_IdleServices);
|
||||||
|
|
||||||
while (idx.begin() == idx.end() && !m_Stopped)
|
while (idx.begin() == idx.end() && !m_Stopped)
|
||||||
m_CV.wait(lock);
|
m_CV.wait(lock);
|
||||||
|
|
||||||
if (m_Stopped)
|
if (m_Stopped)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
CheckTimeView::iterator it = idx.begin();
|
CheckTimeView::iterator it = idx.begin();
|
||||||
service = it->lock();
|
service = it->lock();
|
||||||
|
|
||||||
if (!service) {
|
if (!service) {
|
||||||
idx.erase(it);
|
idx.erase(it);
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObjectLock olock(service); /* also required for the key extractor. */
|
||||||
double wait;
|
double wait;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -92,23 +91,20 @@ void CheckerComponent::CheckThreadProc(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait > 0) {
|
if (wait > 0) {
|
||||||
|
/* Release the object lock. */
|
||||||
|
olock.Unlock();
|
||||||
|
|
||||||
/* Make sure the service we just examined can be destroyed while we're waiting. */
|
/* Make sure the service we just examined can be destroyed while we're waiting. */
|
||||||
service.reset();
|
service.reset();
|
||||||
|
|
||||||
/* Wait for the next check. */
|
/* Wait for the next check. */
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
|
||||||
if (!m_Stopped)
|
if (!m_Stopped)
|
||||||
m_CV.timed_wait(lock, boost::posix_time::milliseconds(wait * 1000));
|
m_CV.timed_wait(lock, boost::posix_time::milliseconds(wait * 1000));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
m_IdleServices.erase(service);
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
|
||||||
m_IdleServices.erase(service);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectLock olock(service); /* also required for the key extractor */
|
|
||||||
|
|
||||||
/* reschedule the service if checks are currently disabled
|
/* reschedule the service if checks are currently disabled
|
||||||
* for it and this is not a forced check */
|
* for it and this is not a forced check */
|
||||||
|
@ -118,35 +114,27 @@ void CheckerComponent::CheckThreadProc(void)
|
||||||
|
|
||||||
service->UpdateNextCheck();
|
service->UpdateNextCheck();
|
||||||
|
|
||||||
{
|
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
CheckTimeView& idx = boost::get<1>(m_IdleServices);
|
||||||
|
|
||||||
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
|
idx.insert(service);
|
||||||
CheckTimeView& idx = boost::get<1>(m_IdleServices);
|
|
||||||
|
|
||||||
idx.insert(service);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
service->SetForceNextCheck(false);
|
service->SetForceNextCheck(false);
|
||||||
|
|
||||||
service->SetFirstCheck(false);
|
service->SetFirstCheck(false);
|
||||||
|
|
||||||
Logger::Write(LogDebug, "checker", "Executing service check for '" + service->GetName() + "'");
|
Logger::Write(LogDebug, "checker", "Executing service check for '" + service->GetName() + "'");
|
||||||
|
|
||||||
{
|
m_IdleServices.erase(service);
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
m_PendingServices.insert(service);
|
||||||
m_IdleServices.erase(service);
|
|
||||||
m_PendingServices.insert(service);
|
|
||||||
}
|
|
||||||
|
|
||||||
double rwait = service->GetNextCheck() - Utility::GetTime();
|
double rwait = service->GetNextCheck() - Utility::GetTime();
|
||||||
|
|
||||||
if (abs(rwait - wait) > 5)
|
if (rwait < -5)
|
||||||
Logger::Write(LogWarning, "checker", "Check delayed: " + Convert::ToString(-rwait) + ",planned wait: " + Convert::ToString(-wait));
|
Logger::Write(LogWarning, "checker", "Check delayed: " + Convert::ToString(-rwait));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
service->BeginExecuteCheck(boost::bind(&CheckerComponent::CheckCompletedHandler, this, service));
|
service->BeginExecuteCheck(boost::bind(&CheckerComponent::CheckCompletedHandler, this, service));
|
||||||
|
@ -156,23 +144,21 @@ void CheckerComponent::CheckThreadProc(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CheckerComponent::CheckCompletedHandler(const Service::Ptr& service)
|
void CheckerComponent::CheckCompletedHandler(const Service::Ptr& service)
|
||||||
{
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_Mutex);
|
||||||
ObjectLock olock(service); /* required for the key extractor */
|
ObjectLock olock(service); /* required for the key extractor */
|
||||||
|
|
||||||
{
|
/* remove the service from the list of pending services; if it's not in the
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
* list this was a manual (i.e. forced) check and we must not re-add the
|
||||||
|
* service to the services list because it's already there. */
|
||||||
/* remove the service from the list of pending services; if it's not in the
|
CheckerComponent::ServiceSet::iterator it;
|
||||||
* list this was a manual (i.e. forced) check and we must not re-add the
|
it = m_PendingServices.find(service);
|
||||||
* service to the services list because it's already there. */
|
if (it != m_PendingServices.end()) {
|
||||||
CheckerComponent::ServiceSet::iterator it;
|
m_PendingServices.erase(it);
|
||||||
it = m_PendingServices.find(service);
|
m_IdleServices.insert(service);
|
||||||
if (it != m_PendingServices.end()) {
|
m_CV.notify_all();
|
||||||
m_PendingServices.erase(it);
|
|
||||||
m_IdleServices.insert(service);
|
|
||||||
m_CV.notify_all();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::Write(LogDebug, "checker", "Check finished for service '" + service->GetName() + "'");
|
Logger::Write(LogDebug, "checker", "Check finished for service '" + service->GetName() + "'");
|
||||||
|
@ -195,20 +181,18 @@ void CheckerComponent::ResultTimerHandler(void)
|
||||||
|
|
||||||
void CheckerComponent::CheckerChangedHandler(const Service::Ptr& service)
|
void CheckerComponent::CheckerChangedHandler(const Service::Ptr& service)
|
||||||
{
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_Mutex);
|
||||||
|
|
||||||
ObjectLock olock(service); /* also required for the key extractor */
|
ObjectLock olock(service); /* also required for the key extractor */
|
||||||
String checker = service->GetChecker();
|
String checker = service->GetChecker();
|
||||||
|
|
||||||
if (checker == EndpointManager::GetInstance()->GetIdentity() || checker == m_Endpoint->GetName()) {
|
if (checker == EndpointManager::GetInstance()->GetIdentity() || checker == m_Endpoint->GetName()) {
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
|
||||||
|
|
||||||
if (m_PendingServices.find(service) != m_PendingServices.end())
|
if (m_PendingServices.find(service) != m_PendingServices.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_IdleServices.insert(service);
|
m_IdleServices.insert(service);
|
||||||
m_CV.notify_all();
|
m_CV.notify_all();
|
||||||
} else {
|
} else {
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
|
||||||
|
|
||||||
m_IdleServices.erase(service);
|
m_IdleServices.erase(service);
|
||||||
m_PendingServices.erase(service);
|
m_PendingServices.erase(service);
|
||||||
m_CV.notify_all();
|
m_CV.notify_all();
|
||||||
|
@ -217,20 +201,20 @@ void CheckerComponent::CheckerChangedHandler(const Service::Ptr& service)
|
||||||
|
|
||||||
void CheckerComponent::NextCheckChangedHandler(const Service::Ptr& service)
|
void CheckerComponent::NextCheckChangedHandler(const Service::Ptr& service)
|
||||||
{
|
{
|
||||||
{
|
boost::mutex::scoped_lock lock(m_Mutex);
|
||||||
ObjectLock olock(service); /* required for the key extractor */
|
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
|
||||||
|
|
||||||
/* remove and re-insert the service from the set in order to force an index update */
|
ObjectLock olock(service); /* required for the key extractor */
|
||||||
typedef nth_index<ServiceSet, 0>::type ServiceView;
|
|
||||||
ServiceView& idx = boost::get<0>(m_IdleServices);
|
|
||||||
|
|
||||||
ServiceView::iterator it = idx.find(service);
|
/* remove and re-insert the service from the set in order to force an index update */
|
||||||
if (it == idx.end())
|
typedef nth_index<ServiceSet, 0>::type ServiceView;
|
||||||
return;
|
ServiceView& idx = boost::get<0>(m_IdleServices);
|
||||||
|
|
||||||
idx.replace(it, service);
|
ServiceView::iterator it = idx.find(service);
|
||||||
m_CV.notify_all();
|
if (it == idx.end())
|
||||||
}
|
return;
|
||||||
|
|
||||||
|
idx.erase(service);
|
||||||
|
idx.insert(service);
|
||||||
|
m_CV.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
configure.ac
13
configure.ac
|
@ -89,10 +89,17 @@ AC_ARG_ENABLE(debug, [ --enable-debug=[no/yes] turn on debugging (default=no)
|
||||||
if test "x$enable_debug" = "xyes"; then
|
if test "x$enable_debug" = "xyes"; then
|
||||||
CFLAGS="$CFLAGS -g -O0"
|
CFLAGS="$CFLAGS -g -O0"
|
||||||
CXXFLAGS="$CXXFLAGS -g -O0"
|
CXXFLAGS="$CXXFLAGS -g -O0"
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
fi
|
fi
|
||||||
|
AC_MSG_RESULT($enable_debug)
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(whether to enable GCC precompiled headers)
|
||||||
|
AC_ARG_ENABLE(pch, [ --enable-pch=[no/yes] enable GCC precompiled headers (default=no)],, enable_pch=no)
|
||||||
|
AM_CONDITIONAL([USE_PCH], [test "x$enable_pch" = "xyes"])
|
||||||
|
if test "x$enable_pch" = "xyes"; then
|
||||||
|
CFLAGS="$CFLAGS -fpch-deps -fpch-preprocess -Winvalid-pch"
|
||||||
|
CXXFLAGS="$CXXFLAGS -fpch-deps -fpch-preprocess -Winvalid-pch"
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT($enable_pch)
|
||||||
|
|
||||||
AS_AC_EXPAND([ICINGA_PREFIX], $prefix)
|
AS_AC_EXPAND([ICINGA_PREFIX], $prefix)
|
||||||
AC_DEFINE_UNQUOTED([ICINGA_PREFIX], "$ICINGA_PREFIX", [The installation prefix.])
|
AC_DEFINE_UNQUOTED([ICINGA_PREFIX], "$ICINGA_PREFIX", [The installation prefix.])
|
||||||
|
|
|
@ -106,3 +106,16 @@ libbase_la_LIBADD = \
|
||||||
${top_builddir}/third-party/mmatch/libmmatch.la \
|
${top_builddir}/third-party/mmatch/libmmatch.la \
|
||||||
${top_builddir}/third-party/cJSON/libcJSON.la \
|
${top_builddir}/third-party/cJSON/libcJSON.la \
|
||||||
${top_builddir}/third-party/popen-noshell/libpopen_noshell.la
|
${top_builddir}/third-party/popen-noshell/libpopen_noshell.la
|
||||||
|
|
||||||
|
if USE_PCH
|
||||||
|
BUILT_SOURCES = i2-base.h.gch
|
||||||
|
|
||||||
|
i2-base.h.gch: i2-base.h
|
||||||
|
$(AM_V_CXX)$(LTCXXCOMPILE) $(libbase_la_CPPFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
libbase_la_DEPENDENCIES = \
|
||||||
|
i2-base.h.gch
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
rm -f i2-base.h.gch
|
||||||
|
endif
|
||||||
|
|
|
@ -30,7 +30,6 @@ String Application::m_PkgLibDir;
|
||||||
String Application::m_PkgDataDir;
|
String Application::m_PkgDataDir;
|
||||||
int Application::m_ArgC;
|
int Application::m_ArgC;
|
||||||
char **Application::m_ArgV;
|
char **Application::m_ArgV;
|
||||||
EventQueue Application::m_EQ;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the Application class.
|
* Constructor for the Application class.
|
||||||
|
@ -122,7 +121,7 @@ void Application::ProfileTimerHandler(void)
|
||||||
void Application::ShutdownTimerHandler(void)
|
void Application::ShutdownTimerHandler(void)
|
||||||
{
|
{
|
||||||
if (m_ShuttingDown)
|
if (m_ShuttingDown)
|
||||||
m_EQ.Stop();
|
GetEQ().Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -565,5 +564,6 @@ void Application::SetPkgDataDir(const String& path)
|
||||||
*/
|
*/
|
||||||
EventQueue& Application::GetEQ(void)
|
EventQueue& Application::GetEQ(void)
|
||||||
{
|
{
|
||||||
return m_EQ;
|
static EventQueue queue;
|
||||||
|
return queue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,6 @@ private:
|
||||||
static String m_LocalStateDir; /**< The local state dir. */
|
static String m_LocalStateDir; /**< The local state dir. */
|
||||||
static String m_PkgLibDir; /**< The package lib dir. */
|
static String m_PkgLibDir; /**< The package lib dir. */
|
||||||
static String m_PkgDataDir; /**< The package data dir. */
|
static String m_PkgDataDir; /**< The package data dir. */
|
||||||
static EventQueue m_EQ; /**< The main thread's event queue. */
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
static void SigIntHandler(int signum);
|
static void SigIntHandler(int signum);
|
||||||
|
|
|
@ -111,6 +111,10 @@ private:
|
||||||
*/
|
*/
|
||||||
struct ObjectLock {
|
struct ObjectLock {
|
||||||
public:
|
public:
|
||||||
|
ObjectLock(void)
|
||||||
|
: m_Lock()
|
||||||
|
{ }
|
||||||
|
|
||||||
ObjectLock(const Object::Ptr& object)
|
ObjectLock(const Object::Ptr& object)
|
||||||
: m_Lock()
|
: m_Lock()
|
||||||
{
|
{
|
||||||
|
@ -125,6 +129,10 @@ public:
|
||||||
m_Lock = recursive_mutex::scoped_lock(object->GetMutex());
|
m_Lock = recursive_mutex::scoped_lock(object->GetMutex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unlock(void)
|
||||||
|
{
|
||||||
|
m_Lock = recursive_mutex::scoped_lock();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
recursive_mutex::scoped_lock m_Lock;
|
recursive_mutex::scoped_lock m_Lock;
|
||||||
|
|
|
@ -46,3 +46,17 @@ libconfig_la_LDFLAGS = \
|
||||||
|
|
||||||
libconfig_la_LIBADD = \
|
libconfig_la_LIBADD = \
|
||||||
${top_builddir}/lib/base/libbase.la
|
${top_builddir}/lib/base/libbase.la
|
||||||
|
|
||||||
|
if USE_PCH
|
||||||
|
BUILT_SOURCES += i2-config.h.gch
|
||||||
|
|
||||||
|
i2-config.h.gch: i2-config.h
|
||||||
|
$(AM_V_CXX)$(LTCXXCOMPILE) $(libconfig_la_CPPFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
libconfig_la_DEPENDENCIES = \
|
||||||
|
i2-config.h.gch
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
rm -f i2-config.h.gch
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
|
@ -61,3 +61,17 @@ libicinga_la_LIBADD = \
|
||||||
${top_builddir}/lib/base/libbase.la \
|
${top_builddir}/lib/base/libbase.la \
|
||||||
${top_builddir}/lib/config/libconfig.la \
|
${top_builddir}/lib/config/libconfig.la \
|
||||||
${top_builddir}/lib/remoting/libremoting.la
|
${top_builddir}/lib/remoting/libremoting.la
|
||||||
|
|
||||||
|
if USE_PCH
|
||||||
|
BUILT_SOURCES = i2-icinga.h.gch
|
||||||
|
|
||||||
|
i2-icinga.h.gch: i2-icinga.h
|
||||||
|
$(AM_V_CXX)$(LTCXXCOMPILE) $(libicinga_la_CPPFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
libicinga_la_DEPENDENCIES = \
|
||||||
|
i2-icinga.h.gch
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
rm -f i2-icinga.h.gch
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
|
@ -506,6 +506,8 @@ void Service::CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo,
|
||||||
* just in case there was no check result. */
|
* just in case there was no check result. */
|
||||||
UpdateNextCheck();
|
UpdateNextCheck();
|
||||||
|
|
||||||
|
olock.Unlock();
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,4 +32,18 @@ libpython_la_LIBADD = \
|
||||||
${top_builddir}/lib/base/libbase.la \
|
${top_builddir}/lib/base/libbase.la \
|
||||||
${top_builddir}/lib/config/libconfig.la \
|
${top_builddir}/lib/config/libconfig.la \
|
||||||
${top_builddir}/lib/remoting/libremoting.la
|
${top_builddir}/lib/remoting/libremoting.la
|
||||||
|
|
||||||
|
if USE_PCH
|
||||||
|
BUILT_SOURCES = i2-python.h.gch
|
||||||
|
|
||||||
|
i2-python.h.gch: i2-python.h
|
||||||
|
$(AM_V_CXX)$(LTCXXCOMPILE) $(libpython_la_CPPFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
libpython_la_DEPENDENCIES = \
|
||||||
|
i2-python.h.gch
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
rm -f i2-python.h.gch
|
||||||
|
endif
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -35,3 +35,17 @@ libremoting_la_LDFLAGS = \
|
||||||
libremoting_la_LIBADD = \
|
libremoting_la_LIBADD = \
|
||||||
${top_builddir}/lib/base/libbase.la \
|
${top_builddir}/lib/base/libbase.la \
|
||||||
${top_builddir}/lib/config/libconfig.la
|
${top_builddir}/lib/config/libconfig.la
|
||||||
|
|
||||||
|
if USE_PCH
|
||||||
|
BUILT_SOURCES = i2-remoting.h.gch
|
||||||
|
|
||||||
|
i2-remoting.h.gch: i2-remoting.h
|
||||||
|
$(AM_V_CXX)$(LTCXXCOMPILE) $(libremoting_la_CPPFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
libremoting_la_DEPENDENCIES = \
|
||||||
|
i2-remoting.h.gch
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
rm -f i2-remoting.h.gch
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
--- m4/ltmain.sh 2013-02-21 11:23:30.000000000 +0100
|
||||||
|
+++ m4/ltmain.sh 2013-02-21 11:36:37.000000000 +0100
|
||||||
|
@@ -2507,6 +2507,7 @@
|
||||||
|
|
||||||
|
case $libobj in
|
||||||
|
*.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
|
||||||
|
+ *.gch) obj=$libobj ;;
|
||||||
|
*)
|
||||||
|
func_fatal_error "cannot determine name of library object from \`$libobj'"
|
||||||
|
;;
|
||||||
|
@@ -2717,7 +2718,14 @@
|
||||||
|
fi
|
||||||
|
|
||||||
|
$opt_dry_run || {
|
||||||
|
- func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
|
||||||
|
+ case $libobj in
|
||||||
|
+ *.gch)
|
||||||
|
+ ln -sF "$objdir/$objname" "$libobj"
|
||||||
|
+ ;;
|
||||||
|
+ *)
|
||||||
|
+ func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
|
||||||
|
+ ;;
|
||||||
|
+ esac
|
||||||
|
|
||||||
|
# Unlock the critical section if it was locked
|
||||||
|
if test "$need_locks" != no; then
|
Loading…
Reference in New Issue