18
18
*/
19
19
package org .neo4j .driver .internal .net .pooling ;
20
20
21
- import java .util .ArrayList ;
22
21
import java .util .List ;
23
22
import java .util .Map ;
24
- import java .util .concurrent .BlockingQueue ;
25
23
import java .util .concurrent .ConcurrentHashMap ;
26
- import java .util .concurrent .LinkedBlockingQueue ;
27
24
import java .util .concurrent .atomic .AtomicBoolean ;
28
25
29
26
import org .neo4j .driver .internal .ConnectionSettings ;
35
32
import org .neo4j .driver .internal .spi .Connection ;
36
33
import org .neo4j .driver .internal .spi .ConnectionPool ;
37
34
import org .neo4j .driver .internal .util .Clock ;
35
+ import org .neo4j .driver .internal .util .Supplier ;
38
36
import org .neo4j .driver .v1 .AuthToken ;
39
37
import org .neo4j .driver .v1 .AuthTokens ;
40
38
import org .neo4j .driver .v1 .Logging ;
48
46
* try to return the session into the session pool, however if we failed to return it back, either because the pool
49
47
* is full or the pool is being cleaned on driver.close, then we directly close the connection attached with the
50
48
* session.
51
- *
49
+ * <p>
52
50
* The session is NOT meant to be thread safe, each thread should have an independent session and close it (return to
53
51
* pool) when the work with the session has been done.
54
- *
52
+ * <p>
55
53
* The driver is thread safe. Each thread could try to get a session from the pool and then return it to the pool
56
54
* at the same time.
57
55
*/
@@ -60,7 +58,8 @@ public class SocketConnectionPool implements ConnectionPool
60
58
/**
61
59
* Pools, organized by server address.
62
60
*/
63
- private final ConcurrentHashMap <BoltServerAddress ,BlockingQueue <PooledConnection >> pools = new ConcurrentHashMap <>();
61
+ private final ConcurrentHashMap <BoltServerAddress ,BlockingPooledConnectionQueue > pools =
62
+ new ConcurrentHashMap <>();
64
63
65
64
private final Clock clock = Clock .SYSTEM ;
66
65
@@ -73,7 +72,7 @@ public class SocketConnectionPool implements ConnectionPool
73
72
private final AtomicBoolean stopped = new AtomicBoolean ( false );
74
73
75
74
public SocketConnectionPool ( ConnectionSettings connectionSettings , SecurityPlan securityPlan ,
76
- PoolSettings poolSettings , Logging logging )
75
+ PoolSettings poolSettings , Logging logging )
77
76
{
78
77
this .connectionSettings = connectionSettings ;
79
78
this .securityPlan = securityPlan ;
@@ -94,41 +93,48 @@ private Connection connect( BoltServerAddress address ) throws ClientException
94
93
95
94
private static Map <String ,Value > tokenAsMap ( AuthToken token )
96
95
{
97
- if ( token instanceof InternalAuthToken )
96
+ if ( token instanceof InternalAuthToken )
98
97
{
99
98
return ((InternalAuthToken ) token ).toMap ();
100
99
}
101
100
else
102
101
{
103
- throw new ClientException ( "Unknown authentication token, `" + token + "`. Please use one of the supported " +
102
+ throw new ClientException (
103
+ "Unknown authentication token, `" + token + "`. Please use one of the supported " +
104
104
"tokens from `" + AuthTokens .class .getSimpleName () + "`." );
105
105
}
106
106
}
107
107
108
108
@ Override
109
- public Connection acquire ( BoltServerAddress address )
109
+ public Connection acquire ( final BoltServerAddress address )
110
110
{
111
111
if ( stopped .get () )
112
112
{
113
113
throw new IllegalStateException ( "Pool has been closed, cannot acquire new values." );
114
114
}
115
- BlockingQueue <PooledConnection > connections = pool ( address );
116
- PooledConnection conn = connections .poll ();
117
- if ( conn == null )
115
+ final BlockingPooledConnectionQueue connections = pool ( address );
116
+ Supplier <PooledConnection > supplier = new Supplier <PooledConnection >()
118
117
{
119
- conn = new PooledConnection ( connect ( address ), new
120
- PooledConnectionReleaseConsumer ( connections , stopped , new PooledConnectionValidator ( this , poolSettings ) ), clock );
121
- }
118
+ @ Override
119
+ public PooledConnection get ()
120
+ {
121
+ return new PooledConnection ( connect ( address ), new
122
+ PooledConnectionReleaseConsumer ( connections , stopped ,
123
+ new PooledConnectionValidator ( SocketConnectionPool .this , poolSettings ) ), clock );
124
+
125
+ }
126
+ };
127
+ PooledConnection conn = connections .acquire ( supplier );
122
128
conn .updateTimestamp ();
123
129
return conn ;
124
130
}
125
131
126
- private BlockingQueue < PooledConnection > pool ( BoltServerAddress address )
132
+ private BlockingPooledConnectionQueue pool ( BoltServerAddress address )
127
133
{
128
- BlockingQueue < PooledConnection > pool = pools .get ( address );
134
+ BlockingPooledConnectionQueue pool = pools .get ( address );
129
135
if ( pool == null )
130
136
{
131
- pool = new LinkedBlockingQueue <>( poolSettings .maxIdleConnectionPoolSize ());
137
+ pool = new BlockingPooledConnectionQueue ( poolSettings .maxIdleConnectionPoolSize () );
132
138
133
139
if ( pools .putIfAbsent ( address , pool ) != null )
134
140
{
@@ -142,19 +148,13 @@ private BlockingQueue<PooledConnection> pool( BoltServerAddress address )
142
148
@ Override
143
149
public void purge ( BoltServerAddress address )
144
150
{
145
- BlockingQueue < PooledConnection > connections = pools .remove ( address );
151
+ BlockingPooledConnectionQueue connections = pools .remove ( address );
146
152
if ( connections == null )
147
153
{
148
154
return ;
149
155
}
150
- while (!connections .isEmpty ())
151
- {
152
- PooledConnection connection = connections .poll ();
153
- if ( connection != null )
154
- {
155
- connection .dispose ();
156
- }
157
- }
156
+
157
+ connections .terminate ();
158
158
}
159
159
160
160
@ Override
@@ -166,41 +166,34 @@ public boolean hasAddress( BoltServerAddress address )
166
166
@ Override
167
167
public void close ()
168
168
{
169
- if ( !stopped .compareAndSet ( false , true ) )
169
+ if ( !stopped .compareAndSet ( false , true ) )
170
170
{
171
171
// already closed or some other thread already started close
172
172
return ;
173
173
}
174
174
175
- for ( BlockingQueue < PooledConnection > pool : pools .values () )
175
+ for ( BlockingPooledConnectionQueue pool : pools .values () )
176
176
{
177
- while ( !pool .isEmpty () )
178
- {
179
- PooledConnection conn = pool .poll ();
180
- if ( conn != null )
181
- {
182
- //close the underlying connection without adding it back to the queue
183
- conn .dispose ();
184
- }
185
- }
177
+ pool .terminate ();
186
178
}
187
179
188
180
pools .clear ();
189
181
}
190
182
183
+
191
184
//for testing
192
- public List <PooledConnection > connectionsForAddress (BoltServerAddress address )
185
+ public List <PooledConnection > connectionsForAddress ( BoltServerAddress address )
193
186
{
194
- LinkedBlockingQueue <PooledConnection > pooledConnections =
195
- (LinkedBlockingQueue <PooledConnection >) pools .get ( address );
196
- if (pooledConnections == null )
187
+ BlockingPooledConnectionQueue pooledConnections = pools .get ( address );
188
+ if ( pooledConnections == null )
197
189
{
198
190
return emptyList ();
199
191
}
200
192
else
201
193
{
202
- return new ArrayList <>( pooledConnections );
194
+ return pooledConnections . toList ( );
203
195
}
204
196
}
205
197
198
+
206
199
}
0 commit comments