aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar buchgr <buchgr@google.com>2017-08-29 13:58:28 +0200
committerGravatar Vladimir Moskva <vladmos@google.com>2017-08-29 18:47:16 +0200
commitc291726428a7caaa6024fdb06af285fbc68f63cb (patch)
tree185eeee87a6977961b54dbeda4ea0707303500ca
parentaa43a8989a2ed3d19d3a83969a85322058e97aa7 (diff)
remote/http: distinquish between action cache and cas
The remote http caching client now prefixes the URL of an action cache request with 'ac' and cas request with 'cas'. This is useful as servers might want to distinquish between the action cache and the cas. Before this change: (GET|PUT) /f141ae2d23d0f976599e678da1c51d82fedaf8b1 After this change: (GET|PUT) /ac/f141ae2d23d0f976599e678da1c51d82fedaf8b1 (GET|PUT) /cas/f141ae2d23d0f976599e678da1c51d82fedaf8b1 This change will likely break any HTTP caching service that assumed the old URL scheme. TESTED: Manually using https://github.com/buchgr/bazel-remote RELNOTES: The remote HTTP/1.1 caching client (--remote_rest_cache) now distinquishes between action cache and CAS. The request URL for the action cache is prefixed with 'ac' and the URL for the CAS is prefixed with 'cas'. PiperOrigin-RevId: 166831997
-rw-r--r--src/main/java/com/google/devtools/build/lib/remote/SimpleBlobStoreActionCache.java27
-rw-r--r--src/main/java/com/google/devtools/build/lib/remote/blobstore/ConcurrentMapBlobStore.java12
-rw-r--r--src/main/java/com/google/devtools/build/lib/remote/blobstore/OnDiskBlobStore.java11
-rw-r--r--src/main/java/com/google/devtools/build/lib/remote/blobstore/RestBlobStore.java42
-rw-r--r--src/main/java/com/google/devtools/build/lib/remote/blobstore/SimpleBlobStore.java31
5 files changed, 99 insertions, 24 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/remote/SimpleBlobStoreActionCache.java b/src/main/java/com/google/devtools/build/lib/remote/SimpleBlobStoreActionCache.java
index 1c4c462eab..645a693401 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/SimpleBlobStoreActionCache.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/SimpleBlobStoreActionCache.java
@@ -180,7 +180,7 @@ public final class SimpleBlobStoreActionCache implements RemoteActionCache {
Digest stdout = uploadFileContents(outErr.getOutputPath());
result.setStdoutDigest(stdout);
}
- blobStore.put(
+ blobStore.putActionResult(
actionKey.getDigest().getHash(), new ByteArrayInputStream(result.build().toByteArray()));
}
@@ -269,7 +269,7 @@ public final class SimpleBlobStoreActionCache implements RemoteActionCache {
return digest;
}
- public void downloadBlob(Digest digest, OutputStream out)
+ private void downloadBlob(Digest digest, OutputStream out)
throws IOException, InterruptedException {
if (digest.getSizeBytes() == 0) {
return;
@@ -300,18 +300,31 @@ public final class SimpleBlobStoreActionCache implements RemoteActionCache {
public ActionResult getCachedActionResult(ActionKey actionKey)
throws IOException, InterruptedException {
try {
- byte[] data = downloadBlob(actionKey.getDigest());
+ byte[] data = downloadActionResult(actionKey.getDigest());
return ActionResult.parseFrom(data);
- } catch (InvalidProtocolBufferException e) {
- return null;
- } catch (CacheNotFoundException e) {
+ } catch (InvalidProtocolBufferException | CacheNotFoundException e) {
return null;
}
}
+ private byte[] downloadActionResult(Digest digest) throws IOException, InterruptedException {
+ if (digest.getSizeBytes() == 0) {
+ return new byte[0];
+ }
+ // This unconditionally downloads the whole blob into memory!
+ checkBlobSize(digest.getSizeBytes() / 1024, "Download Action Result");
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ boolean success = blobStore.getActionResult(digest.getHash(), out);
+ if (!success) {
+ throw new CacheNotFoundException(digest);
+ }
+ return out.toByteArray();
+ }
+
public void setCachedActionResult(ActionKey actionKey, ActionResult result)
throws IOException, InterruptedException {
- blobStore.put(actionKey.getDigest().getHash(), new ByteArrayInputStream(result.toByteArray()));
+ blobStore.putActionResult(actionKey.getDigest().getHash(),
+ new ByteArrayInputStream(result.toByteArray()));
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/remote/blobstore/ConcurrentMapBlobStore.java b/src/main/java/com/google/devtools/build/lib/remote/blobstore/ConcurrentMapBlobStore.java
index 179385c3b7..82cd36bc97 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/blobstore/ConcurrentMapBlobStore.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/blobstore/ConcurrentMapBlobStore.java
@@ -43,11 +43,23 @@ public final class ConcurrentMapBlobStore implements SimpleBlobStore {
}
@Override
+ public boolean getActionResult(String key, OutputStream out)
+ throws IOException, InterruptedException {
+ return get(key, out);
+ }
+
+ @Override
public void put(String key, InputStream in) throws IOException {
byte[] value = ByteStreams.toByteArray(in);
map.put(key, value);
}
@Override
+ public void putActionResult(String key, InputStream in)
+ throws IOException, InterruptedException {
+ put(key, in);
+ }
+
+ @Override
public void close() {}
} \ No newline at end of file
diff --git a/src/main/java/com/google/devtools/build/lib/remote/blobstore/OnDiskBlobStore.java b/src/main/java/com/google/devtools/build/lib/remote/blobstore/OnDiskBlobStore.java
index 8e780556b5..8d41023089 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/blobstore/OnDiskBlobStore.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/blobstore/OnDiskBlobStore.java
@@ -46,6 +46,12 @@ public final class OnDiskBlobStore implements SimpleBlobStore {
}
@Override
+ public boolean getActionResult(String key, OutputStream out)
+ throws IOException, InterruptedException {
+ return get(key, out);
+ }
+
+ @Override
public void put(String key, InputStream in) throws IOException {
// Write a temporary file first, and then rename, to avoid data corruption in case of a crash.
Path temp = toPath(UUID.randomUUID().toString());
@@ -59,6 +65,11 @@ public final class OnDiskBlobStore implements SimpleBlobStore {
}
@Override
+ public void putActionResult(String key, InputStream in) throws IOException, InterruptedException {
+ put(key, in);
+ }
+
+ @Override
public void close() {}
private Path toPath(String key) {
diff --git a/src/main/java/com/google/devtools/build/lib/remote/blobstore/RestBlobStore.java b/src/main/java/com/google/devtools/build/lib/remote/blobstore/RestBlobStore.java
index 82e9b47bad..b7473d8c9b 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/blobstore/RestBlobStore.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/blobstore/RestBlobStore.java
@@ -32,19 +32,22 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
* Implementation of {@link SimpleBlobStore} with a REST service. The REST service needs to
* support the following HTTP methods.
*
- * <p>PUT /cache/1234 HTTP/1.1 PUT method is used to upload a blob with a base16 key. In this
- * example the key is 1234. Valid status codes are 200, 201, 202 and 204.
+ * <p>PUT /{actioncache,cas}/1234 HTTP/1.1 PUT method is used to upload a blob with a base16 key.
+ * In this example the key is 1234. Valid status codes are 200, 201, 202 and 204.
*
- * <p>GET /cache/1234 HTTP/1.1 GET method fetches a blob with the specified key. In this example
- * the key is 1234. A status code of 200 should be followed by the content of blob. Status code of
- * 404 or 204 means the key cannot be found.
+ * <p>GET /{actioncache,cas}/1234 HTTP/1.1 GET method fetches a blob with the specified key. In this
+ * example the key is 1234. A status code of 200 should be followed by the content of blob. Status
+ * code of 404 or 204 means the key cannot be found.
*
- * <p>HEAD /cache/1234 HTTP/1.1 HEAD method checks to see if the specified key exists in the blob
- * store. A status code of 200 indicates the key is found in the blob store. A status code of 404
- * indicates the key is not found in the blob store.
+ * <p>HEAD /{actioncache,cas}/1234 HTTP/1.1 HEAD method checks to see if the specified key exists in
+ * the blob store. A status code of 200 indicates the key is found in the blob store. A status code
+ * of 404 indicates the key is not found in the blob store.
*/
public final class RestBlobStore implements SimpleBlobStore {
+ private static final String ACTION_CACHE_PREFIX = "ac";
+ private static final String CAS_PREFIX = "cas";
+
private final String baseUrl;
private final PoolingHttpClientConnectionManager connMan;
private final HttpClientBuilder clientFactory;
@@ -85,8 +88,18 @@ public final class RestBlobStore implements SimpleBlobStore {
@Override
public boolean get(String key, OutputStream out) throws IOException {
+ return get(CAS_PREFIX, key, out);
+ }
+
+ @Override
+ public boolean getActionResult(String key, OutputStream out)
+ throws IOException, InterruptedException {
+ return get(ACTION_CACHE_PREFIX, key, out);
+ }
+
+ private boolean get(String urlPrefix, String key, OutputStream out) throws IOException {
HttpClient client = clientFactory.build();
- HttpGet get = new HttpGet(baseUrl + "/" + key);
+ HttpGet get = new HttpGet(baseUrl + "/" + urlPrefix + "/" + key);
return client.execute(
get,
response -> {
@@ -105,8 +118,17 @@ public final class RestBlobStore implements SimpleBlobStore {
@Override
public void put(String key, InputStream in) throws IOException {
+ put(CAS_PREFIX, key, in);
+ }
+
+ @Override
+ public void putActionResult(String key, InputStream in) throws IOException, InterruptedException {
+ put(ACTION_CACHE_PREFIX, key, in);
+ }
+
+ private void put(String urlPrefix, String key, InputStream in) throws IOException {
HttpClient client = clientFactory.build();
- HttpPut put = new HttpPut(baseUrl + "/" + key);
+ HttpPut put = new HttpPut(baseUrl + "/" + urlPrefix + "/" + key);
// For now, upload a byte array instead of a stream, due to Hazelcast crashing on the stream.
// See https://github.com/hazelcast/hazelcast/issues/10878.
put.setEntity(new ByteArrayEntity(ByteStreams.toByteArray(in)));
diff --git a/src/main/java/com/google/devtools/build/lib/remote/blobstore/SimpleBlobStore.java b/src/main/java/com/google/devtools/build/lib/remote/blobstore/SimpleBlobStore.java
index 5f79c4590f..38479962b4 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/blobstore/SimpleBlobStore.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/blobstore/SimpleBlobStore.java
@@ -19,25 +19,42 @@ import java.io.InputStream;
import java.io.OutputStream;
/**
- * A simple interface for storing blobs (in the form of byte arrays) each one indexed by a
- * hexadecimal string. Implementation must be thread-safe.
+ * An interface for storing BLOBs each one indexed by a string (hash in hexadecimal).
+ *
+ * <p>Implementations must be thread-safe.
*/
public interface SimpleBlobStore {
- /** Returns true if the provided {@code key} is stored in the blob store. */
+ /**
+ * Returns {@code key} if the provided {@code key} is stored in the CAS.
+ */
boolean containsKey(String key) throws IOException, InterruptedException;
/**
- * Returns the blob (in the form of a byte array) indexed by {@code key}. Returns null if the
- * {@code key} cannot be found.
+ * Fetches the BLOB associated with the {@code key} from the CAS and writes it to {@code out}.
+ *
+ * @return {@code true} if the {@code key} was found. {@code false} otherwise.
*/
boolean get(String key, OutputStream out) throws IOException, InterruptedException;
/**
- * Uploads a blob (as {@code value}) indexed by {@code key} to the blob store. Existing blob
- * indexed by the same {@code key} will be overwritten.
+ * Fetches the BLOB associated with the {@code key} from the Action Cache and writes it to
+ * {@code out}.
+ *
+ * @return {@code true} if the {@code key} was found. {@code false} otherwise.
+ */
+ boolean getActionResult(String actionKey, OutputStream out) throws IOException,
+ InterruptedException;
+
+ /**
+ * Uploads a BLOB (as {@code in}) indexed by {@code key} to the CAS.
*/
void put(String key, InputStream in) throws IOException, InterruptedException;
+ /**
+ * Uploads a BLOB (as {@code in}) indexed by {@code key} to the Action Cache.
+ */
+ void putActionResult(String actionKey, InputStream in) throws IOException, InterruptedException;
+
/** Close resources associated with the blob store. */
void close();
}