Esempio n. 1
0
  def create_cache_manager(self, invalidate_dependents, fingerprint_strategy=None):
    """Creates a cache manager that can be used to invalidate targets on behalf of this task.

    Use this if you need to check for invalid targets but can't use the contextmanager created by
    invalidated(), e.g., because you don't want to mark the targets as valid when done.

    invalidate_dependents:   If True then any targets depending on changed targets are invalidated.
    fingerprint_strategy:    A FingerprintStrategy instance, which can do per task, finer grained
                             fingerprinting of a given Target.
    """

    return InvalidationCacheManager(self._cache_key_generator,
                                    self._build_invalidator_dir,
                                    invalidate_dependents,
                                    fingerprint_strategy=fingerprint_strategy)
Esempio n. 2
0
 def __init__(self, tmpdir):
   InvalidationCacheManager.__init__(self, AppendingCacheKeyGenerator(), tmpdir, True, None)
Esempio n. 3
0
 def __init__(self, tmpdir):
     InvalidationCacheManager.__init__(self,
                                       AppendingCacheKeyGenerator(),
                                       tmpdir, True, None)
Esempio n. 4
0
  def invalidated(self, targets, only_buildfiles=False, invalidate_dependents=False,
                  partition_size_hint=sys.maxint, silent=False, locally_changed_targets=None):
    """Checks targets for invalidation, first checking the artifact cache.
    Subclasses call this to figure out what to work on.

    targets:                 The targets to check for changes.
    only_buildfiles:         If True, then only the target's BUILD files are checked for changes,
                             not its sources.
    invalidate_dependents:   If True then any targets depending on changed targets are invalidated.
    partition_size_hint:     Each VersionedTargetSet in the yielded list will represent targets
                             containing roughly this number of source files, if possible. Set to
                             sys.maxint for a single VersionedTargetSet. Set to 0 for one
                             VersionedTargetSet per target. It is up to the caller to do the right
                             thing with whatever partitioning it asks for.
    locally_changed_targets: Targets that we've edited locally. If specified, and there aren't too
                             many of them, we keep these in separate partitions from other targets,
                             as these are more likely to have build errors, and so to be rebuilt over
                             and over, and partitioning them separately is a performance win.

    Yields an InvalidationCheck object reflecting the (partitioned) targets.

    If no exceptions are thrown by work in the block, the build cache is updated for the targets.
    Note: the artifact cache is not updated. That must be done manually.
    """
    # TODO(benjy): Compute locally_changed_targets here instead of passing it in? We currently pass
    # it in because JvmCompile already has the source->target mapping for other reasons, and also
    # to selectively enable this feature.
    extra_data = [self.invalidate_for()]

    for f in self.invalidate_for_files():
      extra_data.append(hash_file(f))

    cache_manager = InvalidationCacheManager(self._cache_key_generator,
                                             self._build_invalidator_dir,
                                             invalidate_dependents,
                                             extra_data)

    # We separate locally-modified targets from others by coloring them differently.
    # This can be a performance win, because these targets are more likely to be iterated
    # over, and this preserves "chunk stability" for them.
    colors = {}

    # But we only do so if there aren't too many, or this optimization will backfire.
    locally_changed_target_limit = 10

    if locally_changed_targets and len(locally_changed_targets) < locally_changed_target_limit:
      for t in targets:
        if t in locally_changed_targets:
          colors[t] = 'locally_changed'
        else:
          colors[t] = 'not_locally_changed'
    invalidation_check = cache_manager.check(targets, partition_size_hint, colors)

    if invalidation_check.invalid_vts and self.artifact_cache_reads_enabled():
      with self.context.new_workunit('cache'):
        cached_vts, uncached_vts = \
          self.check_artifact_cache(self.check_artifact_cache_for(invalidation_check))
      if cached_vts:
        cached_targets = [vt.target for vt in cached_vts]
        for t in cached_targets:
          self.context.run_tracker.artifact_cache_stats.add_hit('default', t)
        if not silent:
          self._report_targets('Using cached artifacts for ', cached_targets, '.')
      if uncached_vts:
        uncached_targets = [vt.target for vt in uncached_vts]
        for t in uncached_targets:
          self.context.run_tracker.artifact_cache_stats.add_miss('default', t)
        if not silent:
          self._report_targets('No cached artifacts for ', uncached_targets, '.')
      # Now that we've checked the cache, re-partition whatever is still invalid.
      invalidation_check = \
        InvalidationCheck(invalidation_check.all_vts, uncached_vts, partition_size_hint, colors)

    if not silent:
      targets = []
      payloads = []
      num_invalid_partitions = len(invalidation_check.invalid_vts_partitioned)
      for vt in invalidation_check.invalid_vts_partitioned:
        targets.extend(vt.targets)
        payloads.extend(vt.cache_key.payloads)
      if len(targets):
        msg_elements = ['Invalidated ',
                        items_to_report_element([t.address.reference() for t in targets], 'target')]
        if len(payloads) > 0:
          msg_elements.append(' containing ')
          msg_elements.append(items_to_report_element(payloads, 'payload file'))
        if num_invalid_partitions > 1:
          msg_elements.append(' in %d target partitions' % num_invalid_partitions)
        msg_elements.append('.')
        self.context.log.info(*msg_elements)

    # Yield the result, and then mark the targets as up to date.
    yield invalidation_check
    for vt in invalidation_check.invalid_vts:
      vt.update()  # In case the caller doesn't update.