Add resource locking in gclient

There are entries in the DEPS file where two folders uses the same
git URL (ie. freetype2).  This doesn't work well with git caches because
each task will run on it's own and might try to clobber on top of each other.

This adds another field in a WorkItem which is a list of resources.  When the
work queue is flushed, it has to make sure that none of a newly added workitem
has any resource conflicts.

BUG=618124

Review-Url: https://codereview.chromium.org/2049583003
changes/50/351450/1
hinoka 9 years ago committed by Commit bot
parent e9013dbe6f
commit 885e5b1ee2

@ -375,6 +375,11 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
# It will be a dictionary of {deps_name: {"deps_file": depfile_name}} or
# None.
self.recursedeps = None
# This is inherited from WorkItem. We want the URL to be a resource.
if url and isinstance(url, basestring):
# The url is usually given to gclient either as https://blah@123
# or just https://blah. The @123 portion is irrelevent.
self.resources.append(url.split('@')[0])
if not self.name and self.parent:
raise gclient_utils.Error('Dependency without name')

@ -784,6 +784,7 @@ class WorkItem(object):
self._name = name
self.outbuf = cStringIO.StringIO()
self.start = self.finish = None
self.resources = [] # List of resources this work item requires.
def run(self, work_queue):
"""work_queue is passed as keyword argument so it should be
@ -869,6 +870,15 @@ class ExecutionQueue(object):
----------------------------------------""" % (
task.name, comment, elapsed, task.outbuf.getvalue().strip())
def _is_conflict(self, job):
"""Checks to see if a job will conflict with another running job."""
for running_job in self.running:
for used_resource in running_job.item.resources:
logging.debug('Checking resource %s' % used_resource)
if used_resource in job.resources:
return True
return False
def flush(self, *args, **kwargs):
"""Runs all enqueued items until all are executed."""
kwargs['work_queue'] = self
@ -892,9 +902,10 @@ class ExecutionQueue(object):
# Verify its requirements.
if (self.ignore_requirements or
not (set(self.queued[i].requirements) - set(self.ran))):
# Start one work item: all its requirements are satisfied.
self._run_one_task(self.queued.pop(i), args, kwargs)
break
if not self._is_conflict(self.queued[i]):
# Start one work item: all its requirements are satisfied.
self._run_one_task(self.queued.pop(i), args, kwargs)
break
else:
# Couldn't find an item that could run. Break out the outher loop.
break

Loading…
Cancel
Save