Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(920)

Unified Diff: git_cache.py

Issue 1650993005: Allow blocking git-cache update with a timeout. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: nit Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gclient_scm.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: git_cache.py
diff --git a/git_cache.py b/git_cache.py
index 9f835b5ffc144d8c6753c70585c09cea2250002b..9137ef5f58e27cc95a0e0a701693d61af364cba4 100755
--- a/git_cache.py
+++ b/git_cache.py
@@ -44,8 +44,9 @@ class RefsHeadsFailedToFetch(Exception):
class Lockfile(object):
"""Class to represent a cross-platform process-specific lockfile."""
- def __init__(self, path):
+ def __init__(self, path, timeout=0):
self.path = os.path.abspath(path)
+ self.timeout = timeout
self.lockfile = self.path + ".lock"
self.pid = os.getpid()
@@ -91,16 +92,26 @@ class Lockfile(object):
def lock(self):
"""Acquire the lock.
- Note: This is a NON-BLOCKING FAIL-FAST operation.
- Do. Or do not. There is no try.
+ This will block with a deadline of self.timeout seconds.
+ If self.timeout is zero, this is a NON-BLOCKING FAIL-FAST operation.
"""
- try:
- self._make_lockfile()
- except OSError as e:
- if e.errno == errno.EEXIST:
- raise LockError("%s is already locked" % self.path)
- else:
- raise LockError("Failed to create %s (err %s)" % (self.path, e.errno))
+ elapsed = 0
+ while True:
+ try:
+ self._make_lockfile()
+ return
+ except OSError as e:
+ if elapsed < self.timeout:
+ sleep_time = min(3, self.timeout - elapsed)
+ logging.info('Could not create git cache lockfile; '
+ 'will retry after sleep(%d).', sleep_time);
+ elapsed += sleep_time
+ time.sleep(sleep_time)
+ continue
+ if e.errno == errno.EEXIST:
+ raise LockError("%s is already locked" % self.path)
+ else:
+ raise LockError("Failed to create %s (err %s)" % (self.path, e.errno))
def unlock(self):
"""Release the lock."""
@@ -401,13 +412,13 @@ class Mirror(object):
logging.warn('Fetch of %s failed' % spec)
def populate(self, depth=None, shallow=False, bootstrap=False,
- verbose=False, ignore_lock=False):
+ verbose=False, ignore_lock=False, lock_timeout=0):
assert self.GetCachePath()
if shallow and not depth:
depth = 10000
gclient_utils.safe_makedirs(self.GetCachePath())
- lockfile = Lockfile(self.mirror_path)
+ lockfile = Lockfile(self.mirror_path, lock_timeout)
if not ignore_lock:
lockfile.lock()
@@ -582,6 +593,7 @@ def CMDpopulate(parser, args):
'shallow': options.shallow,
'bootstrap': not options.no_bootstrap,
'ignore_lock': options.ignore_locks,
+ 'lock_timeout': options.timeout,
}
if options.depth:
kwargs['depth'] = options.depth
@@ -625,7 +637,8 @@ def CMDfetch(parser, args):
git_dir = os.path.abspath(git_dir)
if git_dir.startswith(cachepath):
mirror = Mirror.FromPath(git_dir)
- mirror.populate(bootstrap=not options.no_bootstrap)
+ mirror.populate(
+ bootstrap=not options.no_bootstrap, lock_timeout=options.timeout)
return 0
for remote in remotes:
remote_url = subprocess.check_output(
@@ -634,7 +647,8 @@ def CMDfetch(parser, args):
mirror = Mirror.FromPath(remote_url)
mirror.print = lambda *args: None
print('Updating git cache...')
- mirror.populate(bootstrap=not options.no_bootstrap)
+ mirror.populate(
+ bootstrap=not options.no_bootstrap, lock_timeout=options.timeout)
subprocess.check_call([Mirror.git_exe, 'fetch', remote])
return 0
@@ -683,6 +697,8 @@ class OptionParser(optparse.OptionParser):
help='Increase verbosity (can be passed multiple times)')
self.add_option('-q', '--quiet', action='store_true',
help='Suppress all extraneous output')
+ self.add_option('--timeout', type='int', default=0,
+ help='Timeout for acquiring cache lock, in seconds')
def parse_args(self, args=None, values=None):
options, args = optparse.OptionParser.parse_args(self, args, values)
« no previous file with comments | « gclient_scm.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698