blob: c02b8be34a2855dcb6a9702165960b5884db1a05 [file] [log] [blame]
// Copyright 2015 Google Inc. 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 static com.google.devtools.build.lib.skyframe.SkyFunctions.DIRECTORY_LISTING_STATE;
import static com.google.devtools.build.lib.skyframe.SkyFunctions.FILE_STATE;
import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.io.IOException;
import java.util.Set;
import javax.annotation.Nullable;
/** Utilities for checking dirtiness of keys (mainly filesystem keys) in the graph. */
class DirtinessCheckerUtils {
private DirtinessCheckerUtils() {}
static class BasicFilesystemDirtinessChecker implements SkyValueDirtinessChecker {
protected boolean applies(SkyKey skyKey) {
SkyFunctionName functionName = skyKey.functionName();
return (functionName.equals(FILE_STATE) || functionName.equals(DIRECTORY_LISTING_STATE));
}
@Override
@Nullable
public DirtyResult maybeCheck(SkyKey skyKey, SkyValue skyValue,
TimestampGranularityMonitor tsgm) {
if (!applies(skyKey)) {
return null;
}
RootedPath rootedPath = (RootedPath) skyKey.argument();
if (skyKey.functionName().equals(FILE_STATE)) {
return checkFileStateValue(rootedPath, (FileStateValue) skyValue, tsgm);
} else {
return checkDirectoryListingStateValue(rootedPath, (DirectoryListingStateValue) skyValue);
}
}
private static DirtyResult checkFileStateValue(
RootedPath rootedPath, FileStateValue fileStateValue, TimestampGranularityMonitor tsgm) {
try {
FileStateValue newValue = FileStateValue.create(rootedPath, tsgm);
return newValue.equals(fileStateValue)
? DirtyResult.NOT_DIRTY
: DirtyResult.dirtyWithNewValue(newValue);
} catch (InconsistentFilesystemException | IOException e) {
// TODO(bazel-team): An IOException indicates a failure to get a file digest or a symlink
// target, not a missing file. Such a failure really shouldn't happen, so failing early
// may be better here.
return DirtyResult.DIRTY;
}
}
private static DirtyResult checkDirectoryListingStateValue(
RootedPath dirRootedPath, DirectoryListingStateValue directoryListingStateValue) {
try {
DirectoryListingStateValue newValue = DirectoryListingStateValue.create(dirRootedPath);
return newValue.equals(directoryListingStateValue)
? DirtyResult.NOT_DIRTY
: DirtyResult.dirtyWithNewValue(newValue);
} catch (IOException e) {
return DirtyResult.DIRTY;
}
}
}
static final class MissingDiffDirtinessChecker extends BasicFilesystemDirtinessChecker {
private final Set<Path> missingDiffPaths;
MissingDiffDirtinessChecker(final Set<Path> missingDiffPaths) {
this.missingDiffPaths = missingDiffPaths;
}
@Override
protected boolean applies(SkyKey skyKey) {
return super.applies(skyKey)
&& missingDiffPaths.contains(((RootedPath) skyKey.argument()).getRoot());
}
}
/** {@link SkyValueDirtinessChecker} that encompasses a union of other dirtiness checkers. */
static final class UnionDirtinessChecker implements SkyValueDirtinessChecker {
private final Iterable<SkyValueDirtinessChecker> dirtinessCheckers;
UnionDirtinessChecker(Iterable<SkyValueDirtinessChecker> dirtinessCheckers) {
this.dirtinessCheckers = dirtinessCheckers;
}
@Override
@Nullable
public DirtyResult maybeCheck(SkyKey key, SkyValue oldValue, TimestampGranularityMonitor tsgm) {
for (SkyValueDirtinessChecker dirtinessChecker : dirtinessCheckers) {
DirtyResult dirtyResult = dirtinessChecker.maybeCheck(key, oldValue, tsgm);
if (dirtyResult != null) {
return dirtyResult;
}
}
return null;
}
}
}