Skip to content

Commit 4103ea0

Browse files
authored
Thread safety (#383)
* Thread safety fixes
1 parent 711e48c commit 4103ea0

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

aws-xray-recorder-sdk-core/src/main/java/com/amazonaws/xray/entities/SubsegmentImpl.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020
import com.fasterxml.jackson.annotation.JsonIgnore;
2121
import com.fasterxml.jackson.core.JsonProcessingException;
2222
import com.fasterxml.jackson.databind.node.ObjectNode;
23-
import java.util.HashSet;
23+
import java.util.Collections;
2424
import java.util.Set;
25+
import java.util.concurrent.ConcurrentHashMap;
2526
import org.apache.commons.logging.Log;
2627
import org.apache.commons.logging.LogFactory;
2728
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -64,7 +65,7 @@ public SubsegmentImpl(AWSXRayRecorder creator,
6465
super(creator, name);
6566
this.parentSegment = parentSegment;
6667
parentSegment.incrementReferenceCount();
67-
this.precursorIds = new HashSet<>();
68+
this.precursorIds = Collections.newSetFromMap(new ConcurrentHashMap<>());
6869
this.shouldPropagate = true;
6970

7071
this.isSampled = samplingStrategyOverride == SamplingStrategyOverride.DISABLED ?

aws-xray-recorder-sdk-core/src/test/java/com/amazonaws/xray/ConcurrencyTest.java

+33
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@
1616
package com.amazonaws.xray;
1717

1818
import com.amazonaws.xray.emitters.Emitter;
19+
import com.amazonaws.xray.entities.Segment;
20+
import com.amazonaws.xray.entities.SegmentImpl;
21+
import com.amazonaws.xray.entities.SubsegmentImpl;
1922
import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy;
23+
import java.util.Iterator;
24+
import java.util.Random;
25+
import java.util.concurrent.Callable;
2026
import java.util.concurrent.CountDownLatch;
2127
import java.util.concurrent.ExecutorService;
2228
import java.util.concurrent.Executors;
@@ -64,4 +70,31 @@ void testManyThreads() throws InterruptedException {
6470
}
6571
}
6672

73+
@Test
74+
public void testPrecursorIdConcurrency() throws Exception {
75+
Segment seg = new SegmentImpl(AWSXRay.getGlobalRecorder(), "test");
76+
SubsegmentImpl subseg = new SubsegmentImpl(AWSXRay.getGlobalRecorder(), "test", seg);
77+
78+
final long startTime = System.currentTimeMillis();
79+
80+
Thread thread1 = new Thread(() -> {
81+
while (true) {
82+
subseg.addPrecursorId("ID" + new Random().nextInt());
83+
}
84+
});
85+
thread1.start();
86+
87+
Callable<Void> callable = (Callable) () -> {
88+
while (System.currentTimeMillis() - startTime < TimeUnit.SECONDS.toMillis(1)) {
89+
Iterator it = subseg.getPrecursorIds().iterator();
90+
while (it.hasNext()) {
91+
it.next();
92+
}
93+
}
94+
return null;
95+
};
96+
callable.call();
97+
98+
thread1.join();
99+
}
67100
}

aws-xray-recorder-sdk-core/src/test/java/com/amazonaws/xray/entities/EntityTest.java

+12
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ void testUnknownClassSerialization() {
7676
seg.serialize(); // Verify we don't crash here
7777
}
7878

79+
@Test
80+
void testPrecursorIds() {
81+
Segment seg = new SegmentImpl(AWSXRay.getGlobalRecorder(), "test");
82+
SubsegmentImpl subseg = new SubsegmentImpl(AWSXRay.getGlobalRecorder(), "test", seg);
83+
subseg.addPrecursorId("myId1");
84+
subseg.addPrecursorId("myId2");
85+
String serializedSubSeg = subseg.serialize();
86+
87+
String expected = "\"precursor_ids\":[\"myId1\",\"myId2\"]";
88+
assertThat(serializedSubSeg).contains(expected);
89+
}
90+
7991
static class EmptyBean {
8092
String otherField = "cerealization";
8193
}

0 commit comments

Comments
 (0)