Skip to content

Commit 422c53a

Browse files
committed
Support persisting class-name filters
1 parent dcf235c commit 422c53a

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

utils/src/main/java/datadog/instrument/utils/ClassNameFilter.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
package datadog.instrument.utils;
88

9+
import java.io.DataInput;
10+
import java.io.DataOutput;
11+
import java.io.IOException;
912
import java.util.Arrays;
1013

1114
/**
@@ -23,6 +26,8 @@ public final class ClassNameFilter {
2326
private static final int MIN_CAPACITY = 1 << 8;
2427
private static final int MAX_HASH_ATTEMPTS = 10;
2528

29+
private static final int FILE_MAGIC = 0xDD094172;
30+
2631
// fixed-size hashtable of encoded members, indexed by class-name
2732
private final long[] members;
2833
private final int slotMask;
@@ -43,6 +48,11 @@ public ClassNameFilter(int capacity) {
4348
members = new long[slotMask + 1];
4449
}
4550

51+
private ClassNameFilter(int slotMask, long[] members) {
52+
this.slotMask = slotMask;
53+
this.members = members;
54+
}
55+
4656
/**
4757
* Tests whether the given class-name is a member of the filter.
4858
*
@@ -106,6 +116,40 @@ public void clear() {
106116
Arrays.fill(members, 0);
107117
}
108118

119+
/**
120+
* Writes filter content to an external resource.
121+
*
122+
* @param out where to write the serialized filter
123+
* @throws IOException if the content cannot be written
124+
*/
125+
public void writeTo(DataOutput out) throws IOException {
126+
out.writeInt(FILE_MAGIC);
127+
out.writeInt(slotMask);
128+
for (long m : members) {
129+
out.writeLong(m);
130+
}
131+
}
132+
133+
/**
134+
* Reads filter content from an external resource.
135+
*
136+
* @param in the serialized filter content
137+
* @return deserialized class-name filter
138+
* @throws IOException if the content cannot be read
139+
*/
140+
public static ClassNameFilter readFrom(DataInput in) throws IOException {
141+
int magic = in.readInt();
142+
if (magic != FILE_MAGIC) {
143+
throw new IOException("Unexpected file magic " + magic);
144+
}
145+
int slotMask = in.readInt();
146+
long[] members = new long[slotMask + 1];
147+
for (int i = 0; i < members.length; i++) {
148+
members[i] = in.readLong();
149+
}
150+
return new ClassNameFilter(slotMask, members);
151+
}
152+
109153
/**
110154
* Computes a 32-bit 'class-code' that includes the length of the package-prefix and simple-name,
111155
* plus the first and last characters of the simple-name (each truncated to fit into 8-bits.)

utils/src/test/java/datadog/instrument/utils/ClassNameFilterTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
import static org.junit.jupiter.api.Assertions.assertFalse;
66
import static org.junit.jupiter.api.Assertions.assertTrue;
77

8+
import java.io.ByteArrayInputStream;
9+
import java.io.ByteArrayOutputStream;
10+
import java.io.DataInputStream;
11+
import java.io.DataOutputStream;
12+
import java.io.IOException;
13+
import java.io.InputStream;
14+
import java.io.UncheckedIOException;
815
import java.util.HashSet;
916
import java.util.Set;
1017
import org.junit.jupiter.api.Test;
@@ -74,4 +81,27 @@ void overflow() {
7481
}
7582
}
7683
}
84+
85+
@Test
86+
void roundTrip() {
87+
ClassNameFilter exporter = new ClassNameFilter(8);
88+
89+
exporter.add("example.MyClass");
90+
exporter.add("example.test.FB");
91+
exporter.add("example.test.Ea");
92+
93+
ClassNameFilter importer;
94+
try (ByteArrayOutputStream sink = new ByteArrayOutputStream()) {
95+
exporter.writeTo(new DataOutputStream(sink));
96+
try (InputStream source = new ByteArrayInputStream(sink.toByteArray())) {
97+
importer = ClassNameFilter.readFrom(new DataInputStream(source));
98+
}
99+
} catch (IOException e) {
100+
throw new UncheckedIOException(e);
101+
}
102+
103+
assertTrue(importer.contains("example.MyClass"));
104+
assertTrue(importer.contains("example.test.FB"));
105+
assertFalse(importer.contains("example.test.Ea"));
106+
}
77107
}

0 commit comments

Comments
 (0)