summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2010-09-13 00:23:34 -0700
committerZac Medico <zmedico@gentoo.org>2010-09-13 00:23:34 -0700
commit58b184b441ff53c46cbb38eb695933d60c6624ad (patch)
tree21cbeaaf4a869b0f7ffba07cf5ae07d42695c1dd
parent46243c16a2538e494d5b98e6f0d3ec17ad80d1b7 (diff)
downloadportage-58b184b441ff53c46cbb38eb695933d60c6624ad.tar.gz
portage-58b184b441ff53c46cbb38eb695933d60c6624ad.tar.bz2
portage-58b184b441ff53c46cbb38eb695933d60c6624ad.zip
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.
-rw-r--r--pym/portage/dbapi/vartree.py34
-rw-r--r--pym/portage/locks.py4
2 files changed, 34 insertions, 4 deletions
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)