// Copyright 2014 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.devtools.build.lib.skyframe; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Interner; import com.google.devtools.build.lib.actions.ActionAnalysisMetadata; import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory; import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory.BuildInfoKey; import com.google.devtools.build.lib.concurrent.BlazeInterners; import com.google.devtools.build.lib.packages.RuleVisibility; import com.google.devtools.build.lib.pkgcache.PathPackageLocator; import com.google.devtools.build.lib.skyframe.SkyframeActionExecutor.ConflictException; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.syntax.SkylarkSemantics; import com.google.devtools.build.skyframe.AbstractSkyKey; import com.google.devtools.build.skyframe.Injectable; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionName; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import java.util.Map; import java.util.UUID; import javax.annotation.Nullable; /** * A value that represents something computed outside of the skyframe framework. These values are * "precomputed" from skyframe's perspective and so the graph needs to be prepopulated with them * (e.g. via injection). */ @AutoCodec public final class PrecomputedValue implements SkyValue { /** * An externally-injected precomputed value. Exists so that modules can inject precomputed values * into Skyframe's graph. * * @see com.google.devtools.build.lib.runtime.BlazeModule#getPrecomputedValues */ public static final class Injected { private final Precomputed precomputed; private final Supplier supplier; private Injected(Precomputed precomputed, Supplier supplier) { this.precomputed = precomputed; this.supplier = supplier; } public void inject(Injectable injectable) { injectable.inject(precomputed.key, new PrecomputedValue(supplier.get())); } @Override public String toString() { return precomputed + ": " + supplier.get(); } } public static Injected injected(Precomputed precomputed, Supplier value) { return new Injected(precomputed, value); } public static Injected injected(Precomputed precomputed, T value) { return new Injected(precomputed, Suppliers.ofInstance(value)); } public static final Precomputed ENABLE_DEFAULTS_PACKAGE = new Precomputed<>(Key.create("enable_default_pkg")); // TODO(dbabkin): better to move this code to PrecomputedValueUtils. // It will gone soon after removing tools/defaults public static boolean isInMemoryToolsDefaults(SkyFunction.Environment env) throws InterruptedException { Boolean enableDefaultsPackage = PrecomputedValue.ENABLE_DEFAULTS_PACKAGE.get(env); return Preconditions.checkNotNull(enableDefaultsPackage); } public static final Precomputed DEFAULTS_PACKAGE_CONTENTS = new Precomputed<>(Key.create("default_pkg")); public static final Precomputed DEFAULT_VISIBILITY = new Precomputed<>(Key.create("default_visibility")); public static final Precomputed SKYLARK_SEMANTICS = new Precomputed<>(Key.create("skylark_semantics")); static final Precomputed BUILD_ID = new Precomputed<>(Key.create("build_id")); public static final Precomputed> ACTION_ENV = new Precomputed<>(Key.create("action_env")); static final Precomputed> COVERAGE_REPORT_KEY = new Precomputed<>(Key.create("coverage_report_actions")); public static final Precomputed> BUILD_INFO_FACTORIES = new Precomputed<>(Key.create("build_info_factories")); static final Precomputed> BAD_ACTIONS = new Precomputed<>(Key.create("bad_actions")); public static final Precomputed PATH_PACKAGE_LOCATOR = new Precomputed<>(Key.create("path_package_locator")); private final Object value; @AutoCodec.Instantiator public PrecomputedValue(Object value) { this.value = Preconditions.checkNotNull(value); } /** * Returns the value of the variable. */ public Object get() { return value; } @Override public int hashCode() { return value.hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof PrecomputedValue)) { return false; } PrecomputedValue other = (PrecomputedValue) obj; return value.equals(other.value); } @Override public String toString() { return ""; } public static void dependOnBuildId(SkyFunction.Environment env) throws InterruptedException { BUILD_ID.get(env); } /** * A helper object corresponding to a variable in Skyframe. * *

Instances do not have internal state. */ public static final class Precomputed { private final Key key; public Precomputed(Key key) { this.key = key; } @VisibleForTesting Key getKeyForTesting() { return key; } /** * Retrieves the value of this variable from Skyframe. * *

If the value was not set, an exception will be raised. */ @Nullable @SuppressWarnings("unchecked") public T get(SkyFunction.Environment env) throws InterruptedException { PrecomputedValue value = (PrecomputedValue) env.getValue(key); if (value == null) { return null; } return (T) value.get(); } /** * Injects a new variable value. */ public void set(Injectable injectable, T value) { injectable.inject(key, new PrecomputedValue(value)); } } /** {@link SkyKey} for {@code PrecomputedValue}. */ @AutoCodec public static class Key extends AbstractSkyKey { private static final Interner interner = BlazeInterners.newWeakInterner(); private Key(String arg) { super(arg); } @AutoCodec.Instantiator public static Key create(String arg) { return interner.intern(new Key(arg)); } @Override public SkyFunctionName functionName() { return SkyFunctions.PRECOMPUTED; } } }