From: Gunnar Beutner Date: Thu, 21 Feb 2013 15:12:50 +0000 (+0100) Subject: Fine-grained locks (WIP, Part 8). X-Git-Tag: v0.0.2~374 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4306c6c07a356cbe38ed363071693cadf5973b10;p=icinga2 Fine-grained locks (WIP, Part 8). --- diff --git a/autogen.sh b/autogen.sh index 17b17bdc2..09e9b9f6e 100755 --- a/autogen.sh +++ b/autogen.sh @@ -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 diff --git a/components/checker/checkercomponent.cpp b/components/checker/checkercomponent.cpp index f260e94a0..e9136beb6 100644 --- a/components/checker/checkercomponent.cpp +++ b/components/checker/checkercomponent.cpp @@ -63,27 +63,26 @@ void CheckerComponent::CheckThreadProc(void) vector services; Service::Ptr service; - { - boost::mutex::scoped_lock lock(m_Mutex); + boost::mutex::scoped_lock lock(m_Mutex); - typedef nth_index::type CheckTimeView; - CheckTimeView& idx = boost::get<1>(m_IdleServices); + typedef nth_index::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::type CheckTimeView; - CheckTimeView& idx = boost::get<1>(m_IdleServices); + typedef nth_index::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); + + ObjectLock olock(service); /* required for the key extractor */ - /* remove and re-insert the service from the set in order to force an index update */ - typedef nth_index::type ServiceView; - ServiceView& idx = boost::get<0>(m_IdleServices); + /* remove and re-insert the service from the set in order to force an index update */ + typedef nth_index::type ServiceView; + ServiceView& idx = boost::get<0>(m_IdleServices); - ServiceView::iterator it = idx.find(service); - if (it == idx.end()) - return; + ServiceView::iterator it = idx.find(service); + if (it == idx.end()) + return; - idx.replace(it, service); - m_CV.notify_all(); - } + idx.erase(service); + idx.insert(service); + m_CV.notify_all(); } diff --git a/configure.ac b/configure.ac index f1bc33f51..386568fd2 100644 --- a/configure.ac +++ b/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 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.]) diff --git a/lib/base/Makefile.am b/lib/base/Makefile.am index 60ffcb8cc..721504a35 100644 --- a/lib/base/Makefile.am +++ b/lib/base/Makefile.am @@ -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 diff --git a/lib/base/application.cpp b/lib/base/application.cpp index 952b80c69..8cc0cc271 100644 --- a/lib/base/application.cpp +++ b/lib/base/application.cpp @@ -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; } diff --git a/lib/base/application.h b/lib/base/application.h index dd6679122..bfeb4ef53 100644 --- a/lib/base/application.h +++ b/lib/base/application.h @@ -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); diff --git a/lib/base/object.h b/lib/base/object.h index d898a0c3d..ce39a2b40 100644 --- a/lib/base/object.h +++ b/lib/base/object.h @@ -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; diff --git a/lib/config/Makefile.am b/lib/config/Makefile.am index 18ad41c77..796f0ba1c 100644 --- a/lib/config/Makefile.am +++ b/lib/config/Makefile.am @@ -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 + diff --git a/lib/icinga/Makefile.am b/lib/icinga/Makefile.am index 9e09a230c..7dc431874 100644 --- a/lib/icinga/Makefile.am +++ b/lib/icinga/Makefile.am @@ -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 + diff --git a/lib/icinga/service-check.cpp b/lib/icinga/service-check.cpp index 579d6b92b..3db70d3fd 100644 --- a/lib/icinga/service-check.cpp +++ b/lib/icinga/service-check.cpp @@ -506,6 +506,8 @@ void Service::CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo, * just in case there was no check result. */ UpdateNextCheck(); + olock.Unlock(); + callback(); } diff --git a/lib/python/Makefile.am b/lib/python/Makefile.am index d314d6968..36080d860 100644 --- a/lib/python/Makefile.am +++ b/lib/python/Makefile.am @@ -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 diff --git a/lib/remoting/Makefile.am b/lib/remoting/Makefile.am index 372dcca81..84e32b6fa 100644 --- a/lib/remoting/Makefile.am +++ b/lib/remoting/Makefile.am @@ -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 + diff --git a/libtool-pch.patch b/libtool-pch.patch new file mode 100644 index 000000000..2f1aac229 --- /dev/null +++ b/libtool-pch.patch @@ -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