Skip to content
This repository was archived by the owner on Dec 23, 2023. It is now read-only.

Commit 168c3cc

Browse files
committed
Serializes CensusContextImpl as a Protocol Buffer.
1 parent e0afa60 commit 168c3cc

File tree

10 files changed

+84
-38
lines changed

10 files changed

+84
-38
lines changed

BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ java_library(
2626
srcs = glob(["core_native/java/com/google/census/*.java"]),
2727
deps = [
2828
":census-core",
29+
"//proto:census_context-proto-java",
2930
"@guava//jar",
3031
"@jsr305//jar",
32+
"@protobuf//jar",
3133
],
3234
)
3335

WORKSPACE

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,18 @@ maven_jar(
2424
artifact = "junit:junit:4.11",
2525
)
2626

27+
maven_jar(
28+
name = "protobuf",
29+
artifact = "com.google.protobuf:protobuf-java:3.0.0",
30+
)
31+
2732
maven_jar(
2833
name = "truth",
2934
artifact = "com.google.truth:truth:0.28",
30-
)
35+
)
36+
37+
git_repository(
38+
name = "io_bazel",
39+
remote = "https://github.com/bazelbuild/bazel",
40+
tag = "0.3.1",
41+
)

core/java/com/google/census/Census.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ public static CensusContext getCurrent() {
4141
return CONTEXT_FACTORY.getCurrent();
4242
}
4343

