예제 #1
0
  public static ObjectTypeNode attachObjectTypeNode(BuildContext context, ObjectType objectType) {
    final InternalRuleBase ruleBase = context.getRuleBase();
    ruleBase.readLock();
    try {
      InternalWorkingMemory[] wms = context.getWorkingMemories();

      EntryPointNode epn = ruleBase.getRete().getEntryPointNode(context.getCurrentEntryPoint());
      if (epn == null) {
        epn = new EntryPointNode(context.getNextId(), ruleBase.getRete(), context);
        if (wms.length > 0) {
          epn.attach(wms);
        } else {
          epn.attach();
        }
      }

      ObjectTypeNode otn = new ObjectTypeNode(context.getNextId(), epn, objectType, context);

      long expirationOffset = getExpiratioOffsetForType(context, objectType);
      otn.setExpirationOffset(expirationOffset);

      if (wms.length > 0) {
        otn.attach(wms);
      } else {
        otn.attach();
      }

      return otn;
    } finally {
      ruleBase.readUnlock();
    }
  }
예제 #2
0
  /** @inheritDoc */
  public void build(
      final BuildContext context, final BuildUtils utils, final RuleConditionElement rce) {

    final Pattern pattern = (Pattern) rce;

    context.pushRuleComponent(pattern);
    this.attachPattern(context, utils, pattern);
    context.popRuleComponent();
  }
 CompilationUnit buildCompilationUnit(BuildContext file) {
   IJavaProject javaProject = JavaCore.create(file.getFile().getProject());
   ASTParser p = ASTParser.newParser(JavaConstants.AST_LEVEL);
   p.setProject(javaProject);
   p.setSource(file.getContents());
   p.setResolveBindings(true);
   p.setKind(ASTParser.K_COMPILATION_UNIT);
   p.setUnitName(file.getFile().getName());
   return (CompilationUnit) p.createAST(null);
 }
  @Override
  protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException {
    if (getProject() == null || !getProject().isAccessible()) return new IProject[0];

    List<BuildParticipant> participants = getBuildParticipants();
    List<BuildContext> contexts = getBuildContexts(kind);
    boolean isBatch = isBatch(kind);
    for (BuildParticipant buildParticipant : participants) {
      long start = System.currentTimeMillis();
      try {
        buildParticipant.buildStarting(contexts, isBatch, monitor);
      } catch (Exception e) {
        IdeLog.logError(AptanaCorePlugin.getDefault(), e.getMessage(), e);
      }
      if (DEBUG)
        System.out.println(
            "Took "
                + (System.currentTimeMillis() - start)
                + "ms for build participant: "
                + buildParticipant.getClass().getSimpleName());
    }
    while (!contexts.isEmpty()) {
      BuildContext context = contexts.remove(0);
      for (BuildParticipant buildParticipant : participants) {
        try {
          buildParticipant.build(context, monitor);
        } catch (Exception e) {
          IdeLog.logError(AptanaCorePlugin.getDefault(), e.getMessage(), e);
        }
      }
      cleanProblemMarkers(context);
      List<IProblem> problems = context.getRecordedProblems();
      if (problems.isEmpty()) continue;
      // Generate markers for each problem!
      for (IProblem problem : problems) {
        addMarker(context, problem);
      }
    }
    for (BuildParticipant buildParticipant : participants) {
      long start = System.currentTimeMillis();
      try {
        buildParticipant.buildFinishing(monitor);
      } catch (Exception e) {
        IdeLog.logError(AptanaCorePlugin.getDefault(), e.getMessage(), e);
      }
      if (DEBUG)
        System.out.println(
            "Took "
                + (System.currentTimeMillis() - start)
                + "ms for build participant: "
                + buildParticipant.getClass().getSimpleName());
    }
    return new IProject[0];
  }
예제 #5
0
  @Test
  public void testLogError() {
    BuckEventBus eventBus = BuckEventBusFactory.newInstance();
    CapturingConsoleEventListener listener = new CapturingConsoleEventListener();
    eventBus.register(listener);
    BuildContext buildContext =
        BuildContext.builder()
            .setActionGraph(createMock(ActionGraph.class))
            .setStepRunner(createMock(StepRunner.class))
            .setProjectFilesystem(createMock(ProjectFilesystem.class))
            .setArtifactCache(createMock(ArtifactCache.class))
            .setJavaPackageFinder(createMock(JavaPackageFinder.class))
            .setEventBus(eventBus)
            .build();

    buildContext.logError(new RuntimeException(), "Error detail: %s", "BUILD_ID");
    assertEquals(ImmutableList.of("Error detail: BUILD_ID"), listener.getLogMessages());
  }
예제 #6
0
 private boolean isNegative(final BuildContext context) {
   for (ListIterator<RuleConditionElement> it = context.stackIterator(); it.hasPrevious(); ) {
     RuleConditionElement rce = it.previous();
     if (rce instanceof GroupElement && ((GroupElement) rce).isNot()) {
       return true;
     }
   }
   return false;
 }
예제 #7
0
  @Test(expected = HumanReadableException.class)
  public void testGetAndroidBootclasspathSupplierWithoutAndroidPlatformTarget() {
    BuildContext.Builder builder = BuildContext.builder();

    // Set to non-null values.
    builder.setActionGraph(createMock(ActionGraph.class));
    builder.setStepRunner(createMock(StepRunner.class));
    builder.setProjectFilesystem(createMock(ProjectFilesystem.class));
    builder.setArtifactCache(createMock(ArtifactCache.class));
    builder.setJavaPackageFinder(createMock(JavaPackageFinder.class));
    builder.setEventBus(BuckEventBusFactory.newInstance());

    BuildContext context = builder.build();
    Supplier<String> androidBootclasspathSupplier = context.getAndroidBootclasspathSupplier();

    // If no AndroidPlatformTarget is passed to the builder, it should return a Supplier whose get()
    // method throws an exception.
    androidBootclasspathSupplier.get();
  }
 private void addMarker(BuildContext context, IProblem problem) throws CoreException {
   IMarker marker = context.getFile().createMarker(IAptanaModelMarker.PROBLEM_MARKER);
   Map<String, Object> attributes = new HashMap<String, Object>();
   attributes.put(IMarker.CHAR_START, problem.startOffset());
   attributes.put(IMarker.CHAR_END, problem.endOffset());
   attributes.put(IMarker.MESSAGE, problem.getMessage());
   attributes.put(IMarker.SEVERITY, problem.getSeverity());
   if (problem.lineNumber() > 0) attributes.put(IMarker.LINE_NUMBER, problem.lineNumber());
   attributes.put(IAptanaModelMarker.ID, problem.getId());
   marker.setAttributes(attributes);
 }
예제 #9
0
  /**
   * @param context
   * @param pattern
   * @param betaConstraints
   */
  private void checkRemoveIdentities(
      final BuildContext context, final Pattern pattern, final List<Constraint> betaConstraints) {
    if (context.getRuleBase().getConfiguration().isRemoveIdentities()
        && pattern.getObjectType().getClass() == ClassObjectType.class) {
      // Check if this object type exists before
      // If it does we need stop instance equals cross product
      final Class<?> thisClass = ((ClassObjectType) pattern.getObjectType()).getClassType();
      for (final Iterator<Pattern> it = context.getObjectType().iterator(); it.hasNext(); ) {
        final Pattern previousPattern = it.next();
        final Class<?> previousClass =
            ((ClassObjectType) previousPattern.getObjectType()).getClassType();
        if (thisClass.isAssignableFrom(previousClass)) {
          betaConstraints.add(new InstanceNotEqualsConstraint(previousPattern));
        }
      }

      // Must be added after the checking, otherwise it matches against itself
      context.getObjectType().add(pattern);
    }
  }
예제 #10
0
  @Test
  public void testGetAndroidBootclasspathSupplierWithAndroidPlatformTarget() {
    BuildContext.Builder builder = BuildContext.builder();

    // Set to non-null values.
    builder.setActionGraph(createMock(ActionGraph.class));
    builder.setStepRunner(createMock(StepRunner.class));
    builder.setProjectFilesystem(createMock(ProjectFilesystem.class));
    builder.setArtifactCache(createMock(ArtifactCache.class));
    builder.setJavaPackageFinder(createMock(JavaPackageFinder.class));
    builder.setEventBus(BuckEventBusFactory.newInstance());

    AndroidPlatformTarget androidPlatformTarget = createMock(AndroidPlatformTarget.class);
    List<Path> entries =
        ImmutableList.of(
            Paths.get("add-ons/addon-google_apis-google-15/libs/effects.jar"),
            Paths.get("add-ons/addon-google_apis-google-15/libs/maps.jar"),
            Paths.get("add-ons/addon-google_apis-google-15/libs/usb.jar"));
    expect(androidPlatformTarget.getBootclasspathEntries()).andReturn(entries);

    replay(androidPlatformTarget);

    builder.setAndroidBootclasspathForAndroidPlatformTarget(Optional.of(androidPlatformTarget));

    BuildContext context = builder.build();
    Supplier<String> androidBootclasspathSupplier = context.getAndroidBootclasspathSupplier();

    String androidBootclasspath =
        MorePaths.pathWithUnixSeparators(androidBootclasspathSupplier.get());
    assertEquals(
        "add-ons/addon-google_apis-google-15/libs/effects.jar:"
            + "add-ons/addon-google_apis-google-15/libs/maps.jar:"
            + "add-ons/addon-google_apis-google-15/libs/usb.jar",
        androidBootclasspath);

    // Call get() again to ensure that the underlying getBootclasspathEntries() is not called again
    // to verify that memoization is working as expected.
    androidBootclasspathSupplier.get();

    verify(androidPlatformTarget);
  }
예제 #11
0
 private static long getExpiratioOffsetForType(BuildContext context, ObjectType objectType) {
   long expirationOffset = -1;
   for (TypeDeclaration type : context.getRuleBase().getTypeDeclarations()) {
     if (type.getObjectType().isAssignableFrom(objectType)) {
       expirationOffset = Math.max(type.getExpirationOffset(), expirationOffset);
     }
   }
   // if none of the type declarations have an @expires annotation
   // we return -1 (no-expiration) value, otherwise we return the
   // set expiration value+1 to enable the fact to match events with
   // the same timestamp
   return expirationOffset == -1 ? -1 : expirationOffset + 1;
 }
예제 #12
0
  private void checkDelaying(final BuildContext context, final Constraint constraint) {
    if (constraint instanceof VariableConstraint) {
      // variable constraints always require a single declaration
      Declaration target = constraint.getRequiredDeclarations()[0];
      if (target.isPatternDeclaration() && target.getPattern().getObjectType().isEvent()) {
        long uplimit = ((VariableConstraint) constraint).getInterval().getUpperBound();

        Timer timer = context.getRule().getTimer();
        DurationTimer durationTimer = new DurationTimer(uplimit);

        if (timer instanceof CompositeMaxDurationTimer) {
          // already a composite so just add
          ((CompositeMaxDurationTimer) timer).addDurationTimer(durationTimer);
        } else {
          if (timer == null) {
            // no timer exists, so ok on it's own
            timer = durationTimer;
          } else {
            // timer exists so we need to make a composite
            CompositeMaxDurationTimer temp = new CompositeMaxDurationTimer();
            if (timer instanceof DurationTimer) {
              // previous timer was a duration, so add another DurationTimer
              temp.addDurationTimer((DurationTimer) timer);
            } else {
              // previous timer was not a duration, so set it as the delegate Timer.
              temp.setTimer(context.getRule().getTimer());
            }
            // now add the new durationTimer
            temp.addDurationTimer(durationTimer);
            timer = temp;
          }
          // with the composite made, reset it on the Rule
          context.getRule().setTimer(timer);
        }
      }
    }
  }
 @Override
 public <T> Template<T> loadTemplate(Type targetType) {
   // FIXME #MN must consider how to load "reference cycle class" in next
   // version
   Class<T> targetClass = (Class) targetType;
   // checkClassValidation(targetClass);
   try {
     // check loadable
     String tmplName = targetClass.getName() + "_$$_Template";
     ClassLoader cl = targetClass.getClassLoader();
     if (cl != null) {
       cl.loadClass(tmplName);
     } else {
       return null;
     }
   } catch (ClassNotFoundException e) {
     return null;
   }
   FieldOption implicitOption = getFieldOption(targetClass);
   FieldEntry[] entries = toFieldEntries(targetClass, implicitOption);
   Template<?>[] tmpls = toTemplate(entries);
   BuildContext bc = createBuildContext();
   return bc.loadTemplate(targetClass, entries, tmpls);
 }
