2222import com .google .common .cache .CacheBuilder ;
2323import java .time .Duration ;
2424import java .util .Objects ;
25- import java .util .concurrent .ConcurrentHashMap ;
2625import java .util .concurrent .ExecutionException ;
2726import java .util .concurrent .TimeUnit ;
28- import java .util .concurrent .atomic .AtomicInteger ;
2927
3028/** Shared process-local latency scores for routed Spanner endpoints. */
3129final class EndpointLatencyRegistry {
@@ -39,28 +37,62 @@ final class EndpointLatencyRegistry {
3937
4038 private static volatile Cache <TrackerKey , LatencyTracker > TRACKERS =
4139 newTrackerCache (Ticker .systemTicker ());
42- private static final ConcurrentHashMap <String , AtomicInteger > INFLIGHT_REQUESTS =
43- new ConcurrentHashMap <>();
4440
4541 private EndpointLatencyRegistry () {}
4642
4743 static boolean hasScore (
4844 @ javax .annotation .Nullable String databaseScope ,
4945 long operationUid ,
5046 String endpointLabelOrAddress ) {
51- TrackerKey trackerKey = trackerKey (databaseScope , operationUid , endpointLabelOrAddress );
47+ return hasScore (databaseScope , operationUid , false , endpointLabelOrAddress );
48+ }
49+
50+ static boolean hasScore (
51+ @ javax .annotation .Nullable String databaseScope ,
52+ long operationUid ,
53+ boolean preferLeader ,
54+ String endpointLabelOrAddress ) {
55+ TrackerKey trackerKey =
56+ trackerKey (databaseScope , operationUid , preferLeader , endpointLabelOrAddress );
5257 return trackerKey != null && TRACKERS .getIfPresent (trackerKey ) != null ;
5358 }
5459
5560 static double getSelectionCost (
5661 @ javax .annotation .Nullable String databaseScope ,
5762 long operationUid ,
5863 String endpointLabelOrAddress ) {
59- TrackerKey trackerKey = trackerKey (databaseScope , operationUid , endpointLabelOrAddress );
64+ return getSelectionCost (databaseScope , operationUid , false , null , endpointLabelOrAddress );
65+ }
66+
67+ static double getSelectionCost (
68+ @ javax .annotation .Nullable String databaseScope ,
69+ long operationUid ,
70+ boolean preferLeader ,
71+ String endpointLabelOrAddress ) {
72+ return getSelectionCost (
73+ databaseScope , operationUid , preferLeader , null , endpointLabelOrAddress );
74+ }
75+
76+ static double getSelectionCost (
77+ @ javax .annotation .Nullable String databaseScope ,
78+ long operationUid ,
79+ @ javax .annotation .Nullable ChannelEndpoint endpoint ,
80+ String endpointLabelOrAddress ) {
81+ return getSelectionCost (databaseScope , operationUid , false , endpoint , endpointLabelOrAddress );
82+ }
83+
84+ static double getSelectionCost (
85+ @ javax .annotation .Nullable String databaseScope ,
86+ long operationUid ,
87+ boolean preferLeader ,
88+ @ javax .annotation .Nullable ChannelEndpoint endpoint ,
89+ String endpointLabelOrAddress ) {
90+ TrackerKey trackerKey =
91+ trackerKey (databaseScope , operationUid , preferLeader , endpointLabelOrAddress );
6092 if (trackerKey == null ) {
6193 return Double .MAX_VALUE ;
6294 }
63- double activeRequests = getInflight ( endpointLabelOrAddress );
95+ double activeRequests = endpoint == null ? 0.0 : endpoint . getActiveRequestCount ( );
6496 LatencyTracker tracker = TRACKERS .getIfPresent (trackerKey );
6597 if (tracker != null ) {
6698 return tracker .getScore () * (activeRequests + 1.0 );
@@ -76,7 +108,17 @@ static void recordLatency(
76108 long operationUid ,
77109 String endpointLabelOrAddress ,
78110 Duration latency ) {
79- TrackerKey trackerKey = trackerKey (databaseScope , operationUid , endpointLabelOrAddress );
111+ recordLatency (databaseScope , operationUid , false , endpointLabelOrAddress , latency );
112+ }
113+
114+ static void recordLatency (
115+ @ javax .annotation .Nullable String databaseScope ,
116+ long operationUid ,
117+ boolean preferLeader ,
118+ String endpointLabelOrAddress ,
119+ Duration latency ) {
120+ TrackerKey trackerKey =
121+ trackerKey (databaseScope , operationUid , preferLeader , endpointLabelOrAddress );
80122 if (trackerKey == null || latency == null ) {
81123 return ;
82124 }
@@ -87,54 +129,43 @@ static void recordError(
87129 @ javax .annotation .Nullable String databaseScope ,
88130 long operationUid ,
89131 String endpointLabelOrAddress ) {
90- recordError (databaseScope , operationUid , endpointLabelOrAddress , DEFAULT_ERROR_PENALTY );
132+ recordError (databaseScope , operationUid , false , endpointLabelOrAddress , DEFAULT_ERROR_PENALTY );
91133 }
92134
93135 static void recordError (
94136 @ javax .annotation .Nullable String databaseScope ,
95137 long operationUid ,
96- String endpointLabelOrAddress ,
97- Duration penalty ) {
98- TrackerKey trackerKey = trackerKey (databaseScope , operationUid , endpointLabelOrAddress );
99- if (trackerKey == null || penalty == null ) {
100- return ;
101- }
102- getOrCreateTracker (trackerKey ).recordError (penalty );
138+ boolean preferLeader ,
139+ String endpointLabelOrAddress ) {
140+ recordError (
141+ databaseScope , operationUid , preferLeader , endpointLabelOrAddress , DEFAULT_ERROR_PENALTY );
103142 }
104143
105- static void beginRequest ( String endpointLabelOrAddress ) {
106- String address = normalizeAddress ( endpointLabelOrAddress );
107- if ( address == null ) {
108- return ;
109- }
110- INFLIGHT_REQUESTS . computeIfAbsent ( address , ignored -> new AtomicInteger ()). incrementAndGet ( );
144+ static void recordError (
145+ @ javax . annotation . Nullable String databaseScope ,
146+ long operationUid ,
147+ String endpointLabelOrAddress ,
148+ Duration penalty ) {
149+ recordError ( databaseScope , operationUid , false , endpointLabelOrAddress , penalty );
111150 }
112151
113- static void finishRequest (String endpointLabelOrAddress ) {
114- String address = normalizeAddress (endpointLabelOrAddress );
115- if (address == null ) {
116- return ;
117- }
118- AtomicInteger counter = INFLIGHT_REQUESTS .get (address );
119- if (counter == null ) {
152+ static void recordError (
153+ @ javax .annotation .Nullable String databaseScope ,
154+ long operationUid ,
155+ boolean preferLeader ,
156+ String endpointLabelOrAddress ,
157+ Duration penalty ) {
158+ TrackerKey trackerKey =
159+ trackerKey (databaseScope , operationUid , preferLeader , endpointLabelOrAddress );
160+ if (trackerKey == null || penalty == null ) {
120161 return ;
121162 }
122- counter .updateAndGet (current -> current > 0 ? current - 1 : 0 );
123- }
124-
125- static int getInflight (String endpointLabelOrAddress ) {
126- String address = normalizeAddress (endpointLabelOrAddress );
127- if (address == null ) {
128- return 0 ;
129- }
130- AtomicInteger counter = INFLIGHT_REQUESTS .get (address );
131- return counter == null ? 0 : Math .max (0 , counter .get ());
163+ getOrCreateTracker (trackerKey ).recordError (penalty );
132164 }
133165
134166 @ VisibleForTesting
135167 static void clear () {
136168 TRACKERS .invalidateAll ();
137- INFLIGHT_REQUESTS .clear ();
138169 }
139170
140171 @ VisibleForTesting
@@ -155,11 +186,20 @@ static TrackerKey trackerKey(
155186 @ javax .annotation .Nullable String databaseScope ,
156187 long operationUid ,
157188 String endpointLabelOrAddress ) {
189+ return trackerKey (databaseScope , operationUid , false , endpointLabelOrAddress );
190+ }
191+
192+ @ VisibleForTesting
193+ static TrackerKey trackerKey (
194+ @ javax .annotation .Nullable String databaseScope ,
195+ long operationUid ,
196+ boolean preferLeader ,
197+ String endpointLabelOrAddress ) {
158198 String address = normalizeAddress (endpointLabelOrAddress );
159199 if (operationUid <= 0 || address == null ) {
160200 return null ;
161201 }
162- return new TrackerKey (normalizeScope (databaseScope ), operationUid , address );
202+ return new TrackerKey (normalizeScope (databaseScope ), operationUid , preferLeader , address );
163203 }
164204
165205 private static long defaultRttMicros () {
@@ -190,11 +230,14 @@ private static Cache<TrackerKey, LatencyTracker> newTrackerCache(Ticker ticker)
190230 static final class TrackerKey {
191231 private final String databaseScope ;
192232 private final long operationUid ;
233+ private final boolean preferLeader ;
193234 private final String address ;
194235
195- private TrackerKey (String databaseScope , long operationUid , String address ) {
236+ private TrackerKey (
237+ String databaseScope , long operationUid , boolean preferLeader , String address ) {
196238 this .databaseScope = databaseScope ;
197239 this .operationUid = operationUid ;
240+ this .preferLeader = preferLeader ;
198241 this .address = address ;
199242 }
200243
@@ -208,18 +251,19 @@ public boolean equals(Object other) {
208251 }
209252 TrackerKey that = (TrackerKey ) other ;
210253 return operationUid == that .operationUid
254+ && preferLeader == that .preferLeader
211255 && Objects .equals (databaseScope , that .databaseScope )
212256 && Objects .equals (address , that .address );
213257 }
214258
215259 @ Override
216260 public int hashCode () {
217- return Objects .hash (databaseScope , operationUid , address );
261+ return Objects .hash (databaseScope , operationUid , preferLeader , address );
218262 }
219263
220264 @ Override
221265 public String toString () {
222- return databaseScope + ":" + operationUid + "@" + address ;
266+ return databaseScope + ":" + operationUid + ":" + preferLeader + " @" + address ;
223267 }
224268 }
225269}
0 commit comments