| // Copyright 2016 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.remote; |
| |
| import static java.nio.charset.StandardCharsets.UTF_8; |
| |
| import com.google.common.hash.HashCode; |
| import com.google.common.hash.Hashing; |
| import com.google.devtools.build.lib.actions.ActionInput; |
| import com.google.devtools.build.lib.actions.ActionInputFileCache; |
| import com.google.devtools.build.lib.actions.cache.VirtualActionInput; |
| import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; |
| import com.google.devtools.build.lib.vfs.Path; |
| import com.google.devtools.remoteexecution.v1test.Action; |
| import com.google.devtools.remoteexecution.v1test.Digest; |
| import com.google.protobuf.Message; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| |
| /** Helper methods relating to computing Digest messages for remote execution. */ |
| @ThreadSafe |
| public final class Digests { |
| private Digests() {} |
| |
| public static Digest computeDigest(byte[] blob) { |
| return buildDigest(Hashing.sha1().hashBytes(blob).toString(), blob.length); |
| } |
| |
| public static Digest computeDigest(Path file) throws IOException { |
| return buildDigest(file.getSHA1Digest(), file.getFileSize()); |
| } |
| |
| public static Digest computeDigest(VirtualActionInput input) throws IOException { |
| ByteArrayOutputStream buffer = new ByteArrayOutputStream(); |
| input.writeTo(buffer); |
| return computeDigest(buffer.toByteArray()); |
| } |
| |
| /** |
| * Computes a digest of the given proto message. Currently, we simply rely on message output as |
| * bytes, but this implementation relies on the stability of the proto encoding, in particular |
| * between different platforms and languages. TODO(olaola): upgrade to a better implementation! |
| */ |
| public static Digest computeDigest(Message message) { |
| return computeDigest(message.toByteArray()); |
| } |
| |
| public static Digest computeDigestUtf8(String str) { |
| return computeDigest(str.getBytes(UTF_8)); |
| } |
| |
| /** |
| * A special type of Digest that is used only as a remote action cache key. This is a |
| * separate type in order to prevent accidentally using other Digests as action keys. |
| */ |
| public static final class ActionKey { |
| private final Digest digest; |
| |
| public Digest getDigest() { |
| return digest; |
| } |
| |
| private ActionKey(Digest digest) { |
| this.digest = digest; |
| } |
| } |
| |
| public static ActionKey computeActionKey(Action action) { |
| return new ActionKey(computeDigest(action)); |
| } |
| |
| /** |
| * Assumes that the given Digest is a valid digest of an Action, and creates an ActionKey |
| * wrapper. This should not be called on the client side! |
| */ |
| public static ActionKey unsafeActionKeyFromDigest(Digest digest) { |
| return new ActionKey(digest); |
| } |
| |
| public static Digest buildDigest(byte[] hash, long size) { |
| return buildDigest(HashCode.fromBytes(hash).toString(), size); |
| } |
| |
| public static Digest buildDigest(String hexHash, long size) { |
| return Digest.newBuilder().setHash(hexHash).setSizeBytes(size).build(); |
| } |
| |
| public static Digest getDigestFromInputCache(ActionInput input, ActionInputFileCache cache) |
| throws IOException { |
| return buildDigest(cache.getDigest(input), cache.getSizeInBytes(input)); |
| } |
| } |