Fine-grained locks (WIP, Part 8).

This commit is contained in:
Gunnar Beutner 2013-02-21 16:12:50 +01:00
parent 5e91f6c54d
commit 4306c6c07a
13 changed files with 173 additions and 72 deletions

View File

@ -186,6 +186,12 @@ do
automake --add-missing --gnu $am_opt
echo "Running 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
done

View File

@ -63,27 +63,26 @@ void CheckerComponent::CheckThreadProc(void)
vector<Service::Ptr> services;
Service::Ptr service;
{
boost::mutex::scoped_lock lock(m_Mutex);
boost::mutex::scoped_lock lock(m_Mutex);
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
CheckTimeView& idx = boost::get<1>(m_IdleServices);
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
CheckTimeView& idx = boost::get<1>(m_IdleServices);
while (idx.begin() == idx.end() && !m_Stopped)
m_CV.wait(lock);
while (idx.begin() == idx.end() && !m_Stopped)
m_CV.wait(lock);
if (m_Stopped)
break;
if (m_Stopped)
break;
CheckTimeView::iterator it = idx.begin();
service = it->lock();
CheckTimeView::iterator it = idx.begin();
service = it->lock();
if (!service) {
idx.erase(it);
continue;
}
if (!service) {
idx.erase(it);
continue;
}
ObjectLock olock(service); /* also required for the key extractor. */
double wait;
{
@ -92,23 +91,20 @@ void CheckerComponent::CheckThreadProc(void)
}
if (wait > 0) {
/* Release the object lock. */
olock.Unlock();
/* Make sure the service we just examined can be destroyed while we're waiting. */
service.reset();
/* Wait for the next check. */
boost::mutex::scoped_lock lock(m_Mutex);
if (!m_Stopped)
m_CV.timed_wait(lock, boost::posix_time::milliseconds(wait * 1000));
continue;
}
{
boost::mutex::scoped_lock lock(m_Mutex);
m_IdleServices.erase(service);
}
ObjectLock olock(service); /* also required for the key extractor */
m_IdleServices.erase(service);
/* reschedule the service if checks are currently disabled
* for it and this is not a forced check */
@ -118,35 +114,27 @@ void CheckerComponent::CheckThreadProc(void)
service->UpdateNextCheck();
{
boost::mutex::scoped_lock lock(m_Mutex);
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
CheckTimeView& idx = boost::get<1>(m_IdleServices);
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
CheckTimeView& idx = boost::get<1>(m_IdleServices);
idx.insert(service);
}
idx.insert(service);
continue;
}
}
service->SetForceNextCheck(false);
service->SetFirstCheck(false);
Logger::Write(LogDebug, "checker", "Executing service check for '" + service->GetName() + "'");
{
boost::mutex::scoped_lock lock(m_Mutex);
m_IdleServices.erase(service);
m_PendingServices.insert(service);
}
m_IdleServices.erase(service);
m_PendingServices.insert(service);
double rwait = service->GetNextCheck() - Utility::GetTime();
if (abs(rwait - wait) > 5)
Logger::Write(LogWarning, "checker", "Check delayed: " + Convert::ToString(-rwait) + ",planned wait: " + Convert::ToString(-wait));
if (rwait < -5)
Logger::Write(LogWarning, "checker", "Check delayed: " + Convert::ToString(-rwait));
try {
service->BeginExecuteCheck(boost::bind(&CheckerComponent::CheckCompletedHandler, this, service));
@ -156,23 +144,21 @@ void CheckerComponent::CheckThreadProc(void)
}
}
void CheckerComponent::CheckCompletedHandler(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 the service from the list of pending services; if it's not in the
* 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. */
CheckerComponent::ServiceSet::iterator it;
it = m_PendingServices.find(service);
if (it != m_PendingServices.end()) {
m_PendingServices.erase(it);
m_IdleServices.insert(service);
m_CV.notify_all();
}
/* remove the service from the list of pending services; if it's not in the
* 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. */
CheckerComponent::ServiceSet::iterator it;
it = m_PendingServices.find(service);
if (it != m_PendingServices.end()) {
m_PendingServices.erase(it);
m_IdleServices.insert(service);
m_CV.notify_all();
}
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)
{
boost::mutex::scoped_lock lock(m_Mutex);
ObjectLock olock(service); /* also required for the key extractor */
String checker = service->GetChecker();
if (checker == EndpointManager::GetInstance()->GetIdentity() || checker == m_Endpoint->GetName()) {
boost::mutex::scoped_lock lock(m_Mutex);
if (m_PendingServices.find(service) != m_PendingServices.end())
return;
m_IdleServices.insert(service);
m_CV.notify_all();
} else {
boost::mutex::scoped_lock lock(m_Mutex);
m_IdleServices.erase(service);
m_PendingServices.erase(service);
m_CV.notify_all();
@ -217,20 +201,20 @@ void CheckerComponent::CheckerChangedHandler(const Service::Ptr& service)
void CheckerComponent::NextCheckChangedHandler(const Service::Ptr& service)
{
{
ObjectLock olock(service); /* required for the key extractor */
boost::mutex::scoped_lock lock(m_Mutex);
boost::mutex::scoped_lock lock(m_Mutex);
/* remove and re-insert the service from the set in order to force an index update */
typedef nth_index<ServiceSet, 0>::type ServiceView;
ServiceView& idx = boost::get<0>(m_IdleServices);
ObjectLock olock(service); /* required for the key extractor */
ServiceView::iterator it = idx.find(service);
if (it == idx.end())
return;
/* remove and re-insert the service from the set in order to force an index update */
typedef nth_index<ServiceSet, 0>::type ServiceView;
ServiceView& idx = boost::get<0>(m_IdleServices);
idx.replace(it, service);
m_CV.notify_all();
}
ServiceView::iterator it = idx.find(service);
if (it == idx.end())
return;
idx.erase(service);
idx.insert(service);
m_CV.notify_all();
}

View File

@ -89,10 +89,17 @@ AC_ARG_ENABLE(debug, [ --enable-debug=[no/yes] turn on debugging (default=no)
if test "x$enable_debug" = "xyes"; then
CFLAGS="$CFLAGS -g -O0"
CXXFLAGS="$CXXFLAGS -g -O0"
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
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)
AC_DEFINE_UNQUOTED([ICINGA_PREFIX], "$ICINGA_PREFIX", [The installation prefix.])

View File

@ -106,3 +106,16 @@ libbase_la_LIBADD = \
${top_builddir}/third-party/mmatch/libmmatch.la \
${top_builddir}/third-party/cJSON/libcJSON.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

View File

@ -30,7 +30,6 @@ String Application::m_PkgLibDir;
String Application::m_PkgDataDir;
int Application::m_ArgC;
char **Application::m_ArgV;
EventQueue Application::m_EQ;
/**
* Constructor for the Application class.
@ -122,7 +121,7 @@ void Application::ProfileTimerHandler(void)
void Application::ShutdownTimerHandler(void)
{
if (m_ShuttingDown)
m_EQ.Stop();
GetEQ().Stop();
}
/**
@ -565,5 +564,6 @@ void Application::SetPkgDataDir(const String& path)
*/
EventQueue& Application::GetEQ(void)
{
return m_EQ;
static EventQueue queue;
return queue;
}

View File

@ -97,7 +97,6 @@ private:
static String m_LocalStateDir; /**< The local state dir. */
static String m_PkgLibDir; /**< The package lib dir. */
static String m_PkgDataDir; /**< The package data dir. */
static EventQueue m_EQ; /**< The main thread's event queue. */
#ifndef _WIN32
static void SigIntHandler(int signum);

View File

@ -111,6 +111,10 @@ private:
*/
struct ObjectLock {
public:
ObjectLock(void)
: m_Lock()
{ }
ObjectLock(const Object::Ptr& object)
: m_Lock()
{
@ -125,6 +129,10 @@ public:
m_Lock = recursive_mutex::scoped_lock(object->GetMutex());
}
void Unlock(void)
{
m_Lock = recursive_mutex::scoped_lock();
}
private:
recursive_mutex::scoped_lock m_Lock;

View File

@ -46,3 +46,17 @@ libconfig_la_LDFLAGS = \
libconfig_la_LIBADD = \
${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

View File

@ -61,3 +61,17 @@ libicinga_la_LIBADD = \
${top_builddir}/lib/base/libbase.la \
${top_builddir}/lib/config/libconfig.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

View File

@ -506,6 +506,8 @@ void Service::CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo,
* just in case there was no check result. */
UpdateNextCheck();
olock.Unlock();
callback();
}

View File

@ -32,4 +32,18 @@ libpython_la_LIBADD = \
${top_builddir}/lib/base/libbase.la \
${top_builddir}/lib/config/libconfig.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

View File

@ -35,3 +35,17 @@ libremoting_la_LDFLAGS = \
libremoting_la_LIBADD = \
${top_builddir}/lib/base/libbase.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

26
libtool-pch.patch Normal file
View File

@ -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