aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar michajlo <michajlo@google.com>2018-01-03 12:44:17 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-01-03 12:45:47 -0800
commit19e42c9936b78b8339e38826a63b1068ad8b46eb (patch)
tree4c13b1f5da7a0163513943c3cb20c8029fe3ace5
parentceaed5145f5ad27facd103a79d047cf0e301b4b5 (diff)
Consolidate GlobDescriptor functionality
Makes GlobDescriptor directly implement SkyKey and adds custom serialization logic. This lets us narrow visibility and migrate yet another SkyKey away from LegacySkyKey. PiperOrigin-RevId: 180705483
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/GlobDescriptor.java112
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java13
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/BUILD1
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/GlobDescriptorTest.java79
4 files changed, 183 insertions, 22 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GlobDescriptor.java b/src/main/java/com/google/devtools/build/lib/skyframe/GlobDescriptor.java
index c9f26f36ad..e3b15f6b72 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/GlobDescriptor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/GlobDescriptor.java
@@ -14,31 +14,43 @@
package com.google.devtools.build.lib.skyframe;
import com.google.common.base.Preconditions;
+import com.google.common.collect.Interner;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.cmdline.PackageIdentifierCodec;
+import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
+import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
+import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
+import com.google.devtools.build.lib.skyframe.serialization.strings.StringCodecs;
import com.google.devtools.build.lib.util.StringCanonicalizer;
import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathCodec;
import com.google.devtools.build.lib.vfs.PathFragment;
-import java.io.Serializable;
-import java.util.Objects;
+import com.google.devtools.build.skyframe.SkyFunctionName;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.protobuf.CodedInputStream;
+import com.google.protobuf.CodedOutputStream;
+import java.io.IOException;
/**
- * A descriptor for a glob request.
+ * A descriptor for a glob request, used as the {@link SkyKey} for {@link GlobFunction}.
*
* <p>{@code subdir} must be empty or point to an existing directory.</p>
*
* <p>{@code pattern} must be valid, as indicated by {@code UnixGlob#checkPatternForError}.
*/
@ThreadSafe
-public final class GlobDescriptor implements Serializable {
- final PackageIdentifier packageId;
- final Path packageRoot;
- final PathFragment subdir;
- final String pattern;
- final boolean excludeDirs;
+public final class GlobDescriptor implements SkyKey {
+
+ private static final Interner<GlobDescriptor> interner = BlazeInterners.newWeakInterner();
+
+ /** Creates and returns a new {@link ObjectCodec} for {@link GlobDescriptor}s. */
+ public static ObjectCodec<GlobDescriptor> getCodec(PathCodec pathCodec) {
+ return new GlobDescriptorCodec(pathCodec);
+ }
/**
- * Constructs a GlobDescriptor.
+ * Returns interned instance based on the parameters.
*
* @param packageId the name of the owner package (must be an existing package)
* @param packageRoot the package root of {@code packageId}
@@ -48,7 +60,24 @@ public final class GlobDescriptor implements Serializable {
* @param pattern a valid glob pattern
* @param excludeDirs true if directories should be excluded from results
*/
- public GlobDescriptor(PackageIdentifier packageId, Path packageRoot, PathFragment subdir,
+ public static GlobDescriptor create(
+ PackageIdentifier packageId,
+ Path packageRoot,
+ PathFragment subdir,
+ String pattern,
+ boolean excludeDirs) {
+ return interner.intern(
+ new GlobDescriptor(packageId, packageRoot, subdir, pattern, excludeDirs));
+
+ }
+
+ private final PackageIdentifier packageId;
+ private final Path packageRoot;
+ private final PathFragment subdir;
+ private final String pattern;
+ private final boolean excludeDirs;
+
+ private GlobDescriptor(PackageIdentifier packageId, Path packageRoot, PathFragment subdir,
String pattern, boolean excludeDirs) {
this.packageId = Preconditions.checkNotNull(packageId);
this.packageRoot = Preconditions.checkNotNull(packageRoot);
@@ -105,11 +134,6 @@ public final class GlobDescriptor implements Serializable {
}
@Override
- public int hashCode() {
- return Objects.hash(packageId, subdir, pattern, excludeDirs);
- }
-
- @Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
@@ -122,4 +146,60 @@ public final class GlobDescriptor implements Serializable {
&& subdir.equals(other.subdir) && pattern.equals(other.pattern)
&& excludeDirs == other.excludeDirs;
}
+
+ @Override
+ public int hashCode() {
+ // Generated instead of Objects.hashCode to avoid intermediate array required for latter.
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (excludeDirs ? 1231 : 1237);
+ result = prime * result + packageId.hashCode();
+ result = prime * result + packageRoot.hashCode();
+ result = prime * result + pattern.hashCode();
+ result = prime * result + subdir.hashCode();
+ return result;
+ }
+
+ @Override
+ public SkyFunctionName functionName() {
+ return SkyFunctions.GLOB;
+ }
+
+ private static class GlobDescriptorCodec implements ObjectCodec<GlobDescriptor> {
+
+ private final PackageIdentifierCodec packageIdCodec = new PackageIdentifierCodec();
+ private final PathCodec pathCodec;
+ private final ObjectCodec<String> stringCodec = StringCodecs.asciiOptimized();
+
+ private GlobDescriptorCodec(PathCodec pathCodec) {
+ this.pathCodec = pathCodec;
+ }
+
+ @Override
+ public Class<GlobDescriptor> getEncodedClass() {
+ return GlobDescriptor.class;
+ }
+
+ @Override
+ public void serialize(GlobDescriptor globDesc, CodedOutputStream codedOut)
+ throws IOException, SerializationException {
+ packageIdCodec.serialize(globDesc.getPackageId(), codedOut);
+ pathCodec.serialize(globDesc.getPackageRoot(), codedOut);
+ PathFragment.CODEC.serialize(globDesc.getSubdir(), codedOut);
+ stringCodec.serialize(globDesc.getPattern(), codedOut);
+ codedOut.writeBoolNoTag(globDesc.excludeDirs());
+ }
+
+ @Override
+ public GlobDescriptor deserialize(CodedInputStream codedIn)
+ throws SerializationException, IOException {
+ PackageIdentifier packageId = packageIdCodec.deserialize(codedIn);
+ Path packageRoot = pathCodec.deserialize(codedIn);
+ PathFragment pathFragment = PathFragment.CODEC.deserialize(codedIn);
+ String pattern = stringCodec.deserialize(codedIn);
+ boolean excludeDirs = codedIn.readBool();
+ return GlobDescriptor.create(packageId, packageRoot, pathFragment, pattern, excludeDirs);
+ }
+ }
+
} \ No newline at end of file
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java
index 6d71a63cb2..eb00cb9f20 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java
@@ -23,7 +23,6 @@ import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.UnixGlob;
-import com.google.devtools.build.skyframe.LegacySkyKey;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
@@ -104,9 +103,7 @@ public final class GlobValue implements SkyValue {
@ThreadSafe
static SkyKey internalKey(PackageIdentifier packageId, Path packageRoot, PathFragment subdir,
String pattern, boolean excludeDirs) {
- return LegacySkyKey.create(
- SkyFunctions.GLOB,
- new GlobDescriptor(packageId, packageRoot, subdir, pattern, excludeDirs));
+ return GlobDescriptor.create(packageId, packageRoot, subdir, pattern, excludeDirs);
}
/**
@@ -116,8 +113,12 @@ public final class GlobValue implements SkyValue {
*/
@ThreadSafe
static SkyKey internalKey(GlobDescriptor glob, String subdirName) {
- return internalKey(glob.packageId, glob.packageRoot, glob.subdir.getRelative(subdirName),
- glob.pattern, glob.excludeDirs);
+ return internalKey(
+ glob.getPackageId(),
+ glob.getPackageRoot(),
+ glob.getSubdir().getRelative(subdirName),
+ glob.getPattern(),
+ glob.excludeDirs());
}
/**
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/BUILD b/src/test/java/com/google/devtools/build/lib/skyframe/BUILD
index a92f87161b..a4b01da481 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/BUILD
@@ -78,6 +78,7 @@ java_test(
"//src/main/java/com/google/devtools/build/lib/collect/nestedset",
"//src/main/java/com/google/devtools/build/lib/concurrent",
"//src/main/java/com/google/devtools/build/lib/rules/cpp",
+ "//src/main/java/com/google/devtools/build/lib/skyframe/serialization/testutils",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs",
"//src/main/java/com/google/devtools/build/skyframe",
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/GlobDescriptorTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/GlobDescriptorTest.java
new file mode 100644
index 0000000000..3601eaa0b0
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/GlobDescriptorTest.java
@@ -0,0 +1,79 @@
+// Copyright 2017 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.skyframe;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.skyframe.serialization.testutils.FsUtils;
+import com.google.devtools.build.lib.skyframe.serialization.testutils.ObjectCodecTester;
+import com.google.devtools.build.lib.vfs.PathCodec;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link GlobDescriptor}. */
+@RunWith(JUnit4.class)
+public class GlobDescriptorTest {
+
+ @Test
+ public void testSerialization() throws Exception {
+ ObjectCodecTester.newBuilder(GlobDescriptor.getCodec(new PathCodec(FsUtils.TEST_FILESYSTEM)))
+ .addSubjects(
+ GlobDescriptor.create(
+ PackageIdentifier.create("@foo", PathFragment.create("//bar")),
+ FsUtils.TEST_FILESYSTEM.getPath("/packageRoot"),
+ PathFragment.create("subdir"),
+ "pattern",
+ /*excludeDirs=*/ false),
+ GlobDescriptor.create(
+ PackageIdentifier.create("@bar", PathFragment.create("//foo")),
+ FsUtils.TEST_FILESYSTEM.getPath("/anotherPackageRoot"),
+ PathFragment.create("anotherSubdir"),
+ "pattern",
+ /*excludeDirs=*/ true))
+ .verificationFunction(
+ (orig, deserialized) -> assertThat(deserialized).isSameAs(orig))
+ .buildAndRunTests();
+ }
+
+ @Test
+ public void testCreateReturnsInternedInstances() throws LabelSyntaxException {
+ GlobDescriptor original = GlobDescriptor.create(
+ PackageIdentifier.create("@foo", PathFragment.create("//bar")),
+ FsUtils.TEST_FILESYSTEM.getPath("/packageRoot"),
+ PathFragment.create("subdir"),
+ "pattern",
+ /*excludeDirs=*/ false);
+
+ GlobDescriptor sameCopy = GlobDescriptor.create(
+ original.getPackageId(),
+ original.getPackageRoot(),
+ original.getSubdir(),
+ original.getPattern(),
+ original.excludeDirs());
+ assertThat(sameCopy).isSameAs(original);
+
+ GlobDescriptor diffCopy = GlobDescriptor.create(
+ original.getPackageId(),
+ original.getPackageRoot(),
+ original.getSubdir(),
+ original.getPattern(),
+ !original.excludeDirs());
+ assertThat(diffCopy).isNotEqualTo(original);
+ }
+
+}