diff options
Diffstat (limited to 'impl/src/main/java/io/perfmark/impl/Mark.java')
-rw-r--r-- | impl/src/main/java/io/perfmark/impl/Mark.java | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/impl/src/main/java/io/perfmark/impl/Mark.java b/impl/src/main/java/io/perfmark/impl/Mark.java new file mode 100644 index 0000000..a07c194 --- /dev/null +++ b/impl/src/main/java/io/perfmark/impl/Mark.java @@ -0,0 +1,505 @@ +/* + * Copyright 2019 Google LLC + * + * 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 io.perfmark.impl; + +import java.util.Arrays; +import javax.annotation.Nullable; + +public final class Mark { + // TODO: make sure these match the values in Impl + public static final String NO_TAG_NAME = ""; + public static final long NO_TAG_ID = Long.MIN_VALUE; + public static final long NO_LINK_ID = Long.MIN_VALUE; + + public static final long NO_NANOTIME = 0; + + private static final long N0 = 0; + private static final String S0 = null; + + private final long generation; + + private final long n1; + private final long n2; + private final long n3; + + @Nullable private final String s1; + @Nullable private final String s2; + @Nullable private final String s3; + + private final Operation operation; + + public static Mark taskStart(long generation, long nanoTime, String name) { + return new Mark(nanoTime, N0, N0, name, S0, S0, generation, Operation.TASK_START_N1S1); + } + + public static Mark taskStart(long generation, long nanoTime, String name, String subName) { + return new Mark(nanoTime, N0, N0, name, subName, S0, generation, Operation.TASK_START_N1S2); + } + + public static Mark taskEnd(long generation, long nanoTime) { + return new Mark(nanoTime, N0, N0, S0, S0, S0, generation, Operation.TASK_END_N1S0); + } + + public static Mark taskEnd(long generation, long nanoTime, String name) { + return new Mark(nanoTime, N0, N0, name, S0, S0, generation, Operation.TASK_END_N1S1); + } + + public static Mark taskEnd(long generation, long nanoTime, String name, String subName) { + return new Mark(nanoTime, N0, N0, name, subName, S0, generation, Operation.TASK_END_N1S2); + } + + public static Mark event(long generation, long nanoTime, String name) { + return new Mark(nanoTime, N0, N0, name, S0, S0, generation, Operation.EVENT_N1S1); + } + + public static Mark event(long generation, long nanoTime, String name, String subName) { + return new Mark(nanoTime, N0, N0, name, subName, S0, generation, Operation.EVENT_N1S2); + } + + public static Mark event( + long generation, long nanoTime, String taskName, String tagName, long tagId) { + return new Mark( + nanoTime, tagId, N0, taskName, tagName, S0, generation, Operation.EVENT_N2S2); + } + + public static Mark event( + long generation, + long nanoTime, + String taskName, + String subTaskName, + String tagName, + long tagId) { + return new Mark( + nanoTime, tagId, N0, taskName, subTaskName, tagName, generation, Operation.EVENT_N2S3); + } + + public static Mark tag(long generation, String tagName, long tagId) { + return new Mark(tagId, N0, N0, tagName, S0, S0, generation, Operation.TAG_N1S1); + } + + public static Mark tag(long generation, long tagId) { + return new Mark(tagId, N0, N0, S0, S0, S0, generation, Operation.TAG_N1S0); + } + + public static Mark tag(long generation, String tagName) { + return new Mark(N0, N0, N0, tagName, S0, S0, generation, Operation.TAG_N0S1); + } + + public static Mark keyedTag(long generation, String tagName, String value) { + return new Mark(N0, N0, N0, tagName, value, S0, generation, Operation.TAG_KEYED_N0S2); + } + + public static Mark keyedTag(long generation, String tagName, long value) { + return new Mark(value, N0, N0, tagName, S0, S0, generation, Operation.TAG_KEYED_N1S1); + } + + public static Mark keyedTag(long generation, String tagName, long value0, long value1) { + return new Mark(value0, value1, N0, tagName, S0, S0, generation, Operation.TAG_KEYED_N2S1); + } + + public static Mark link(long generation, long linkId) { + return new Mark(linkId, N0, N0, S0, S0, S0, generation, Operation.LINK); + } + + public Mark withTaskName(String name) { + switch (operation) { + case EVENT_N1S1: + case TASK_END_N1S1: + case TASK_START_N1S1: + return new Mark(n1, n2, n3, name, s2, s3, generation, operation); + case TASK_START_N1S2: + case TASK_END_N1S0: + case NONE: + case TASK_END_N1S2: + case EVENT_N1S2: + case EVENT_N2S2: + case EVENT_N2S3: + case LINK: + case TAG_N0S1: + case TAG_N1S0: + case TAG_N1S1: + case TAG_KEYED_N1S1: + case TAG_KEYED_N2S1: + case TAG_KEYED_N0S2: + throw new UnsupportedOperationException(); + } + throw new AssertionError(); + } + + private Mark( + long n1, + long n2, + long n3, + @Nullable String s1, + @Nullable String s2, + @Nullable String s3, + long generation, + Operation operation) { + if (operation == null) { + throw new NullPointerException("operation"); + } + this.operation = operation; + this.generation = generation; + + if (operation == Operation.NONE) { + throw new IllegalArgumentException("bad operation"); + } + this.n1 = n1; + this.n2 = n2; + this.n3 = n3; + + this.s1 = s1; + this.s2 = s2; + this.s3 = s3; + } + + public enum OperationType { + NONE, + TASK_START, + TASK_END, + EVENT, + LINK, + TAG, + ; + } + + public enum Operation { + NONE(OperationType.NONE, 0, 0), + /** startTask(String taskName) 1 long for nanoTime. */ + TASK_START_N1S1(OperationType.TASK_START, 1, 1), + /** startTask(String name, String subTaskName) 1 long for nanoTime. */ + TASK_START_N1S2(OperationType.TASK_START, 1, 2), + + TASK_END_N1S0(OperationType.TASK_END, 1, 0), + TASK_END_N1S1(OperationType.TASK_END, 1, 1), + TASK_END_N1S2(OperationType.TASK_END, 1, 2), + + EVENT_N1S1(OperationType.EVENT, 1, 1), + EVENT_N1S2(OperationType.EVENT, 1, 2), + /** Tagged event, since attach tags can't apply to events */ + EVENT_N2S2(OperationType.EVENT, 2, 2), + /** Tagged event, since attach tags can't apply to events */ + EVENT_N2S3(OperationType.EVENT, 2, 3), + + LINK(OperationType.LINK, 1, 0), + + /** An unkeyed tag that has a single string value. */ + TAG_N0S1(OperationType.TAG, 0, 1), + /** An unkeyed tag that has a single numeric value. */ + TAG_N1S0(OperationType.TAG, 1, 0), + /** + * An unkeyed tag that has a string and numeric value. The values are unrelated to each other. + */ + TAG_N1S1(OperationType.TAG, 1, 1), + + TAG_KEYED_N1S1(OperationType.TAG, 1, 1), + + TAG_KEYED_N2S1(OperationType.TAG, 2, 1), + + TAG_KEYED_N0S2(OperationType.TAG, 0, 2), + ; + + private final OperationType opType; + private final int longs; + private final int strings; + + Operation(OperationType opType, int longs, int strings) { + this.opType = opType; + this.longs = longs; + this.strings = strings; + assert longs <= maxNumbers(); + assert strings <= maxStrings(); + } + + private static final Operation[] values = Operation.values(); + + static { + assert values.length <= (1 << Generator.GEN_OFFSET); + } + + public OperationType getOpType() { + return opType; + } + + public int getNumbers() { + return longs; + } + + public int getStrings() { + return strings; + } + + public static int maxNumbers() { + return 2; + } + + public static int maxStrings() { + return 3; + } + + public static int maxMarkers() { + return 1; + } + + public static Operation valueOf(int code) { + return values[code]; + } + } + + public long getNanoTime() { + switch (operation.opType) { + case TASK_START: + case TASK_END: + case EVENT: + return n1; + case NONE: + case LINK: + case TAG: + throw new UnsupportedOperationException(); + } + throw new AssertionError(operation.opType); + } + + public long getGeneration() { + return generation; + } + + public Operation getOperation() { + return operation; + } + + public String getTagStringValue() { + switch (operation) { + case TAG_N0S1: + case TAG_N1S1: + return s1; + case TAG_KEYED_N0S2: + case EVENT_N2S2: + return s2; + case EVENT_N2S3: + return s3; + case TAG_N1S0: + case NONE: + case TASK_START_N1S1: + case TASK_START_N1S2: + case TASK_END_N1S0: + case TASK_END_N1S1: + case TASK_END_N1S2: + case EVENT_N1S1: + case EVENT_N1S2: + case TAG_KEYED_N1S1: + case TAG_KEYED_N2S1: + case LINK: + throw new UnsupportedOperationException(); + } + throw new AssertionError(operation.opType); + } + + public long getTagFirstNumeric() { + switch (operation) { + case TAG_N1S0: + case TAG_N1S1: + case TAG_KEYED_N1S1: + case TAG_KEYED_N2S1: + return n1; + case EVENT_N2S2: + case EVENT_N2S3: + return n2; + case TAG_N0S1: + case TAG_KEYED_N0S2: + case NONE: + case TASK_START_N1S1: + case TASK_START_N1S2: + case TASK_END_N1S0: + case TASK_END_N1S1: + case TASK_END_N1S2: + case EVENT_N1S1: + case EVENT_N1S2: + case LINK: + throw new UnsupportedOperationException(); + } + throw new AssertionError(operation.opType); + } + + public long getTagSecondNumeric() { + switch (operation) { + case TAG_KEYED_N2S1: + return n2; + case TAG_N1S0: + case TAG_N1S1: + case TAG_KEYED_N1S1: + case EVENT_N2S2: + case EVENT_N2S3: + case TAG_N0S1: + case TAG_KEYED_N0S2: + case NONE: + case TASK_START_N1S1: + case TASK_START_N1S2: + case TASK_END_N1S0: + case TASK_END_N1S1: + case TASK_END_N1S2: + case EVENT_N1S1: + case EVENT_N1S2: + case LINK: + throw new UnsupportedOperationException(); + } + throw new AssertionError(operation.opType); + } + + public String getTagKey() { + switch (operation) { + case TAG_KEYED_N0S2: + case TAG_KEYED_N1S1: + case TAG_KEYED_N2S1: + return s1; + case TAG_N1S1: + case TAG_N0S1: + case TAG_N1S0: + case NONE: + case TASK_START_N1S1: + case TASK_START_N1S2: + case TASK_END_N1S0: + case TASK_END_N1S1: + case TASK_END_N1S2: + case EVENT_N1S1: + case EVENT_N1S2: + case EVENT_N2S2: + case EVENT_N2S3: + case LINK: + throw new UnsupportedOperationException(); + } + throw new AssertionError(operation.opType); + } + + public String getTaskName() { + switch (operation) { + case TASK_START_N1S1: + case TASK_START_N1S2: + case TASK_END_N1S1: + case TASK_END_N1S2: + case EVENT_N1S1: + case EVENT_N1S2: + case EVENT_N2S2: + case EVENT_N2S3: + return s1; + case NONE: + case LINK: + case TASK_END_N1S0: + case TAG_N0S1: + case TAG_N1S0: + case TAG_N1S1: + case TAG_KEYED_N0S2: + case TAG_KEYED_N1S1: + case TAG_KEYED_N2S1: + throw new UnsupportedOperationException(); + } + throw new AssertionError(operation); + } + + public String getSubTaskName() { + switch (operation) { + case TASK_END_N1S2: + case TASK_START_N1S2: + case EVENT_N1S2: + case EVENT_N2S3: + return s2; + case TASK_START_N1S1: + case TASK_END_N1S0: + case TASK_END_N1S1: + case EVENT_N1S1: + case EVENT_N2S2: + case NONE: + case LINK: + case TAG_N0S1: + case TAG_KEYED_N0S2: + case TAG_KEYED_N1S1: + case TAG_KEYED_N2S1: + case TAG_N1S0: + case TAG_N1S1: + throw new UnsupportedOperationException(); + } + throw new AssertionError(operation); + } + + public long getLinkId() { + switch (operation.opType) { + case LINK: + return n1; + case TASK_START: + case TASK_END: + case EVENT: + case NONE: + case TAG: + throw new UnsupportedOperationException(); + } + throw new AssertionError(operation.opType); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Mark)) { + return false; + } + Mark that = (Mark) obj; + return equal(this.s1, that.s1) + && equal(this.s2, that.s2) + && equal(this.s3, that.s3) + && this.n1 == that.n1 + && this.n2 == that.n2 + && this.n3 == that.n3 + && this.operation == that.operation + && this.generation == that.generation; + } + + @Override + public int hashCode() { + return Arrays.hashCode(new Object[] {operation, s1, s2, s3, n1, n2, n3, generation}); + } + + @Override + public String toString() { + return "Mark{" + + "operation=" + + operation + + ", " + + "s1=" + + s1 + + ", " + + "s2=" + + s2 + + ", " + + "s3=" + + s3 + + ", " + + "n1=" + + n1 + + ", " + + "n2=" + + n2 + + ", " + + "n3=" + + n3 + + ", " + + "generation=" + + generation + + "}"; + } + + static <T> boolean equal(T a, T b) { + return a == b || a.equals(b); + } +} |