Dan Kenigsberg has uploaded a new change for review. Change subject: Factor betterThreading out of Vdsm ......................................................................
Factor betterThreading out of Vdsm Recently, I've spun-off betterThreading as http://pypi.python.org/pypi/pthreading and have placed it in Fedora https://admin.fedoraproject.org/pkgdb/acls/name/python-pthreading . I believe that other complex multi-threading Python2 applications running on Linux would benefit from python-threading. Let us use it instead of containing it. Change-Id: I9353f393050cea3b1811bc6f778eb23f0849ccc2 Signed-off-by: Dan Kenigsberg <[email protected]> --- M tests/Makefile.am D tests/betterThreadingTests.py M vdsm.spec.in M vdsm/Makefile.am D vdsm/betterThreading.py M vdsm/vdsm 6 files changed, 3 insertions(+), 345 deletions(-) git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/86/7886/1 diff --git a/tests/Makefile.am b/tests/Makefile.am index ef10237..1ac017b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -23,7 +23,6 @@ test_modules = \ alignmentScanTests.py \ betterPopenTests.py \ - betterThreadingTests.py \ capsTests.py \ configNetworkTests.py \ fileUtilTests.py \ diff --git a/tests/betterThreadingTests.py b/tests/betterThreadingTests.py deleted file mode 100644 index 0e2d989..0000000 --- a/tests/betterThreadingTests.py +++ /dev/null @@ -1,229 +0,0 @@ -# -# Copyright 2012 Red Hat, Inc. -# -# 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 Street, Fifth Floor, Boston, MA 02110-1301 USA -# -# Refer to the README and COPYING files for full details of the license -# -import threading -from time import sleep - -from testrunner import VdsmTestCase as TestCaseBase -import betterThreading - - -def getTweakedEvent(): - # use betterThreading.Event if exposed. Newer Vdsm only has the - # monkey-patched threading.Event - try: - return betterThreading.Event() - except AttributeError: - return threading.Event() - - -class LockTests(TestCaseBase): - def _testAcquire(self, lock): - self.assertTrue(lock.acquire()) - - def _testRelease(self, lock): - lock.acquire() - lock.release() - self.assertTrue(lock.acquire(False)) - - def testAcquireLock(self): - self._testAcquire(betterThreading.Lock()) - - def testAcquireRLock(self): - self._testAcquire(betterThreading.RLock()) - - def testReleaseLock(self): - self._testRelease(betterThreading.Lock()) - - def testReleaseRLock(self): - self._testRelease(betterThreading.RLock()) - - def testAcquireNonblocking(self): - lock = betterThreading.Lock() - lock.acquire() - self.assertFalse(lock.acquire(False)) - - def testAcquireRecursive(self): - lock = betterThreading.RLock() - self.assertTrue(lock.acquire()) - self.assertTrue(lock.acquire(False)) - - -class Flag(object): - def __init__(self): - self._flag = False - - def __nonzero__(self): - return self._flag - - def set(self): - self._flag = True - - def clear(self): - self._flag = False - - -class ConditionTests(TestCaseBase): - def testBaseTest(self, lock=None, timeout=None): - """ - Base Condition exerciser - """ - flag = Flag() - c = betterThreading.Condition(lock) - - def setter(flag): - sleep(2) - with c: - flag.set() - c.notify() - threading.Thread(target=setter, args=(flag,)).start() - with c: - while not flag: - self.log.debug("main waits") - c.wait(timeout) - - self.assertTrue(flag) - - def testNotifyAll(self, lock=None): - """ - Exercise Condition.notifyAll() - """ - flag = Flag() - c = betterThreading.Condition(lock) - - def setter(flag): - sleep(2) - with c: - flag.set() - c.notifyAll() - threading.Thread(target=setter, args=(flag,)).start() - with c: - while not flag: - c.wait() - - self.assertTrue(flag) - - def testXWait(self, lock=None): - """ - Exercise Condition.wait() with 1s timeout that never become true - """ - self.log.info("Creating Condition object") - flag = Flag() - c = betterThreading.Condition(lock) - tired = 0 - with c: - while not flag and tired < 5: - self.log.debug("main waits") - c.wait(1) - tired = 5 - - self.assertFalse(flag) - - def testNotify(self): - """ - Exercise Condition.notify() - """ - self.testBaseTest() - - def testWaitIntegerTimeout(self): - """ - Exercise Condition.wait() with 1s timeout - """ - self.testBaseTest(timeout=1) - - def testWaitFloatTimeout(self): - """ - Exercise Condition.wait() with 0.3s timeout (fraction of a second) - """ - self.testBaseTest(timeout=0.3) - - def testNotifyWithUserProvidedLock(self): - """ - Exercise Condition.notify() - """ - self.testBaseTest(lock=betterThreading.Lock()) - - def testWaitIntegerTimeoutWithUserProvidedLock(self): - """ - Exercise Condition.wait() with 1s timeout - """ - self.testBaseTest(lock=betterThreading.Lock(), timeout=1) - - def testWaitFloatTimeoutWithUserProvidedLock(self): - """ - Exercise Condition.wait() with 0.3s timeout (fraction of a second) - """ - self.testBaseTest(lock=betterThreading.Lock(), timeout=0.3) - - def testNotifyWithUserProvidedRLock(self): - """ - Exercise Condition.notify() - """ - self.testBaseTest(lock=betterThreading.RLock()) - - def testWaitIntegerTimeoutWithUserProvidedRLock(self): - """ - Exercise Condition.wait() with 1s timeout - """ - self.testBaseTest(lock=betterThreading.RLock(), timeout=1) - - def testWaitFloatTimeoutWithUserProvidedRLock(self): - """ - Exercise Condition.wait() with 0.3s timeout (fraction of a second) - """ - self.testBaseTest(lock=betterThreading.RLock(), timeout=0.3) - - -class EventTests(TestCaseBase): - def _test(self, timeout): - self.log.info("Creating Event object") - e = getTweakedEvent() - - def setter(): - self.log.info("Setter thread is sleeping") - sleep(2) - self.log.info("Setter thread is setting") - e.set() - self.log.info("Event object is set (%s) :D", e.is_set()) - - self.log.info("Starting setter thread") - threading.Thread(target=setter).start() - self.log.info("Waiting for salvation") - res = e.wait(timeout) - self.assertTrue(res is not False) - - def testPassWithTimeout(self): - self._test(5) - - def testPassWithoutTimeout(self): - self._test(None) - - def testNotPassTimeout(self): - self.log.info("Creating Event object") - e = getTweakedEvent() - self.log.info("Waiting for salvation (That will never come)") - res = e.wait(0.5) - self.assertFalse(res) - - def testZeroTimeout(self): - self.log.info("Creating Event object") - e = getTweakedEvent() - self.log.info("Waiting 0 for salvation (That will never come)") - res = e.wait(0) - self.assertFalse(res) diff --git a/vdsm.spec.in b/vdsm.spec.in index bb6730e..b023269 100644 --- a/vdsm.spec.in +++ b/vdsm.spec.in @@ -49,6 +49,7 @@ Requires: python-ethtool Requires: nfs-utils dmidecode Requires: lvm2 >= 2.02.95 +Requires: python-pthreading %if 0%{?rhel} Requires: python @@ -592,7 +593,6 @@ %{_datadir}/%{vdsm_name}/logUtils.py* %{_datadir}/%{vdsm_name}/dsaversion.py* %{_datadir}/%{vdsm_name}/pthread.py* -%{_datadir}/%{vdsm_name}/betterThreading.py* %{_libexecdir}/%{vdsm_name}/persist-vdsm-hooks %{_libexecdir}/%{vdsm_name}/unpersist-vdsm-hook %{_libexecdir}/%{vdsm_name}/ovirt_functions.sh diff --git a/vdsm/Makefile.am b/vdsm/Makefile.am index 96c8a56..b7d17ba 100644 --- a/vdsm/Makefile.am +++ b/vdsm/Makefile.am @@ -25,7 +25,6 @@ dist_vdsm_PYTHON = \ alignmentScan.py \ API.py \ - betterThreading.py \ BindingXMLRPC.py \ blkid.py \ caps.py \ diff --git a/vdsm/betterThreading.py b/vdsm/betterThreading.py deleted file mode 100644 index 93fdd91..0000000 --- a/vdsm/betterThreading.py +++ /dev/null @@ -1,112 +0,0 @@ -# -# Copyright 2011 Red Hat, Inc. -# -# 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 Street, Fifth Floor, Boston, MA 02110-1301 USA -# -# Refer to the README and COPYING files for full details of the license -# - -""" -betterThreading module provides Lock and Condition synchronization -objects compatible with Python native threading module. -The implementation, however, is based on POSIX thread library as delivered -by the libpthread. Lock and Condition are designed to be a drop-in -replacement for their respective threading counterpart. -""" - -import time -import errno -import os - -import pthread - -class Lock(pthread.PthreadMutex): - """ - Lock class mimics Python native threading.Lock() API on top of - the POSIX thread mutex synchronization primitive. - """ - def __enter__(self): - self.acquire() - return self - - def __exit__(self, exc_type, exc_value, traceback): - self.release() - - def acquire(self, blocking=True): - - rc = self.lock() if blocking else self.trylock() - - if rc == 0: - return True - elif rc == errno.EBUSY: - return False - else: - raise OSError(rc, os.strerror(rc)) - - def release(self): - self.unlock() - - -class RLock(Lock): - def __init__(self): - pthread.PthreadMutex.__init__(self, recursive=True) - - -class Condition(object): - """ - Condition class mimics Python native threading.Condition() API - on top of the POSIX thread conditional variable synchronization - primitive. - """ - def __init__(self, lock=None): - self.__lock = lock if lock else Lock() - self.__cond = pthread.PthreadCond(mutex=self.__lock) - # Export the lock's acquire() and release() methods - self.acquire = self.__lock.acquire - self.release = self.__lock.release - - def __enter__(self): - return self.__lock.__enter__() - - def __exit__(self, *args): - return self.__lock.__exit__(*args) - - def wait(self, timeout=None): - if timeout is not None: - bailout = time.time() + timeout - abstime = pthread.timespec() - abstime.tv_sec = int(bailout) - abstime.tv_nsec = int((bailout - int(bailout)) * (10**9)) - return self.__cond.timedwait(abstime) - else: - return self.__cond.wait() - - def notify(self): - return self.__cond.signal() - - def notifyAll(self): - return self.__cond.broadcast() - - notify_all = notifyAll - - -# hack threading module to use our classes, so that Queue and SocketServer can -# easily enjoy them. - -import threading - -threading.Condition = Condition -threading.Lock = Lock -threading.RLock = RLock diff --git a/vdsm/vdsm b/vdsm/vdsm index e48d478..cc02d72 100755 --- a/vdsm/vdsm +++ b/vdsm/vdsm @@ -16,7 +16,8 @@ from vdsm import constants import dsaversion -import betterThreading # before threading is ever used +import pthreading +pthreading.monkey_patch() # before threading is ever used loggerConfFile = constants.P_VDSM_CONF + 'logger.conf' -- To view, visit http://gerrit.ovirt.org/7886 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I9353f393050cea3b1811bc6f778eb23f0849ccc2 Gerrit-PatchSet: 1 Gerrit-Project: vdsm Gerrit-Branch: master Gerrit-Owner: Dan Kenigsberg <[email protected]> _______________________________________________ vdsm-patches mailing list [email protected] https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches
