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(); } }
/** @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]; }
@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()); }
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; }
@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); }
/** * @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); } }
@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); }
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; }
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); }
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."); } } }
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); }
/** * 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); }
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; }
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); }
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; }
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); }
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(); }
private void cleanProblemMarkers(BuildContext context) throws CoreException { if (context != null && context.getFile() != null) context .getFile() .deleteMarkers(IAptanaModelMarker.PROBLEM_MARKER, false, IResource.DEPTH_ONE); }
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); }
/* (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(); }
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; }