예제 #14
0
  private void createConstraints(
      BuildContext context,
      BuildUtils utils,
      Pattern pattern,
      List<Constraint> alphaConstraints,
      List<Constraint> betaConstraints) {

    final List<?> constraints = pattern.getConstraints();

    // check if cross products for identity patterns should be disabled
    checkRemoveIdentities(context, pattern, betaConstraints);

    // checks if this pattern is nested inside a NOT CE
    final boolean isNegative = isNegative(context);

    for (final Iterator<?> it = constraints.iterator(); it.hasNext(); ) {
      final Object object = it.next();
      // Check if its a declaration
      if (object instanceof Declaration) {
        // nothing to be done
        continue;
      }

      final Constraint constraint = (Constraint) object;
      if (constraint.getType().equals(Constraint.ConstraintType.ALPHA)) {
        alphaConstraints.add(constraint);
      } else if (constraint.getType().equals(Constraint.ConstraintType.BETA)) {
        betaConstraints.add(constraint);
        if (isNegative
            && context.getRuleBase().getConfiguration().getEventProcessingMode()
                == EventProcessingOption.STREAM
            && pattern.getObjectType().isEvent()
            && constraint.isTemporal()) {
          checkDelaying(context, constraint);
        }
      } else {
        throw new RuntimeDroolsException(
            "Unknown constraint type: "
                + constraint.getType()
                + ". This is a bug. Please contact development team.");
      }
    }
  }
예제 #15
0
  private void executePostBuildSteps(
      BuildRule rule, Iterable<Step> postBuildSteps, BuildContext context)
      throws InterruptedException, StepFailedException {

    LOG.debug("Running post-build steps for %s", rule);

    StepRunner stepRunner = context.getStepRunner();
    Optional<BuildTarget> optionalTarget = Optional.of(rule.getBuildTarget());
    for (Step step : postBuildSteps) {
      stepRunner.runStepForBuildTarget(step, optionalTarget);

      // Check for interruptions that may have been ignored by step.
      if (Thread.interrupted()) {
        Thread.currentThread().interrupt();
        throw new InterruptedException();
      }
    }

    LOG.debug("Finished running post-build steps for %s", rule);
  }
예제 #16
0
  /**
   * Execute the commands for this build rule. Requires all dependent rules are already built
   * successfully.
   */
  private void executeCommandsNowThatDepsAreBuilt(
      BuildRule rule,
      BuildContext context,
      BuildableContext buildableContext,
      BuildInfoRecorder buildInfoRecorder)
      throws InterruptedException, StepFailedException {

    LOG.debug("Building locally: %s", rule);
    // Attempt to get an approximation of how long it takes to actually run the command.
    @SuppressWarnings("PMD.PrematureDeclaration")
    long start = System.nanoTime();

    // Get and run all of the commands.
    List<Step> steps = rule.getBuildSteps(context, buildableContext);

    AbiRule abiRule = checkIfRuleOrBuildableIsAbiRule(rule);
    if (abiRule != null) {
      buildInfoRecorder.addBuildMetadata(
          ABI_KEY_FOR_DEPS_ON_DISK_METADATA, abiRule.getAbiKeyForDeps().getHash());
    }

    StepRunner stepRunner = context.getStepRunner();
    Optional<BuildTarget> optionalTarget = Optional.of(rule.getBuildTarget());
    for (Step step : steps) {
      stepRunner.runStepForBuildTarget(step, optionalTarget);

      // Check for interruptions that may have been ignored by step.
      if (Thread.interrupted()) {
        Thread.currentThread().interrupt();
        throw new InterruptedException();
      }
    }

    long end = System.nanoTime();
    LOG.debug(
        "Build completed: %s %s (%dns)", rule.getType(), rule.getFullyQualifiedName(), end - start);
  }
예제 #17
0
  static RuleTerminalNode buildTerminalNodeForNamedConsequence(
      BuildContext context, NamedConsequence namedConsequence) {
    RuleImpl rule = context.getRule();
    GroupElement subrule = (GroupElement) context.peek();

    ActivationListenerFactory factory =
        context
            .getKnowledgeBase()
            .getConfiguration()
            .getActivationListenerFactory(rule.getActivationListener());

    context.setConsequenceName(namedConsequence.getConsequenceName());
    TerminalNode terminal =
        factory.createActivationListener(
            context.getNextId(),
            context.getTupleSource(),
            rule,
            subrule,
            0, // subruleIndex,
            context);
    context.setConsequenceName(null);

    return (RuleTerminalNode) terminal;
  }
