From 354e3edebebbdb23007db0e4af2dd294fecd570b Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Thu, 3 Jul 2008 22:48:21 +0000 Subject: Bug #230469 - Implement non-blocking distlocks for --fetchonly. This adds a "flags" keyword parameter to the portage.locks.lock() function. Default is flags=0. If flags contains os.O_NONBLOCK then lock() will raise portage.exception.TryAgain instead of blocking. This new flags parameter is used to implement non-blocking distlocks in fetch() when fetchonly mode is enabled. svn path=/main/trunk/; revision=10917 --- pym/portage/__init__.py | 26 +++++++++++++++++++------- pym/portage/exception.py | 4 ++++ pym/portage/locks.py | 13 +++++++++---- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 9859e0f5e..6aa4d2664 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -3512,15 +3512,27 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks", from textwrap import wrap waiting_msg = "\n".join(msg_prefix + line \ for line in wrap(waiting_msg, 65)) + if locks_in_subdir: - file_lock = portage.locks.lockfile( - os.path.join(mysettings["DISTDIR"], - locks_in_subdir, myfile), wantnewlockfile=1, - waiting_msg=waiting_msg) + lock_file = os.path.join(mysettings["DISTDIR"], + locks_in_subdir, myfile) + else: + lock_file = myfile_path + + lock_kwargs = {} + if fetchonly: + lock_kwargs["flags"] = os.O_NONBLOCK else: - file_lock = portage.locks.lockfile( - myfile_path, wantnewlockfile=1, - waiting_msg=waiting_msg) + lock_kwargs["waiting_msg"] = waiting_msg + + try: + file_lock = portage.locks.lockfile(myfile_path, + wantnewlockfile=1, **lock_kwargs) + except portage.exception.TryAgain: + writemsg((">>> File '%s' is already locked by " + \ + "another fetcher. Continuing...\n") % myfile, + noiselevel=-1) + continue try: if not listonly: diff --git a/pym/portage/exception.py b/pym/portage/exception.py index d91584b73..66cd16244 100644 --- a/pym/portage/exception.py +++ b/pym/portage/exception.py @@ -57,6 +57,10 @@ class PermissionDenied(PortageException): from errno import EACCES as errno """Permission denied""" +class TryAgain(PortageException): + from errno import EAGAIN as errno + """Try again""" + class ReadOnlyFileSystem(PortageException): """Read-only file system""" diff --git a/pym/portage/locks.py b/pym/portage/locks.py index 004108eb7..000cd3495 100644 --- a/pym/portage/locks.py +++ b/pym/portage/locks.py @@ -5,7 +5,8 @@ import errno, os, stat, time, types -from portage.exception import InvalidData, DirectoryNotFound, FileNotFound +from portage.exception import DirectoryNotFound, FileNotFound, \ + InvalidData, TryAgain from portage.data import portage_gid from portage.util import writemsg from portage.localization import _ @@ -17,7 +18,8 @@ def lockdir(mydir): def unlockdir(mylock): return unlockfile(mylock) -def lockfile(mypath, wantnewlockfile=0, unlinkfile=0, waiting_msg=None): +def lockfile(mypath, wantnewlockfile=0, unlinkfile=0, + waiting_msg=None, flags=0): """Creates all dirs upto, the given dir. Creates a lockfile for the given directory as the file: directoryname+'.portage_lockfile'.""" import fcntl @@ -54,7 +56,8 @@ def lockfile(mypath, wantnewlockfile=0, unlinkfile=0, waiting_msg=None): except OSError, e: if e[0] == 2: # No such file or directory return lockfile(mypath, wantnewlockfile=wantnewlockfile, - unlinkfile=unlinkfile, waiting_msg=waiting_msg) + unlinkfile=unlinkfile, waiting_msg=waiting_msg, + flags=flags) else: writemsg("Cannot chown a lockfile. This could cause inconvenience later.\n"); os.umask(old_mask) @@ -78,6 +81,8 @@ def lockfile(mypath, wantnewlockfile=0, unlinkfile=0, waiting_msg=None): raise if e.errno in (errno.EACCES, errno.EAGAIN): # resource temp unavailable; eg, someone beat us to the lock. + if flags & os.O_NONBLOCK: + raise TryAgain(mypath) if waiting_msg is None: if isinstance(mypath, int): print "waiting for lock on fd %i" % myfd @@ -114,7 +119,7 @@ def lockfile(mypath, wantnewlockfile=0, unlinkfile=0, waiting_msg=None): writemsg("lockfile recurse\n",1) lockfilename, myfd, unlinkfile, locking_method = lockfile( mypath, wantnewlockfile=wantnewlockfile, unlinkfile=unlinkfile, - waiting_msg=waiting_msg) + waiting_msg=waiting_msg, flags=flags) writemsg(str((lockfilename,myfd,unlinkfile))+"\n",1) return (lockfilename,myfd,unlinkfile,locking_method) -- cgit v1.2.3-1-g7c22