From 58b184b441ff53c46cbb38eb695933d60c6624ad Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Mon, 13 Sep 2010 00:23:34 -0700 Subject: Bug #336142 - Add support for using a thread to wait for locks inside dblink.lockdb() so that the scheduler can concurrently service ipc calls in the main thread. --- pym/portage/dbapi/vartree.py | 34 ++++++++++++++++++++++++++++++++-- pym/portage/locks.py | 4 ++-- 2 files changed, 34 insertions(+), 4 deletions(-) (limited to 'pym') diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index fddb4326c..19ebaaa76 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -37,7 +37,7 @@ from portage.const import _ENABLE_DYN_LINK_MAP, _ENABLE_PRESERVE_LIBS from portage.dbapi import dbapi from portage.exception import CommandNotFound, \ InvalidData, InvalidPackageName, \ - FileNotFound, PermissionDenied, UnsupportedAPIException + FileNotFound, PermissionDenied, TryAgain, UnsupportedAPIException from portage.localization import _ from portage.util.movefile import movefile @@ -62,6 +62,10 @@ import os as _os import stat import sys import tempfile +try: + import threading +except ImportError: + import dummy_threading as threading import time import warnings @@ -1276,13 +1280,39 @@ class dblink(object): raise AssertionError("Lock already held.") # At least the parent needs to exist for the lock file. ensure_dirs(self.dbroot) - self._lock_vdb = lockdir(self.dbroot) + if self._scheduler is None: + self._lock_vdb = lockdir(self.dbroot) + else: + try: + self._lock_vdb = lockdir(self.dbroot, flags=os.O_NONBLOCK) + except TryAgain: + self._lockdb_rlock = threading.RLock() + lockdb_thread = threading.Thread( + target=self._lockdb_thread) + lockdb_thread.start() + if not self._lockdb_have_lock(): + self._scheduler.schedule( + condition=self._lockdb_have_lock) + lockdb_thread.join() + self._lockdb_rlock = None def unlockdb(self): if self._lock_vdb: unlockdir(self._lock_vdb) self._lock_vdb = None + def _lockdb_thread(self): + lock_vdb = lockdir(self.dbroot) + self._lockdb_rlock.acquire() + self._lock_vdb = lock_vdb + self._lockdb_rlock.release() + + def _lockdb_have_lock(self): + self._lockdb_rlock.acquire() + rval = self._lock_vdb is not None + self._lockdb_rlock.release() + return rval + def getpath(self): "return path to location of db information (for >>> informational display)" return self.dbdir diff --git a/pym/portage/locks.py b/pym/portage/locks.py index ed20e30ca..00a50b818 100644 --- a/pym/portage/locks.py +++ b/pym/portage/locks.py @@ -30,8 +30,8 @@ HARDLINK_FD = -2 # so that it doesn't interfere with the status display. _quiet = False -def lockdir(mydir): - return lockfile(mydir,wantnewlockfile=1) +def lockdir(mydir, flags=0): + return lockfile(mydir, wantnewlockfile=1, flags=flags) def unlockdir(mylock): return unlockfile(mylock) -- cgit v1.2.3-1-g7c22