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 # It will be a dictionary of {deps_name: {"deps_file": depfile_name}} or
# None. # None.
self.recursedeps = 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: if not self.name and self.parent:
raise gclient_utils.Error('Dependency without name') raise gclient_utils.Error('Dependency without name')

@ -784,6 +784,7 @@ class WorkItem(object):
self._name = name self._name = name
self.outbuf = cStringIO.StringIO() self.outbuf = cStringIO.StringIO()
self.start = self.finish = None self.start = self.finish = None
self.resources = [] # List of resources this work item requires.
def run(self, work_queue): def run(self, work_queue):
"""work_queue is passed as keyword argument so it should be """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()) 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): def flush(self, *args, **kwargs):
"""Runs all enqueued items until all are executed.""" """Runs all enqueued items until all are executed."""
kwargs['work_queue'] = self kwargs['work_queue'] = self
@ -892,6 +902,7 @@ class ExecutionQueue(object):
# Verify its requirements. # Verify its requirements.
if (self.ignore_requirements or if (self.ignore_requirements or
not (set(self.queued[i].requirements) - set(self.ran))): not (set(self.queued[i].requirements) - set(self.ran))):
if not self._is_conflict(self.queued[i]):
# Start one work item: all its requirements are satisfied. # Start one work item: all its requirements are satisfied.
self._run_one_task(self.queued.pop(i), args, kwargs) self._run_one_task(self.queued.pop(i), args, kwargs)
break break

Loading…
Cancel
Save