예제 #18
0
  public void build(BuildContext context, BuildUtils utils, RuleConditionElement rce) {
    NamedConsequence namedConsequence = (NamedConsequence) rce;

    Timer timer = context.getRule().getTimer();
    if (timer != null) {
      ReteooComponentBuilder builder = utils.getBuilderFor(Timer.class);
      builder.build(context, utils, context.getRule().getTimer());
    }

    RuleTerminalNode terminalNode = buildTerminalNodeForNamedConsequence(context, namedConsequence);

    terminalNode.attach(context);

    terminalNode.networkUpdated(new UpdateContext());

    // adds the terminal node to the list of nodes created/added by this sub-rule
    context.getNodes().add(terminalNode);

    if (timer != null) {
      context.setTupleSource(context.getTupleSource().getLeftTupleSource());
    }

    context.setTerminated(namedConsequence.isTerminal());
  }
 private void writeTemplate(Class<?> targetClass, FieldEntry[] entries, String directoryName) {
   Template[] tmpls = toTemplate(entries);
   BuildContext bc = createBuildContext();
   bc.writeTemplate(targetClass, entries, tmpls, directoryName);
 }
 @Override
 public <T> Template<T> buildTemplate(Class<T> targetClass, FieldEntry[] entries) {
   Template<?>[] tmpls = toTemplate(entries);
   BuildContext bc = createBuildContext();
   return bc.buildTemplate(targetClass, entries, tmpls);
 }
예제 #21
0
  private ListenableFuture<BuildResult> processBuildRule(
      final BuildRule rule,
      final BuildContext context,
      ConcurrentLinkedQueue<ListenableFuture<Void>> asyncCallbacks)
      throws InterruptedException {

    // Log to the event bus.
    context.getEventBus().logVerboseAndPost(LOG, BuildRuleEvent.resumed(rule));

    final OnDiskBuildInfo onDiskBuildInfo = context.createOnDiskBuildInfoFor(rule.getBuildTarget());
    final BuildInfoRecorder buildInfoRecorder =
        context
            .createBuildInfoRecorder(rule.getBuildTarget())
            .addBuildMetadata(BuildInfo.METADATA_KEY_FOR_RULE_KEY, rule.getRuleKey().toString())
            .addBuildMetadata(
                BuildInfo.METADATA_KEY_FOR_RULE_KEY_WITHOUT_DEPS,
                rule.getRuleKeyWithoutDeps().toString());
    final BuildableContext buildableContext = new DefaultBuildableContext(buildInfoRecorder);

    // Dispatch the build job for this rule.
    ListenableFuture<BuildResult> buildResult =
        processBuildRule(
            rule, context, onDiskBuildInfo, buildInfoRecorder, buildableContext, asyncCallbacks);

    // If we're performing a deep build, guarantee that all dependencies will *always* get
    // materialized locally by chaining up to our result future.
    if (buildMode == BuildMode.DEEP) {
      buildResult =
          MoreFutures.chainExceptions(getDepResults(rule, context, asyncCallbacks), buildResult);
    }

    // Setup a callback to handle either the cached or built locally cases.
    AsyncFunction<BuildResult, BuildResult> callback =
        new AsyncFunction<BuildResult, BuildResult>() {
          @Override
          public ListenableFuture<BuildResult> apply(@Nonnull BuildResult input) throws Exception {

            // If we weren't successful, exit now.
            if (input.getStatus() != BuildRuleStatus.SUCCESS) {
              return Futures.immediateFuture(input);
            }

            // We shouldn't see any build fail result at this point.
            BuildRuleSuccessType success = Preconditions.checkNotNull(input.getSuccess());

            // If we didn't build the rule locally, reload the recorded paths from the build
            // metadata.
            if (success != BuildRuleSuccessType.BUILT_LOCALLY) {
              for (String str :
                  onDiskBuildInfo.getValues(BuildInfo.METADATA_KEY_FOR_RECORDED_PATHS).get()) {
                buildInfoRecorder.recordArtifact(Paths.get(str));
              }
            }

            // If the success type means the rule has potentially changed it's outputs...
            if (success.outputsHaveChanged()) {

              // The build has succeeded, whether we've fetched from cache, or built locally.
              // So run the post-build steps.
              if (rule instanceof HasPostBuildSteps) {
                executePostBuildSteps(
                    rule,
                    ((HasPostBuildSteps) rule).getPostBuildSteps(context, buildableContext),
                    context);
              }

              // Invalidate any cached hashes for the output paths, since we've updated them.
              for (Path path : buildInfoRecorder.getRecordedPaths()) {
                fileHashCache.invalidate(path);
              }
            }

            // If this rule uses dep files and we built locally, make sure we store the new dep file
            // list and re-calculate the dep file rule key.
            if (useDependencyFileRuleKey(rule) && success == BuildRuleSuccessType.BUILT_LOCALLY) {

              // Query the rule for the actual inputs it used, and verify these are relative.
              ImmutableList<Path> inputs =
                  ((SupportsDependencyFileRuleKey) rule).getInputsAfterBuildingLocally();
              for (Path path : inputs) {
                Preconditions.checkState(
                    !path.isAbsolute(),
                    String.format(
                        "%s: reported absolute path as an input: %s", rule.getBuildTarget(), path));
              }

              // Record the inputs into our metadata for next time.
              ImmutableList<String> inputStrings =
                  FluentIterable.from(inputs).transform(Functions.toStringFunction()).toList();
              buildInfoRecorder.addMetadata(BuildInfo.METADATA_KEY_FOR_DEP_FILE, inputStrings);

              // Re-calculate and store the depfile rule key for next time.
              Optional<RuleKey> depFileRuleKey =
                  calculateDepFileRuleKey(
                      rule, Optional.of(inputStrings), /* allowMissingInputs */ false);
              Preconditions.checkState(depFileRuleKey.isPresent());
              buildInfoRecorder.addBuildMetadata(
                  BuildInfo.METADATA_KEY_FOR_DEP_FILE_RULE_KEY, depFileRuleKey.get().toString());
            }

            // Make sure that all of the local files have the same values they would as if the
            // rule had been built locally.
            buildInfoRecorder.addBuildMetadata(
                BuildInfo.METADATA_KEY_FOR_TARGET, rule.getBuildTarget().toString());
            buildInfoRecorder.addMetadata(
                BuildInfo.METADATA_KEY_FOR_RECORDED_PATHS,
                FluentIterable.from(buildInfoRecorder.getRecordedPaths())
                    .transform(Functions.toStringFunction()));
            if (success.shouldWriteRecordedMetadataToDiskAfterBuilding()) {
              try {
                boolean clearExistingMetadata = success.shouldClearAndOverwriteMetadataOnDisk();
                buildInfoRecorder.writeMetadataToDisk(clearExistingMetadata);
              } catch (IOException e) {
                throw new IOException(
                    String.format("Failed to write metadata to disk for %s.", rule), e);
              }
            }

            // Give the rule a chance to populate its internal data structures now that all of
            // the files should be in a valid state.
            try {
              if (rule instanceof InitializableFromDisk) {
                doInitializeFromDisk((InitializableFromDisk<?>) rule, onDiskBuildInfo);
              }
            } catch (IOException e) {
              throw new IOException(String.format("Error initializing %s from disk.", rule), e);
            }

            return Futures.immediateFuture(input);
          }
        };
    buildResult = Futures.transform(buildResult, callback);

    // Handle either build success or failure.
    final SettableFuture<BuildResult> result = SettableFuture.create();
    asyncCallbacks.add(
        MoreFutures.addListenableCallback(
            buildResult,
            new FutureCallback<BuildResult>() {

              // TODO(mbolin): Delete all files produced by the rule, as they are not guaranteed
              // to be valid at this point?
              private void cleanupAfterError() {
                try {
                  onDiskBuildInfo.deleteExistingMetadata();
                } catch (Throwable t) {
                  context
                      .getEventBus()
                      .post(
                          ThrowableConsoleEvent.create(
                              t, "Error when deleting metadata for %s.", rule));
                }
              }

              private void uploadToCache(BuildRuleSuccessType success) {

                // Collect up all the rule keys we have index the artifact in the cache with.
                Set<RuleKey> ruleKeys = Sets.newHashSet();

                // If the rule key has changed (and is not already in the cache), we need to push
                // the artifact to cache using the new key.
                if (success.shouldUploadResultingArtifact()) {
                  ruleKeys.add(rule.getRuleKey());
                }

                // If the input-based rule key has changed, we need to push the artifact to cache
                // using the new key.
                if (rule instanceof SupportsInputBasedRuleKey
                    && success.shouldUploadResultingArtifactInputBased()) {
                  ruleKeys.add(
                      onDiskBuildInfo
                          .getRuleKey(BuildInfo.METADATA_KEY_FOR_INPUT_BASED_RULE_KEY)
                          .get());
                }

                // If we have any rule keys to push to the cache with, do the upload now.
                if (!ruleKeys.isEmpty()) {
                  try {
                    buildInfoRecorder.performUploadToArtifactCache(
                        ImmutableSet.copyOf(ruleKeys),
                        context.getArtifactCache(),
                        context.getEventBus());
                  } catch (Throwable t) {
                    context
                        .getEventBus()
                        .post(
                            ThrowableConsoleEvent.create(
                                t, "Error uploading to cache for %s.", rule));
                  }
                }
              }

              private void handleResult(BuildResult input) {
                Optional<Long> outputSize = Optional.absent();
                Optional<HashCode> outputHash = Optional.absent();
                Optional<BuildRuleSuccessType> successType = Optional.absent();

                if (input.getStatus() == BuildRuleStatus.FAIL) {

                  // Make this failure visible for other rules, so that they can stop early.
                  firstFailure = input.getFailure();

                  // If we failed, cleanup the state of this rule.
                  cleanupAfterError();
                }

                // Unblock dependents.
                result.set(input);

                if (input.getStatus() == BuildRuleStatus.SUCCESS) {
                  BuildRuleSuccessType success = Preconditions.checkNotNull(input.getSuccess());
                  successType = Optional.of(success);
                  uploadToCache(success);

                  // Calculate the hash and size of the rule outputs.
                  try {
                    outputSize = Optional.of(buildInfoRecorder.getOutputSize());
                    outputHash = Optional.of(buildInfoRecorder.getOutputHash(fileHashCache));
                  } catch (IOException e) {
                    context
                        .getEventBus()
                        .post(
                            ThrowableConsoleEvent.create(
                                e, "Error getting output hash and size for %s.", rule));
                  }
                }

                // Log the result to the event bus.
                context
                    .getEventBus()
                    .logVerboseAndPost(
                        LOG,
                        BuildRuleEvent.finished(
                            rule,
                            input.getStatus(),
                            input.getCacheResult(),
                            successType,
                            outputHash,
                            outputSize));
              }

              @Override
              public void onSuccess(BuildResult input) {
                handleResult(input);
              }

              @Override
              public void onFailure(@Nonnull Throwable thrown) {
                handleResult(BuildResult.failure(rule, thrown));

                // Reset interrupted flag once failure has been recorded.
                if (thrown instanceof InterruptedException) {
                  Thread.currentThread().interrupt();
                }
              }
            }));
    return result;
  }
