1919import static java .util .concurrent .TimeUnit .NANOSECONDS ;
2020
2121import com .datastax .driver .core .policies .ReconnectionPolicy ;
22+ import java .util .concurrent .ConcurrentHashMap ;
23+ import java .util .concurrent .ConcurrentMap ;
2224import java .util .concurrent .atomic .AtomicInteger ;
2325
2426/**
@@ -45,7 +47,8 @@ abstract class ConvictionPolicy {
4547 *
4648 * @return whether the host should be considered down.
4749 */
48- abstract boolean signalConnectionFailure (Connection connection , boolean decrement );
50+ abstract boolean signalConnectionFailure (
51+ Connection connection , boolean decrement , boolean hostIsDown );
4952
5053 abstract boolean canReconnectNow ();
5154
@@ -57,92 +60,111 @@ interface Factory {
5760 /**
5861 * Creates a new ConvictionPolicy instance for {@code host}.
5962 *
60- * @param host the host this policy applies to
63+ * @param endpoint the host this policy applies to
6164 * @return the newly created {@link ConvictionPolicy} instance.
6265 */
63- ConvictionPolicy create (Host host , ReconnectionPolicy reconnectionPolicy );
66+ ConvictionPolicy create (EndPoint endpoint );
6467 }
6568
6669 static class DefaultConvictionPolicy extends ConvictionPolicy {
67- private final Host host ;
70+ private final EndPoint endpoint ;
6871 private final ReconnectionPolicy reconnectionPolicy ;
6972 private final AtomicInteger openConnections = new AtomicInteger ();
7073
7174 private volatile long nextReconnectionTime = Long .MIN_VALUE ;
7275 private ReconnectionPolicy .ReconnectionSchedule reconnectionSchedule ;
7376
74- private DefaultConvictionPolicy (Host host , ReconnectionPolicy reconnectionPolicy ) {
75- this .host = host ;
77+ private DefaultConvictionPolicy (EndPoint endpoint , ReconnectionPolicy reconnectionPolicy ) {
78+ this .endpoint = endpoint ;
7679 this .reconnectionPolicy = reconnectionPolicy ;
7780 }
7881
7982 @ Override
8083 void signalConnectionsOpening (int count ) {
81- int newTotal = openConnections .addAndGet (count );
84+ int newTotal = this . openConnections .addAndGet (count );
8285 Host .statesLogger .debug (
83- "[{}] preparing to open {} new connections, total = {}" , host , count , newTotal );
86+ "[{}] preparing to open {} new connections, total = {}" , endpoint , count , newTotal );
8487 resetReconnectionTime ();
8588 }
8689
8790 @ Override
8891 void signalConnectionClosed (Connection connection ) {
89- int remaining = openConnections .decrementAndGet ();
92+ int remaining = this . openConnections .decrementAndGet ();
9093 assert remaining >= 0 ;
91- Host .statesLogger .debug ("[{}] {} closed, remaining = {}" , host , connection , remaining );
94+ Host .statesLogger .debug ("[{}] {} closed, remaining = {}" , endpoint , connection , remaining );
9295 }
9396
9497 @ Override
95- boolean signalConnectionFailure (Connection connection , boolean decrement ) {
98+ boolean signalConnectionFailure (Connection connection , boolean decrement , boolean hostIsDown ) {
9699 int remaining ;
97100 if (decrement ) {
98- if (host . state != Host . State . DOWN ) updateReconnectionTime ();
101+ if (! hostIsDown ) updateReconnectionTime ();
99102
100- remaining = openConnections .decrementAndGet ();
103+ remaining = this . openConnections .decrementAndGet ();
101104 assert remaining >= 0 ;
102- Host .statesLogger .debug ("[{}] {} failed, remaining = {}" , host , connection , remaining );
105+ Host .statesLogger .debug ("[{}] {} failed, remaining = {}" , endpoint , connection , remaining );
103106 } else {
104- remaining = openConnections .get ();
107+ remaining = this . openConnections .get ();
105108 }
106109 return remaining == 0 ;
107110 }
108111
109112 private synchronized void updateReconnectionTime () {
110113 long now = System .nanoTime ();
111- if (nextReconnectionTime > now )
114+ if (this . nextReconnectionTime > now )
112115 // Someone else updated the time before us
113116 return ;
114117
115- if (reconnectionSchedule == null ) reconnectionSchedule = reconnectionPolicy .newSchedule ();
118+ if (this .reconnectionSchedule == null )
119+ this .reconnectionSchedule = reconnectionPolicy .newSchedule ();
116120
117- long nextDelayMs = reconnectionSchedule .nextDelayMs ();
121+ long nextDelayMs = this . reconnectionSchedule .nextDelayMs ();
118122 Host .statesLogger .debug (
119- "[{}] preventing new connections for the next {} ms" , host , nextDelayMs );
120- nextReconnectionTime = now + NANOSECONDS .convert (nextDelayMs , MILLISECONDS );
123+ "[{}] preventing new connections for the next {} ms" , endpoint , nextDelayMs );
124+ this . nextReconnectionTime = now + NANOSECONDS .convert (nextDelayMs , MILLISECONDS );
121125 }
122126
123127 private synchronized void resetReconnectionTime () {
124- reconnectionSchedule = null ;
125- nextReconnectionTime = Long .MIN_VALUE ;
128+ this . reconnectionSchedule = null ;
129+ this . nextReconnectionTime = Long .MIN_VALUE ;
126130 }
127131
128132 @ Override
129133 boolean canReconnectNow () {
130134 boolean canReconnectNow =
131- nextReconnectionTime == Long .MIN_VALUE || System .nanoTime () >= nextReconnectionTime ;
135+ this .nextReconnectionTime == Long .MIN_VALUE
136+ || System .nanoTime () >= this .nextReconnectionTime ;
132137 Host .statesLogger .trace ("canReconnectNow={}" , canReconnectNow );
133138 return canReconnectNow ;
134139 }
135140
141+ private static class ConvictionState {}
142+
136143 @ Override
137144 boolean hasActiveConnections () {
138- return openConnections .get () > 0 ;
145+ return this . openConnections .get () > 0 ;
139146 }
140147
141148 static class Factory implements ConvictionPolicy .Factory {
149+ private final ConcurrentMap <EndPoint , ConvictionPolicy > policyCache =
150+ new ConcurrentHashMap <>();
151+ private final ReconnectionPolicy reconnectionPolicy ;
152+
153+ public Factory (ReconnectionPolicy reconnectionPolicy ) {
154+ this .reconnectionPolicy = reconnectionPolicy ;
155+ }
142156
143157 @ Override
144- public ConvictionPolicy create (Host host , ReconnectionPolicy reconnectionPolicy ) {
145- return new DefaultConvictionPolicy (host , reconnectionPolicy );
158+ public ConvictionPolicy create (EndPoint endpoint ) {
159+ ConvictionPolicy convictionPolicy = policyCache .get (endpoint );
160+ if (convictionPolicy == null ) {
161+ convictionPolicy = new DefaultConvictionPolicy (endpoint , reconnectionPolicy );
162+ ConvictionPolicy alreadyExisting = policyCache .putIfAbsent (endpoint , convictionPolicy );
163+ if (alreadyExisting != null ) {
164+ return alreadyExisting ;
165+ }
166+ }
167+ return convictionPolicy ;
146168 }
147169 }
148170 }
0 commit comments