diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/actions/cache/ActionCache.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/actions/cache/ActionCache.java | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/actions/cache/ActionCache.java b/src/main/java/com/google/devtools/build/lib/actions/cache/ActionCache.java new file mode 100644 index 0000000000..2ac0ab82da --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/actions/cache/ActionCache.java @@ -0,0 +1,173 @@ +// Copyright 2014 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.actions.cache; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible; +import com.google.devtools.build.lib.vfs.PathFragment; + +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * An interface defining a cache of already-executed Actions. + * + * <p>This class' naming is misleading; it doesn't cache the actual actions, but it stores a + * fingerprint of the action state (ie. a hash of the input and output files on disk), so + * we can tell if we need to rerun an action given the state of the file system. + * + * <p>Each action entry uses one of its output paths as a key (after conversion + * to the string). + */ +@ThreadCompatible +public interface ActionCache { + + /** + * Updates the cache entry for the specified key. + */ + void put(String key, ActionCache.Entry entry); + + /** + * Returns the corresponding cache entry for the specified key, if any, or + * null if not found. + */ + ActionCache.Entry get(String key); + + /** + * Removes entry from cache + */ + void remove(String key); + + /** + * Returns a new Entry instance. This method allows ActionCache subclasses to + * define their own Entry implementation. + */ + ActionCache.Entry createEntry(String key); + + /** + * An entry in the ActionCache that contains all action input and output + * artifact paths and their metadata plus action key itself. + * + * Cache entry operates under assumption that once it is fully initialized + * and getFileDigest() method is called, it becomes logically immutable (all methods + * will continue to return same result regardless of internal data transformations). + */ + public final class Entry { + private final String actionKey; + private final List<String> files; + // If null, digest is non-null and the entry is immutable. + private Map<String, Metadata> mdMap; + private Digest digest; + + public Entry(String key) { + actionKey = key; + files = new ArrayList<>(); + mdMap = new HashMap<>(); + } + + public Entry(String key, List<String> files, Digest digest) { + actionKey = key; + this.files = files; + this.digest = digest; + mdMap = null; + } + + /** + * Adds the artifact, specified by the executable relative path and its + * metadata into the cache entry. + */ + public void addFile(PathFragment relativePath, Metadata md) { + Preconditions.checkState(mdMap != null); + Preconditions.checkState(!isCorrupted()); + Preconditions.checkState(digest == null); + + String execPath = relativePath.getPathString(); + files.add(execPath); + mdMap.put(execPath, md); + } + + /** + * @return action key string. + */ + public String getActionKey() { + return actionKey; + } + + /** + * Returns the combined digest of the action's inputs and outputs. + * + * This may compresses the data into a more compact representation, and + * makes the object immutable. + */ + public Digest getFileDigest() { + if (digest == null) { + digest = Digest.fromMetadata(mdMap); + mdMap = null; + } + return digest; + } + + /** + * Returns true if this cache entry is corrupted and should be ignored. + */ + public boolean isCorrupted() { + return actionKey == null; + } + + /** + * @return stored path strings. + */ + public Collection<String> getPaths() { + return files; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(" actionKey = ").append(actionKey).append("\n"); + builder.append(" digestKey = "); + if (digest == null) { + builder.append(Digest.fromMetadata(mdMap)).append(" (from mdMap)\n"); + } else { + builder.append(digest).append("\n"); + } + List<String> fileInfo = Lists.newArrayListWithCapacity(files.size()); + fileInfo.addAll(files); + Collections.sort(fileInfo); + for (String info : fileInfo) { + builder.append(" ").append(info).append("\n"); + } + return builder.toString(); + } + } + + /** + * Give persistent cache implementations a notification to write to disk. + * @return size in bytes of the serialized cache. + */ + long save() throws IOException; + + /** + * Dumps action cache content into the given PrintStream. + */ + void dump(PrintStream out); +} |