예제 #22
0
  private ListenableFuture<BuildResult> processBuildRule(
      final BuildRule rule,
      final BuildContext context,
      final OnDiskBuildInfo onDiskBuildInfo,
      final BuildInfoRecorder buildInfoRecorder,
      final BuildableContext buildableContext,
      ConcurrentLinkedQueue<ListenableFuture<Void>> asyncCallbacks)
      throws InterruptedException {

    // If we've already seen a failure, exit early.
    if (!context.isKeepGoing() && firstFailure != null) {
      return Futures.immediateFuture(BuildResult.canceled(rule, firstFailure));
    }

    // 1. Check if it's already built.
    Optional<RuleKey> cachedRuleKey =
        onDiskBuildInfo.getRuleKey(BuildInfo.METADATA_KEY_FOR_RULE_KEY);
    if (cachedRuleKey.isPresent() && rule.getRuleKey().equals(cachedRuleKey.get())) {
      return Futures.immediateFuture(
          BuildResult.success(
              rule, BuildRuleSuccessType.MATCHING_RULE_KEY, CacheResult.localKeyUnchangedHit()));
    }

    // 2. Rule key cache lookup.
    final CacheResult cacheResult =
        tryToFetchArtifactFromBuildCacheAndOverlayOnTopOfProjectFilesystem(
            rule,
            rule.getRuleKey(),
            buildInfoRecorder,
            context.getArtifactCache(),
            context.getProjectFilesystem(),
            context);
    if (cacheResult.getType().isSuccess()) {
      return Futures.immediateFuture(
          BuildResult.success(rule, BuildRuleSuccessType.FETCHED_FROM_CACHE, cacheResult));
    }

    // Log to the event bus.
    context.getEventBus().logVerboseAndPost(LOG, BuildRuleEvent.suspended(rule));

    // 3. Build deps.
    return Futures.transform(
        getDepResults(rule, context, asyncCallbacks),
        new AsyncFunction<List<BuildResult>, BuildResult>() {
          @Override
          public ListenableFuture<BuildResult> apply(@Nonnull List<BuildResult> depResults)
              throws Exception {

            // Log to the event bus.
            context.getEventBus().logVerboseAndPost(LOG, BuildRuleEvent.resumed(rule));

            // If any dependency wasn't successful, cancel ourselves.
            for (BuildResult depResult : depResults) {
              if (depResult.getStatus() != BuildRuleStatus.SUCCESS) {
                return Futures.immediateFuture(
                    BuildResult.canceled(rule, Preconditions.checkNotNull(depResult.getFailure())));
              }
            }

            // If we've already seen a failure, exit early.
            if (!context.isKeepGoing() && firstFailure != null) {
              return Futures.immediateFuture(BuildResult.canceled(rule, firstFailure));
            }

            // Dep-file rule keys.
            if (useDependencyFileRuleKey(rule)) {

              // Try to get the current dep-file rule key.
              Optional<RuleKey> depFileRuleKey =
                  calculateDepFileRuleKey(
                      rule,
                      onDiskBuildInfo.getValues(BuildInfo.METADATA_KEY_FOR_DEP_FILE),
                      /* allowMissingInputs */ true);
              if (depFileRuleKey.isPresent()) {

                // Check the input-based rule key says we're already built.
                Optional<RuleKey> lastDepFileRuleKey =
                    onDiskBuildInfo.getRuleKey(BuildInfo.METADATA_KEY_FOR_DEP_FILE_RULE_KEY);
                if (lastDepFileRuleKey.isPresent()
                    && lastDepFileRuleKey.get().equals(depFileRuleKey.get())) {
                  return Futures.immediateFuture(
                      BuildResult.success(
                          rule,
                          BuildRuleSuccessType.MATCHING_DEP_FILE_RULE_KEY,
                          CacheResult.localKeyUnchangedHit()));
                }
              }
            }

            // Input-based rule keys.
            if (rule instanceof SupportsInputBasedRuleKey) {

              // Calculate the input-based rule key and record it in the metadata.
              RuleKey inputRuleKey = inputBasedRuleKeyBuilderFactory.newInstance(rule).build();
              buildInfoRecorder.addBuildMetadata(
                  BuildInfo.METADATA_KEY_FOR_INPUT_BASED_RULE_KEY, inputRuleKey.toString());

              // Check the input-based rule key says we're already built.
              Optional<RuleKey> lastInputRuleKey =
                  onDiskBuildInfo.getRuleKey(BuildInfo.METADATA_KEY_FOR_INPUT_BASED_RULE_KEY);
              if (lastInputRuleKey.isPresent() && lastInputRuleKey.get().equals(inputRuleKey)) {
                return Futures.immediateFuture(
                    BuildResult.success(
                        rule,
                        BuildRuleSuccessType.MATCHING_INPUT_BASED_RULE_KEY,
                        CacheResult.localKeyUnchangedHit()));
              }

              // Try to fetch the artifact using the input-based rule key.
              CacheResult cacheResult =
                  tryToFetchArtifactFromBuildCacheAndOverlayOnTopOfProjectFilesystem(
                      rule,
                      inputRuleKey,
                      buildInfoRecorder,
                      context.getArtifactCache(),
                      context.getProjectFilesystem(),
                      context);
              if (cacheResult.getType().isSuccess()) {
                return Futures.immediateFuture(
                    BuildResult.success(
                        rule, BuildRuleSuccessType.FETCHED_FROM_CACHE_INPUT_BASED, cacheResult));
              }
            }

            // 4. ABI check
            // Deciding whether we need to rebuild is tricky business. We want to rebuild as little
            // as possible while always being sound.
            //
            // For java_library rules that depend only on their first-order deps,
            // they only need to rebuild themselves if any of the following conditions hold:
            // (1) The definition of the build rule has changed.
            // (2) Any of the input files (which includes resources as well as .java files) have
            //     changed.
            // (3) The ABI of any of its dependent java_library rules has changed.
            //
            // For other types of build rules, we have to be more conservative when rebuilding. In
            // those cases, we rebuild if any of the following conditions hold:
            // (1) The definition of the build rule has changed.
            // (2) Any of the input files have changed.
            // (3) Any of the RuleKeys of this rule's deps have changed.
            //
            // Because a RuleKey for a rule will change if any of its transitive deps have changed,
            // that means a change in one of the leaves can result in almost all rules being
            // rebuilt, which is slow. Fortunately, we limit the effects of this when building Java
            // code when checking the ABI of deps instead of the RuleKey for deps.
            AbiRule abiRule = checkIfRuleOrBuildableIsAbiRule(rule);
            if (abiRule != null) {
              RuleKey ruleKeyNoDeps = rule.getRuleKeyWithoutDeps();
              Optional<RuleKey> cachedRuleKeyNoDeps =
                  onDiskBuildInfo.getRuleKey(BuildInfo.METADATA_KEY_FOR_RULE_KEY_WITHOUT_DEPS);
              if (ruleKeyNoDeps.equals(cachedRuleKeyNoDeps.orNull())) {
                // The RuleKey for the definition of this build rule and its input files has not
                // changed.  Therefore, if the ABI of its deps has not changed, there is nothing to
                // rebuild.
                Sha1HashCode abiKeyForDeps = abiRule.getAbiKeyForDeps();
                Optional<Sha1HashCode> cachedAbiKeyForDeps =
                    onDiskBuildInfo.getHash(ABI_KEY_FOR_DEPS_ON_DISK_METADATA);
                if (abiKeyForDeps.equals(cachedAbiKeyForDeps.orNull())) {
                  return Futures.immediateFuture(
                      BuildResult.success(
                          rule,
                          BuildRuleSuccessType.MATCHING_DEPS_ABI_AND_RULE_KEY_NO_DEPS,
                          AbstractCacheResult.localKeyUnchangedHit()));
                }
              }
            }

            // 5. build the rule
            executeCommandsNowThatDepsAreBuilt(rule, context, buildableContext, buildInfoRecorder);

            return Futures.immediateFuture(
                BuildResult.success(rule, BuildRuleSuccessType.BUILT_LOCALLY, cacheResult));
          }
        },
        service);
  }
