// Copyright 2015 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.skyframe; import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; /** * {@link WalkableGraph} that looks nodes up in a {@link QueryableGraph}. */ public class DelegatingWalkableGraph implements WalkableGraph { private final QueryableGraph graph; public DelegatingWalkableGraph(QueryableGraph graph) { this.graph = graph; } private NodeEntry getEntry(SkyKey key) { NodeEntry entry = Preconditions.checkNotNull(graph.get(key), key); Preconditions.checkState(entry.isDone(), "%s %s", key, entry); return entry; } private Map getEntries(Iterable keys) { Map result = graph.getBatch(keys); Preconditions.checkState(result.size() == Iterables.size(keys), "%s %s", keys, result); for (Map.Entry entry : result.entrySet()) { Preconditions.checkState(entry.getValue().isDone(), entry); } return result; } @Override public boolean exists(SkyKey key) { NodeEntry entry = graph.get(key); return entry != null && entry.isDone(); } @Nullable @Override public SkyValue getValue(SkyKey key) { return getEntry(key).getValue(); } private static final Function GET_SKY_VALUE_FUNCTION = new Function() { @Nullable @Override public SkyValue apply(NodeEntry entry) { return entry.isDone() ? entry.getValue() : null; } }; @Override public Map getSuccessfulValues(Iterable keys) { return Maps.filterValues(Maps.transformValues(graph.getBatch(keys), GET_SKY_VALUE_FUNCTION), Predicates.notNull()); } @Override public Map getMissingAndExceptions(Iterable keys) { Map result = new HashMap<>(); Map graphResult = graph.getBatch(keys); for (SkyKey key : keys) { NodeEntry nodeEntry = graphResult.get(key); if (nodeEntry == null || !nodeEntry.isDone()) { result.put(key, null); } else { ErrorInfo errorInfo = nodeEntry.getErrorInfo(); if (errorInfo != null) { result.put(key, errorInfo.getException()); } } } return result; } @Nullable @Override public Exception getException(SkyKey key) { ErrorInfo errorInfo = getEntry(key).getErrorInfo(); return errorInfo == null ? null : errorInfo.getException(); } private static final Function> GET_DIRECT_DEPS_FUNCTION = new Function>() { @Override public Iterable apply(NodeEntry entry) { return entry.getDirectDeps(); } }; @Override public Map> getDirectDeps(Iterable keys) { return Maps.transformValues(getEntries(keys), GET_DIRECT_DEPS_FUNCTION); } private static final Function> GET_REVERSE_DEPS_FUNCTION = new Function>() { @Override public Iterable apply(NodeEntry entry) { return entry.getReverseDeps(); } }; @Override public Map> getReverseDeps(Iterable keys) { return Maps.transformValues(getEntries(keys), GET_REVERSE_DEPS_FUNCTION); } }