24
24
import java .util .LinkedList ;
25
25
import java .util .List ;
26
26
import java .util .ServiceLoader ;
27
+ import java .util .concurrent .BlockingQueue ;
27
28
import java .util .concurrent .ConcurrentHashMap ;
28
- import java .util .concurrent .TimeUnit ;
29
+ import java .util .concurrent .LinkedBlockingQueue ;
29
30
30
31
import org .neo4j .driver .internal .connector .socket .SocketConnector ;
31
32
import org .neo4j .driver .internal .spi .Connection ;
32
33
import org .neo4j .driver .internal .spi .ConnectionPool ;
33
34
import org .neo4j .driver .internal .spi .Connector ;
34
35
import org .neo4j .driver .internal .util .Clock ;
35
- import org .neo4j .driver .internal .util .Consumer ;
36
36
import org .neo4j .driver .v1 .AuthToken ;
37
37
import org .neo4j .driver .v1 .Config ;
38
38
import org .neo4j .driver .v1 .exceptions .ClientException ;
@@ -62,36 +62,23 @@ public class InternalConnectionPool implements ConnectionPool
62
62
/**
63
63
* Pools, organized by URL.
64
64
*/
65
- private final ConcurrentHashMap <URI ,ThreadCachingPool <PooledConnection >> pools = new ConcurrentHashMap <>();
66
-
67
- /**
68
- * Connections that fail this criteria will be disposed of.
69
- */
70
- private final ValidationStrategy <PooledConnection > connectionValidation ;
65
+ private final ConcurrentHashMap <URI ,BlockingQueue <PooledConnection >> pools = new ConcurrentHashMap <>();
71
66
72
67
private final AuthToken authToken ;
73
- /**
74
- * Timeout in milliseconds if there are no available sessions.
75
- */
76
- private final long acquireSessionTimeout ;
77
-
78
68
private final Clock clock ;
79
69
private final Config config ;
80
70
81
71
public InternalConnectionPool ( Config config , AuthToken authToken )
82
72
{
83
- this ( loadConnectors (), Clock .SYSTEM , config , authToken ,
84
- Long .getLong ( "neo4j.driver.acquireSessionTimeout" , 30_000 ) );
73
+ this ( loadConnectors (), Clock .SYSTEM , config , authToken );
85
74
}
86
75
87
76
public InternalConnectionPool ( Collection <Connector > conns , Clock clock , Config config ,
88
- AuthToken authToken , long acquireTimeout )
77
+ AuthToken authToken )
89
78
{
90
79
this .authToken = authToken ;
91
- this .acquireSessionTimeout = acquireTimeout ;
92
80
this .config = config ;
93
81
this .clock = clock ;
94
- this .connectionValidation = new PooledConnectionValidator ( config .idleTimeBeforeConnectionTest () );
95
82
for ( Connector connector : conns )
96
83
{
97
84
for ( String s : connector .supportedSchemes () )
@@ -104,37 +91,32 @@ public InternalConnectionPool( Collection<Connector> conns, Clock clock, Config
104
91
@ Override
105
92
public Connection acquire ( URI sessionURI )
106
93
{
107
- try
108
- {
109
- Connection conn = pool ( sessionURI ).acquire ( acquireSessionTimeout , TimeUnit .MILLISECONDS );
94
+ BlockingQueue <PooledConnection > connections = pool ( sessionURI );
95
+ PooledConnection conn = connections .poll ();
110
96
if ( conn == null )
111
97
{
112
- throw new ClientException (
113
- "Failed to acquire a session with Neo4j " +
114
- "as all the connections in the connection pool are already occupied by other sessions. " +
115
- "Please close unused session and retry. " +
116
- "Current Pool size: " + config .connectionPoolSize () +
117
- ". If your application requires running more sessions concurrently than the current pool " +
118
- "size, you should create a driver with a larger connection pool size." );
98
+ Connector connector = connectors .get ( sessionURI .getScheme () );
99
+ if ( connector == null )
100
+ {
101
+ throw new ClientException (
102
+ format ( "Unsupported URI scheme: '%s' in url: '%s'. Supported transports are: '%s'." ,
103
+ sessionURI .getScheme (), sessionURI , connectorSchemes () ) );
104
+ }
105
+ conn = new PooledConnection (connector .connect ( sessionURI , config , authToken ), new PooledConnectionReleaseConsumer ( connections , config ), clock );
119
106
}
107
+ conn .updateUsageTimestamp ();
120
108
return conn ;
121
- }
122
- catch ( InterruptedException e )
123
- {
124
- throw new ClientException ( "Interrupted while waiting for a connection to Neo4j." );
125
- }
126
109
}
127
110
128
- private ThreadCachingPool <PooledConnection > pool ( URI sessionURI )
111
+ private BlockingQueue <PooledConnection > pool ( URI sessionURI )
129
112
{
130
- ThreadCachingPool <PooledConnection > pool = pools .get ( sessionURI );
113
+ BlockingQueue <PooledConnection > pool = pools .get ( sessionURI );
131
114
if ( pool == null )
132
115
{
133
- pool = newPool ( sessionURI );
116
+ pool = new LinkedBlockingQueue <>( config . maxIdleConnectionPoolSize () );
134
117
if ( pools .putIfAbsent ( sessionURI , pool ) != null )
135
118
{
136
119
// We lost a race to create the pool, dispose of the one we created, and recurse
137
- pool .close ();
138
120
return pool ( sessionURI );
139
121
}
140
122
}
@@ -161,48 +143,24 @@ private static Collection<Connector> loadConnectors()
161
143
@ Override
162
144
public void close () throws Neo4jException
163
145
{
164
- for ( ThreadCachingPool <PooledConnection > pool : pools .values () )
146
+ for ( BlockingQueue <PooledConnection > pool : pools .values () )
165
147
{
166
- pool .close ();
148
+ while ( !pool .isEmpty () )
149
+ {
150
+ PooledConnection conn = pool .poll ();
151
+ if ( conn != null )
152
+ {
153
+ //close the underlying connection without adding it back to the queue
154
+ conn .dispose ();
155
+ }
156
+ }
167
157
}
158
+
168
159
pools .clear ();
169
160
}
170
161
171
162
private String connectorSchemes ()
172
163
{
173
164
return Arrays .toString ( connectors .keySet ().toArray ( new String [connectors .keySet ().size ()] ) );
174
165
}
175
-
176
- private ThreadCachingPool <PooledConnection > newPool ( final URI uri )
177
- {
178
-
179
- return new ThreadCachingPool <>( config .connectionPoolSize (), new Allocator <PooledConnection >()
180
- {
181
- @ Override
182
- public PooledConnection allocate ( Consumer <PooledConnection > release )
183
- {
184
- Connector connector = connectors .get ( uri .getScheme () );
185
- if ( connector == null )
186
- {
187
- throw new ClientException (
188
- format ( "Unsupported URI scheme: '%s' in url: '%s'. Supported transports are: '%s'." ,
189
- uri .getScheme (), uri , connectorSchemes () ) );
190
- }
191
- Connection conn = connector .connect ( uri , config , authToken );
192
- return new PooledConnection ( conn , release );
193
- }
194
-
195
- @ Override
196
- public void onDispose ( PooledConnection pooledConnection )
197
- {
198
- pooledConnection .dispose ();
199
- }
200
-
201
- @ Override
202
- public void onAcquire ( PooledConnection pooledConnection )
203
- {
204
-
205
- }
206
- }, connectionValidation , clock );
207
- }
208
166
}
0 commit comments