예제 #23
0
  private void attachPattern(
      final BuildContext context, final BuildUtils utils, final Pattern pattern)
      throws InvalidPatternException {

    // Set pattern offset to the appropriate value
    pattern.setOffset(context.getCurrentPatternOffset());

    final List<Constraint> alphaConstraints = new LinkedList<Constraint>();
    final List<Constraint> betaConstraints = new LinkedList<Constraint>();
    final List<Behavior> behaviors = new LinkedList<Behavior>();

    this.createConstraints(context, utils, pattern, alphaConstraints, betaConstraints);

    // Create BetaConstraints object
    context.setBetaconstraints(betaConstraints);

    // set behaviors list
    behaviors.addAll(pattern.getBehaviors());
    context.setBehaviors(behaviors);

    if (pattern.getSource() != null) {
      context.setAlphaConstraints(alphaConstraints);
      final int currentOffset = context.getCurrentPatternOffset();

      PatternSource source = pattern.getSource();

      ReteooComponentBuilder builder = utils.getBuilderFor(source);

      builder.build(context, utils, source);
      // restoring offset
      context.setCurrentPatternOffset(currentOffset);
    }

    if (pattern.getSource() == null || context.getCurrentEntryPoint() != EntryPoint.DEFAULT) {
      attachAlphaNodes(context, utils, pattern, alphaConstraints);

      if (context.getCurrentEntryPoint() != EntryPoint.DEFAULT) {
        context.setObjectSource(
            (ObjectSource)
                utils.attachNode(
                    context,
                    new PropagationQueuingNode(
                        context.getNextId(), context.getObjectSource(), context)));
        // the entry-point specific network nodes are attached, so, set context to default
        // entry-point
        context.setCurrentEntryPoint(EntryPoint.DEFAULT);
      }
    }

    // last thing to do is increment the offset, since if the pattern has a source,
    // offset must be overriden
    context.incrementCurrentPatternOffset();
  }
