summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico2011-12-14 05:59:59 (GMT)
committerZac Medico2011-12-14 05:59:59 (GMT)
commit3bcbe6b069687855fa3cc8f0e39be6c240ee3e3e (patch)
tree7fcbb9983aea62dbb96d8a9a296e141fc0339abe
parent7bcb8e14d52c51904d42ccb1df49f481df2be9dd (diff)
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.py71
1 files changed, 41 insertions, 30 deletions
diff --git a/pym/portage/locks.py b/pym/portage/locks.py
index 980c1c7..59026e9 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)