44-
/** Creates a {@link CensusContext} from the given on-the-wire encoded representation. */
44+
/**
45+
* Creates a {@link CensusContext} from the given on-the-wire encoded representation. Should be
46+
* the inverse of {@link CensusContext#serialize()}. The serialized representation should be
47+
* based on the {@link CensusContext} protobuf representation.
48+
*/
4549
@Nullable
4650
public static CensusContext deserialize(ByteBuffer buffer) {
4751
return CONTEXT_FACTORY.deserialize(buffer);

core/java/com/google/census/CensusContext.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public final CensusContext with(
4848

4949
/**
5050
* Serializes the {@link CensusContext} into the on-the-wire representation.
51+
* The inverse of {@link CensusContextFactory#deserialize()} and should be based on the
52+
* {@link CensusContext} protobuf representation.
5153
*
5254
* @return serialized bytes.
5355
*/

core/java/com/google/census/CensusContextFactory.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@
1414
package com.google.census;
1515

1616
import java.nio.ByteBuffer;
17-
1817
import javax.annotation.Nullable;
1918

2019
/**
2120
* Factory class for {@link CensusContext}.
2221
*/
2322
public abstract class CensusContextFactory {
24-
/** Creates a new {@link CensusContext} built from the given on-the-wire encoded representation.
23+
/**
24+
* Creates a {@link CensusContext} from the given on-the-wire encoded representation. Should be
25+
* the inverse of {@link CensusContext#serialize()}. The serialized representation should be
26+
* based on the {@link CensusContext} protobuf representation.
2527
*
2628
* @param buffer on-the-wire representation of a {@link CensusContext}
2729
* @return a {@link CensusContext} deserialized from {@code buffer}

core/javatests/com/google/census/CensusContextFactoryTest.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,11 @@
1515

1616
import static com.google.common.truth.Truth.assertThat;
1717

18-
import static java.nio.charset.StandardCharsets.UTF_8;
19-
18+
import java.nio.ByteBuffer;
2019
import org.junit.Test;
2120
import org.junit.runner.RunWith;
2221
import org.junit.runners.JUnit4;
2322

24-
import java.nio.ByteBuffer;
25-
2623
/**
2724
* Tests for {@link CensusContextFactory}.
2825
*/
@@ -33,12 +30,6 @@ public void testDeserializeEmpty() {
3330
assertThat(Census.deserialize(ByteBuffer.wrap(new byte[0]))).isEqualTo(Census.getDefault());
3431
}
3532

36-
@Test
37-
public void testDeserializeBadData() {
38-
assertThat(Census.deserialize(ByteBuffer.wrap("\2as\3df\2".getBytes(UTF_8))))
39-
.isNull();
40-
}
41-
4233
@Test
4334
public void testGetCurrent() {
4435
assertThat(Census.getCurrent()).isEqualTo(Census.getDefault());

core/javatests/com/google/census/CensusContextTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public void testMultipleThreadsWithContext() throws Exception {
147147
// Tests for Object overrides.
148148
@Test
149149
public void testEquals() {
150-
assertThat(DEFAULT).isEqualTo(DEFAULT);
150+
assertThat(DEFAULT).isEqualTo(DEFAULT.builder().build());
151151
assertThat(DEFAULT.with(K1, V1)).isEqualTo(DEFAULT.with(K1, V1));
152152
assertThat(DEFAULT.with(K1, V1, K2, V2)).isEqualTo(DEFAULT.with(K1, V1, K2, V2));
153153
assertThat(DEFAULT.with(K1, V1, K2, V2)).isEqualTo(DEFAULT.with(K2, V2, K1, V1));

core_native/java/com/google/census/CensusContextFactoryImpl.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,27 @@
1515

1616
import java.nio.ByteBuffer;
1717
import java.util.HashMap;
18-
1918
import javax.annotation.Nullable;
2019

2120
/** Native Implementation of {@link CensusContextFactory} */
2221
final class CensusContextFactoryImpl extends CensusContextFactory {
2322
static final CensusContextImpl DEFAULT = new CensusContextImpl(new HashMap<String, String>(0));
2423

2524
/**
26-
* The serialized tags are of the form:
27-
* {@code (<tag prefix> + 'key' + <tag delim> + 'value')}
25+
* Deserializes a {@link CensusContextImpl} from a serialized {@link CensusContextProto}. The
26+
* encoded tags are of the form: (<tag prefix> + 'key' + <tag delim> + 'value')*
2827
*/
2928
@Override
3029
@Nullable
3130
public CensusContextImpl deserialize(ByteBuffer buffer) {
3231
return CensusSerializer.deserialize(buffer);
3332
}
3433

35-
/** Returns the current thread-local {@link CensusContext}. */
3634
@Override
3735
public CensusContext getCurrent() {
3836
return CensusCurrentContext.get();
3937
}
4038

41-
/** Returns the default {@link CensusContext}. */
4239
@Override
4340
public CensusContext getDefault() {
4441
return DEFAULT;

core_native/java/com/google/census/CensusContextImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ public CensusContextImpl record(MetricMap stats) {
3434
return this;
3535
}
3636

37+
/**
38+
* Serializes a {@link CensusContextImpl} into {@link CensusContextProto} serialized format. The
39+
* encoded tags are of the form: (<tag prefix> + 'key' + <tag delim> + 'value')*
40+
*/
3741
@Override
3842
public ByteBuffer serialize() {
3943
return CensusSerializer.serialize(this);

core_native/java/com/google/census/CensusSerializer.java

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,22 @@
1313

1414
package com.google.census;
1515

16-
import static java.nio.charset.StandardCharsets.UTF_8;
16+
import com.google.census.proto.CensusContextProto;
17+
import com.google.protobuf.InvalidProtocolBufferException;
1718

1819
import java.nio.ByteBuffer;
1920
import java.util.HashMap;
2021
import java.util.Map.Entry;
21-
2222
import javax.annotation.Nullable;
2323

2424
/** Native implementation {@link CensusContext} serialization. */
2525
final class CensusSerializer {
2626
private static final char TAG_PREFIX = '\2';
2727
private static final char TAG_DELIM = '\3';
2828

29-
// The serialized tags are of the form: (<tag prefix> + 'key' + <tag delim> + 'value')*
29+
30+
// Serializes a CensusContext by transforming it into a CensusContextProto. The
31+
// encoded tags are of the form: (<tag prefix> + 'key' + <tag delim> + 'value')*
3032
static ByteBuffer serialize(CensusContextImpl context) {
3133
StringBuilder builder = new StringBuilder();
3234
for (Entry<String, String> tag : context.tags.entrySet()) {
@@ -36,27 +38,58 @@ static ByteBuffer serialize(CensusContextImpl context) {
3638
.append(TAG_DELIM)
3739
.append(tag.getValue());
3840
}
39-
return ByteBuffer.wrap(builder.toString().getBytes(UTF_8));
41+
return ByteBuffer.wrap(CensusContextProto.CensusContext.
42+
newBuilder().setTags(builder.toString()).build().toByteArray());
4043
}
4144

42-
// The serialized tags are of the form: (<tag prefix> + 'key' + <tag delim> + 'value')*
45+
// Deserializes based on an serialized CensusContextProto. The encoded tags are of the form:
46+
// (<tag prefix> + 'key' + <tag delim> + 'value')*
4347
@Nullable
4448
static CensusContextImpl deserialize(ByteBuffer buffer) {
45-
String input = new String(buffer.array(), UTF_8);
46-
HashMap<String, String> tags = new HashMap<>();
47-
if (!input.matches("(\2[^\2\3]*\3[^\2\3]*)*")) {
49+
try {
50+
CensusContextProto.CensusContext context =
51+
CensusContextProto.CensusContext.parser().parseFrom(buffer.array());
52+
return new CensusContextImpl(fromString(context.getTags()));
53+
} catch (IllegalArgumentException | InvalidProtocolBufferException e) {
4854
return null;
4955
}
50-
if (!input.isEmpty()) {
51-
int keyIndex = 0;
52-
do {
53-
int valIndex = input.indexOf(TAG_DELIM, keyIndex + 1);
54-
String key = input.substring(keyIndex + 1, valIndex);
55-
keyIndex = input.indexOf(TAG_PREFIX, valIndex + 1);
56-
String val = input.substring(valIndex + 1, keyIndex == -1 ? input.length() : keyIndex);
57-
tags.put(key, val);
58-
} while (keyIndex != -1);
56+
}
57+
58+
private static HashMap<String, String> fromString(String encoded) {
59+
HashMap<String, String> tags = new HashMap<>();
60+
int length = encoded.length();
61+
int index = 0;
62+
while (index != length) {
63+
int valIndex = endOfKey(encoded, index);
64+
String key = encoded.substring(index + 1, valIndex);
65+
index = endOfValue(encoded, valIndex);
66+
String val = encoded.substring(valIndex + 1, index);
67+
tags.put(key, val);
68+
}
69+
return tags;
70+
}
71+
72+
private static int endOfKey(String encoded, int index) {
73+
int valIndex = encoded.indexOf(TAG_DELIM, index);
74+
if (valIndex == -1) {
75+
throw new IllegalArgumentException("Missing tag delimiter.");
76+
}
77+
int keyIndex = encoded.lastIndexOf(TAG_PREFIX, valIndex);
78+
if (keyIndex != index) {
79+
throw new IllegalArgumentException("Missing tag prefix.");
80+
}
81+
return valIndex;
82+
}
83+
84+
private static int endOfValue(String encoded, int index) {
85+
int keyIndex = encoded.indexOf(TAG_PREFIX, index);
86+
if (keyIndex == -1) {
87+
keyIndex = encoded.length();
88+
}
89+
int valIndex = encoded.lastIndexOf(TAG_DELIM, keyIndex);
90+
if (valIndex != index) {
91+
throw new IllegalArgumentException("Missing tag delimiter.");
5992
}
60-
return new CensusContextImpl(tags);
93+
return keyIndex;
6194
}
6295
}

0 commit comments

Comments
 (0)