예제 #24
0
 private void cleanProblemMarkers(BuildContext context) throws CoreException {
   if (context != null && context.getFile() != null)
     context
         .getFile()
         .deleteMarkers(IAptanaModelMarker.PROBLEM_MARKER, false, IResource.DEPTH_ONE);
 }
예제 #25
0
  public void attachAlphaNodes(
      final BuildContext context,
      final BuildUtils utils,
      final Pattern pattern,
      List<Constraint> alphaConstraints)
      throws InvalidPatternException {

    // Drools Query ObjectTypeNode never has memory, but other ObjectTypeNode/AlphaNoesNodes may (if
    // not in sequential),
    // so need to preserve, so we can restore after this node is added. LeftMemory  and Terminal
    // remain the same once set.

    boolean objectMemory = context.isObjectTypeNodeMemoryEnabled();
    boolean alphaMemory = context.isAlphaMemoryAllowed();

    ObjectType objectType = pattern.getObjectType();

    if (pattern.getObjectType() instanceof ClassObjectType) {
      // Is this the query node, if so we don't want any memory
      if (DroolsQuery.class == ((ClassObjectType) pattern.getObjectType()).getClassType()) {
        context.setTupleMemoryEnabled(false);
        context.setObjectTypeNodeMemoryEnabled(false);
        context.setTerminalNodeMemoryEnabled(false);
        context.setAlphaNodeMemoryAllowed(false);
      }
    }

    context.setObjectSource(
        (ObjectSource)
            utils.attachNode(
                context,
                new EntryPointNode(context.getNextId(), context.getRuleBase().getRete(), context)));

    ObjectTypeNode otn =
        new ObjectTypeNode(
            context.getNextId(), (EntryPointNode) context.getObjectSource(), objectType, context);
    if (objectType.isEvent()
        && EventProcessingOption.STREAM.equals(
            context.getRuleBase().getConfiguration().getEventProcessingMode())) {
      long expirationOffset = getExpiratioOffsetForType(context, objectType);
      if (expirationOffset != -1) {
        // expiration policy is set, so use it
        otn.setExpirationOffset(expirationOffset);
      } else {
        // otherwise calculate it based on behaviours and temporal constraints
        for (Behavior behavior : pattern.getBehaviors()) {
          if (behavior.getExpirationOffset() != -1) {
            expirationOffset = Math.max(behavior.getExpirationOffset(), expirationOffset);
          }
        }
        long distance = context.getTemporalDistance().getExpirationOffset(pattern);
        if (distance == -1) {
          // it means the rules have no temporal constraints, or
          // the constraints require events to be hold forever. In this
          // case, we allow type declarations to override the implicit
          // expiration offset by defining an expiration policy with the
          // @expires tag
          otn.setExpirationOffset(expirationOffset);
        } else {
          otn.setExpirationOffset(Math.max(distance, expirationOffset));
        }
      }
    }

    context.setObjectSource((ObjectSource) utils.attachNode(context, otn));

    for (final Iterator<Constraint> it = alphaConstraints.iterator(); it.hasNext(); ) {
      final AlphaNodeFieldConstraint constraint = (AlphaNodeFieldConstraint) it.next();

      context.pushRuleComponent(constraint);
      context.setObjectSource(
          (ObjectSource)
              utils.attachNode(
                  context,
                  new AlphaNode(
                      context.getNextId(),
                      (AlphaNodeFieldConstraint) constraint,
                      context.getObjectSource(),
                      context)));
      context.popRuleComponent();
    }

    // now restore back to original values
    context.setObjectTypeNodeMemoryEnabled(objectMemory);
    context.setAlphaNodeMemoryAllowed(alphaMemory);
  }
