6
6
package com .microsoft .sqlserver .jdbc ;
7
7
8
8
import java .util .UUID ;
9
- import java .util .concurrent .locks .Lock ;
10
- import java .util .concurrent .locks .ReentrantLock ;
11
9
12
10
13
11
/**
14
12
* ActivityCorrelator provides the APIs to access the ActivityId in TLS
15
13
*/
16
14
final class ActivityCorrelator {
17
15
18
- private static ActivityId activityId ;
19
- private static Lock lockObject = new ReentrantLock ();
20
-
21
- // Get the current ActivityId in TLS
22
- static ActivityId getCurrent () {
23
- if (activityId == null ) {
24
- lockObject .lock ();
25
- if (activityId == null ) {
26
- activityId = new ActivityId ();
27
- }
28
- lockObject .unlock ();
16
+ private static ThreadLocal <ActivityId > t_ActivityId = new ThreadLocal <ActivityId >() {
17
+ @ Override
18
+ protected ActivityId initialValue () {
19
+ return new ActivityId ();
29
20
}
21
+ };
30
22
31
- return activityId ;
23
+ static ActivityId getCurrent () {
24
+ return t_ActivityId .get ();
32
25
}
33
26
34
27
// Increment the Sequence number of the ActivityId in TLS
35
28
// and return the ActivityId with new Sequence number
36
29
static ActivityId getNext () {
37
- // Get the current ActivityId in TLS
38
- ActivityId activityId = getCurrent ();
39
-
40
- // Increment the Sequence number
41
- activityId .increment ();
42
-
43
- return activityId ;
30
+ return getCurrent ().getIncrement ();
44
31
}
45
32
46
33
/*
@@ -53,35 +40,51 @@ private ActivityCorrelator() {}
53
40
class ActivityId {
54
41
private final UUID id ;
55
42
private long sequence ;
43
+ // Cache the string since it gets frequently referenced.
44
+ private String cachedToString ;
56
45
57
46
ActivityId () {
58
47
id = UUID .randomUUID ();
59
- sequence = 1 ;
48
+ // getNext() is called during prelogin and will be the logical "first call" after
49
+ // instantiation, incrementing this to >= 1 before any activity logs are written.
50
+ sequence = 0 ;
60
51
}
61
52
62
53
UUID getId () {
63
54
return id ;
64
55
}
65
56
66
57
long getSequence () {
58
+ // Edge case: A new thread re-uses an existing connection. Ensure sequence > 0.
59
+ if (sequence == 0L ) {
60
+ ++sequence ;
61
+ }
62
+
67
63
return sequence ;
68
64
}
69
65
70
- void increment () {
66
+ ActivityId getIncrement () {
67
+ cachedToString = null ;
71
68
if (sequence < 0xffffffffl ) // to get to 32-bit unsigned
72
69
{
73
70
++sequence ;
74
71
} else {
75
72
sequence = 0 ;
76
73
}
74
+
75
+ return this ;
77
76
}
78
77
79
78
@ Override
80
79
public String toString () {
81
- StringBuilder sb = new StringBuilder ();
82
- sb .append (id .toString ());
83
- sb .append ("-" );
84
- sb .append (sequence );
85
- return sb .toString ();
80
+ if (cachedToString == null ) {
81
+ StringBuilder sb = new StringBuilder (38 );
82
+ sb .append (id .toString ());
83
+ sb .append ("-" );
84
+ sb .append (getSequence ());
85
+ cachedToString = sb .toString ();
86
+ }
87
+
88
+ return cachedToString .toString ();
86
89
}
87
90
}
0 commit comments