diff options
author | Zac Medico <zmedico@gentoo.org> | 2011-12-13 21:59:59 -0800 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2011-12-13 21:59:59 -0800 |
commit | 3bcbe6b069687855fa3cc8f0e39be6c240ee3e3e (patch) | |
tree | 7fcbb9983aea62dbb96d8a9a296e141fc0339abe | |
parent | 7bcb8e14d52c51904d42ccb1df49f481df2be9dd (diff) | |
download | portage-3bcbe6b069687855fa3cc8f0e39be6c240ee3e3e.tar.gz portage-3bcbe6b069687855fa3cc8f0e39be6c240ee3e3e.tar.bz2 portage-3bcbe6b069687855fa3cc8f0e39be6c240ee3e3e.zip |
hardlink_lockfile: optimize away most link calls
If fstat shows more than one hardlink, then it's extremely unlikely
that the following link call will result in a lock, so optimize away
the wasteful link call and sleep or raise TryAgain.
-rw-r--r-- | pym/portage/locks.py | 71 |
1 files changed, 41 insertions, 30 deletions
diff --git a/pym/portage/locks.py b/pym/portage/locks.py index 980c1c762..59026e90a 100644 --- a/pym/portage/locks.py +++ b/pym/portage/locks.py @@ -337,8 +337,10 @@ def hardlink_lockfile(lockfilename, max_wait=DeprecationWarning, else: raise else: + myfd_st = None try: - if os.fstat(myfd).st_gid != portage_gid: + myfd_st = os.fstat(myfd) + if myfd_st.st_gid != portage_gid: os.fchown(myfd, -1, portage_gid) except OSError as e: if e.errno not in (errno.ENOENT, errno.ESTALE): @@ -349,38 +351,47 @@ def hardlink_lockfile(lockfilename, max_wait=DeprecationWarning, writemsg(_("Group IDs of current user: %s\n") % \ " ".join(str(n) for n in os.getgroups()), noiselevel=-1) + else: + # another process has removed the file, so we'll have + # to create it again + continue finally: os.close(myfd) - try: - os.link(lockfilename, myhardlock) - except OSError as e: - func_call = "link('%s', '%s')" % (lockfilename, myhardlock) - if e.errno == OperationNotPermitted.errno: - raise OperationNotPermitted(func_call) - elif e.errno == PermissionDenied.errno: - raise PermissionDenied(func_call) - elif e.errno in (errno.ESTALE, errno.ENOENT): - # another process has removed the file, so we'll have - # to create it again - continue - else: - raise - - if hardlink_is_mine(myhardlock, lockfilename): - if out is not None: - out.eend(os.EX_OK) - break - - try: - os.unlink(myhardlock) - except OSError as e: - # This should not happen, since the file name of - # myhardlock is unique to our host and PID, - # and the above link() call succeeded. - if e.errno not in (errno.ENOENT, errno.ESTALE): - raise - raise FileNotFound(myhardlock) + # If fstat shows more than one hardlink, then it's extremely + # unlikely that the following link call will result in a lock, + # so optimize away the wasteful link call and sleep or raise + # TryAgain. + if myfd_st is not None and myfd_st.st_nlink < 2: + try: + os.link(lockfilename, myhardlock) + except OSError as e: + func_call = "link('%s', '%s')" % (lockfilename, myhardlock) + if e.errno == OperationNotPermitted.errno: + raise OperationNotPermitted(func_call) + elif e.errno == PermissionDenied.errno: + raise PermissionDenied(func_call) + elif e.errno in (errno.ESTALE, errno.ENOENT): + # another process has removed the file, so we'll have + # to create it again + continue + else: + raise + else: + if hardlink_is_mine(myhardlock, lockfilename): + if out is not None: + out.eend(os.EX_OK) + break + + try: + os.unlink(myhardlock) + except OSError as e: + # This should not happen, since the file name of + # myhardlock is unique to our host and PID, + # and the above link() call succeeded. + if e.errno not in (errno.ENOENT, errno.ESTALE): + raise + raise FileNotFound(myhardlock) if flags & os.O_NONBLOCK: raise TryAgain(lockfilename) |