예제 #26
0
  /* (non-Javadoc)
   * @see org.kie.reteoo.builder.ReteooComponentBuilder#build(org.kie.reteoo.builder.BuildContext, org.kie.reteoo.builder.BuildUtils, org.kie.rule.RuleConditionElement)
   */
  public void build(
      final BuildContext context, final BuildUtils utils, final RuleConditionElement rce) {
    final From from = (From) rce;
    context.pushRuleComponent(from);

    @SuppressWarnings("unchecked")
    BetaConstraints betaConstraints =
        utils.createBetaNodeConstraint(
            context, (List<BetaNodeFieldConstraint>) context.getBetaconstraints(), true);

    context.setTupleSource(
        (LeftTupleSource)
            utils.attachNode(
                context,
                context
                    .getComponentFactory()
                    .getNodeFactoryService()
                    .buildFromNode(
                        context.getNextId(),
                        from.getDataProvider(),
                        context.getTupleSource(),
                        context
                            .getAlphaConstraints()
                            .toArray(
                                new AlphaNodeFieldConstraint[context.getAlphaConstraints().size()]),
                        betaConstraints,
                        context.isTupleMemoryEnabled(),
                        context,
                        from)));
    context.setAlphaConstraints(null);
    context.setBetaconstraints(null);
    context.popRuleComponent();
  }
예제 #27
0
  private CacheResult tryToFetchArtifactFromBuildCacheAndOverlayOnTopOfProjectFilesystem(
      BuildRule rule,
      RuleKey ruleKey,
      BuildInfoRecorder buildInfoRecorder,
      ArtifactCache artifactCache,
      ProjectFilesystem filesystem,
      BuildContext buildContext)
      throws InterruptedException {

    // Create a temp file whose extension must be ".zip" for Filesystems.newFileSystem() to infer
    // that we are creating a zip-based FileSystem.
    Path zipFile;
    try {
      zipFile =
          Files.createTempFile(
              "buck_artifact_" + MoreFiles.sanitize(rule.getBuildTarget().getShortName()), ".zip");
    } catch (IOException e) {
      throw new RuntimeException(e);
    }

    // TODO(mbolin): Change ArtifactCache.fetch() so that it returns a File instead of takes one.
    // Then we could download directly from the remote cache into the on-disk cache and unzip it
    // from there.
    CacheResult cacheResult =
        buildInfoRecorder.fetchArtifactForBuildable(ruleKey, zipFile, artifactCache);
    if (!cacheResult.getType().isSuccess()) {
      try {
        Files.delete(zipFile);
      } catch (IOException e) {
        LOG.warn(e, "failed to delete %s", zipFile);
      }
      return cacheResult;
    }

    // We unzip the file in the root of the project directory.
    // Ideally, the following would work:
    //
    // Path pathToZip = Paths.get(zipFile.getAbsolutePath());
    // FileSystem fs = FileSystems.newFileSystem(pathToZip, /* loader */ null);
    // Path root = Iterables.getOnlyElement(fs.getRootDirectories());
    // MoreFiles.copyRecursively(root, projectRoot);
    //
    // Unfortunately, this does not appear to work, in practice, because MoreFiles fails when trying
    // to resolve a Path for a zip entry against a file Path on disk.
    ArtifactCacheEvent.Started started =
        ArtifactCacheEvent.started(
            ArtifactCacheEvent.Operation.DECOMPRESS, ImmutableSet.of(ruleKey));
    buildContext.getEventBus().post(started);
    try {
      Unzip.extractZipFile(
          zipFile.toAbsolutePath(),
          filesystem,
          Unzip.ExistingFileMode.OVERWRITE_AND_CLEAN_DIRECTORIES);

      // We only delete the ZIP file when it has been unzipped successfully. Otherwise, we leave it
      // around for debugging purposes.
      Files.delete(zipFile);

      if (cacheResult.getType() == CacheResult.Type.HIT) {

        // If we have a hit, also write out the build metadata.
        Path metadataDir = BuildInfo.getPathToMetadataDirectory(rule.getBuildTarget());
        for (Map.Entry<String, String> ent : cacheResult.getMetadata().entrySet()) {
          Path dest = metadataDir.resolve(ent.getKey());
          filesystem.createParentDirs(dest);
          filesystem.writeContentsToPath(ent.getValue(), dest);
        }
      }

    } catch (IOException e) {
      // In the wild, we have seen some inexplicable failures during this step. For now, we try to
      // give the user as much information as we can to debug the issue, but return CacheResult.MISS
      // so that Buck will fall back on doing a local build.
      buildContext
          .getEventBus()
          .post(
              ConsoleEvent.warning(
                  "Failed to unzip the artifact for %s at %s.\n"
                      + "The rule will be built locally, "
                      + "but here is the stacktrace of the failed unzip call:\n"
                      + rule.getBuildTarget(),
                  zipFile.toAbsolutePath(),
                  Throwables.getStackTraceAsString(e)));
      return CacheResult.miss();
    } finally {
      buildContext.getEventBus().post(ArtifactCacheEvent.finished(started));
    }

    return cacheResult;
  }