13
13
*/
14
14
package org .asynchttpclient .netty .channel ;
15
15
16
- import static io .netty .util .internal .ThrowableUtil .unknownStackTrace ;
17
16
import io .netty .bootstrap .Bootstrap ;
18
17
import io .netty .buffer .ByteBufAllocator ;
19
18
import io .netty .channel .Channel ;
35
34
import io .netty .handler .logging .LoggingHandler ;
36
35
import io .netty .handler .ssl .SslHandler ;
37
36
import io .netty .handler .stream .ChunkedWriteHandler ;
38
- import io .netty .util .AttributeKey ;
39
37
import io .netty .util .Timer ;
40
38
import io .netty .util .concurrent .DefaultThreadFactory ;
41
39
import io .netty .util .concurrent .GlobalEventExecutor ;
42
40
43
- import java .io .IOException ;
44
41
import java .net .InetSocketAddress ;
45
42
import java .util .Map ;
46
43
import java .util .Map .Entry ;
47
- import java .util .concurrent .ConcurrentHashMap ;
48
44
import java .util .concurrent .ThreadFactory ;
49
45
import java .util .concurrent .TimeUnit ;
50
46
import java .util .function .Function ;
61
57
import org .asynchttpclient .channel .ChannelPool ;
62
58
import org .asynchttpclient .channel .ChannelPoolPartitioning ;
63
59
import org .asynchttpclient .channel .NoopChannelPool ;
64
- import org .asynchttpclient .exception .PoolAlreadyClosedException ;
65
- import org .asynchttpclient .exception .TooManyConnectionsException ;
66
- import org .asynchttpclient .exception .TooManyConnectionsPerHostException ;
67
60
import org .asynchttpclient .handler .AsyncHandlerExtensions ;
68
61
import org .asynchttpclient .netty .NettyResponseFuture ;
69
62
import org .asynchttpclient .netty .OnLastHttpContentCallback ;
@@ -93,30 +86,23 @@ public class ChannelManager {
93
86
public static final String AHC_WS_HANDLER = "ahc-ws" ;
94
87
public static final String LOGGING_HANDLER = "logging" ;
95
88
96
- private static final AttributeKey <Object > partitionKeyAttr = AttributeKey .valueOf (ChannelManager .class , "partitionKey" );
97
-
98
89
private final AsyncHttpClientConfig config ;
99
90
private final SslEngineFactory sslEngineFactory ;
100
91
private final EventLoopGroup eventLoopGroup ;
101
92
private final boolean allowReleaseEventLoopGroup ;
102
93
private final Bootstrap httpBootstrap ;
103
94
private final Bootstrap wsBootstrap ;
104
95
private final long handshakeTimeout ;
105
- private final IOException tooManyConnections ;
106
- private final IOException tooManyConnectionsPerHost ;
107
96
108
97
private final ChannelPool channelPool ;
109
98
private final ChannelGroup openChannels ;
110
- private final boolean maxTotalConnectionsEnabled ;
111
- private final NonBlockingSemaphoreLike freeChannels ;
112
- private final boolean maxConnectionsPerHostEnabled ;
113
- private final ConcurrentHashMap <Object , NonBlockingSemaphore > freeChannelsPerHost = new ConcurrentHashMap <>();
114
99
115
100
private AsyncHttpClientHandler wsHandler ;
116
101
117
102
public ChannelManager (final AsyncHttpClientConfig config , Timer nettyTimer ) {
118
103
119
104
this .config = config ;
105
+
120
106
this .sslEngineFactory = config .getSslEngineFactory () != null ? config .getSslEngineFactory () : new DefaultSslEngineFactory ();
121
107
try {
122
108
this .sslEngineFactory .init (config );
@@ -134,38 +120,7 @@ public ChannelManager(final AsyncHttpClientConfig config, Timer nettyTimer) {
134
120
}
135
121
this .channelPool = channelPool ;
136
122
137
-
138
- tooManyConnections = unknownStackTrace (new TooManyConnectionsException (config .getMaxConnections ()), ChannelManager .class , "acquireChannelLock" );
139
- tooManyConnectionsPerHost = unknownStackTrace (new TooManyConnectionsPerHostException (config .getMaxConnectionsPerHost ()), ChannelManager .class , "acquireChannelLock" );
140
- maxTotalConnectionsEnabled = config .getMaxConnections () > 0 ;
141
- maxConnectionsPerHostEnabled = config .getMaxConnectionsPerHost () > 0 ;
142
-
143
- freeChannels = maxTotalConnectionsEnabled ?
144
- new NonBlockingSemaphore (config .getMaxConnections ()) :
145
- NonBlockingSemaphoreInfinite .INSTANCE ;
146
-
147
- if (maxTotalConnectionsEnabled || maxConnectionsPerHostEnabled ) {
148
- openChannels = new DefaultChannelGroup ("asyncHttpClient" , GlobalEventExecutor .INSTANCE ) {
149
- @ Override
150
- public boolean remove (Object o ) {
151
- boolean removed = super .remove (o );
152
- if (removed ) {
153
- freeChannels .release ();
154
- if (maxConnectionsPerHostEnabled ) {
155
- Object partitionKey = Channel .class .cast (o ).attr (partitionKeyAttr ).getAndSet (null );
156
- if (partitionKey != null ) {
157
- NonBlockingSemaphore hostFreeChannels = freeChannelsPerHost .get (partitionKey );
158
- if (hostFreeChannels != null )
159
- hostFreeChannels .release ();
160
- }
161
- }
162
- }
163
- return removed ;
164
- }
165
- };
166
- } else {
167
- openChannels = new DefaultChannelGroup ("asyncHttpClient" , GlobalEventExecutor .INSTANCE );
168
- }
123
+ openChannels = new DefaultChannelGroup ("asyncHttpClient" , GlobalEventExecutor .INSTANCE );
169
124
170
125
handshakeTimeout = config .getHandshakeTimeout ();
171
126
@@ -315,10 +270,7 @@ public final void tryToOfferChannelToPool(Channel channel, AsyncHandler<?> async
315
270
Channels .setDiscard (channel );
316
271
if (asyncHandler instanceof AsyncHandlerExtensions )
317
272
AsyncHandlerExtensions .class .cast (asyncHandler ).onConnectionOffer (channel );
318
- if (channelPool .offer (channel , partitionKey )) {
319
- if (maxConnectionsPerHostEnabled )
320
- channel .attr (partitionKeyAttr ).setIfAbsent (partitionKey );
321
- } else {
273
+ if (!channelPool .offer (channel , partitionKey )) {
322
274
// rejected by pool
323
275
closeChannel (channel );
324
276
}
@@ -337,32 +289,6 @@ public boolean removeAll(Channel connection) {
337
289
return channelPool .removeAll (connection );
338
290
}
339
291
340
- private boolean tryAcquireGlobal () {
341
- return freeChannels .tryAcquire ();
342
- }
343
-
344
- private NonBlockingSemaphoreLike getFreeConnectionsForHost (Object partitionKey ) {
345
- return maxConnectionsPerHostEnabled ?
346
- freeChannelsPerHost .computeIfAbsent (partitionKey , pk -> new NonBlockingSemaphore (config .getMaxConnectionsPerHost ())) :
347
- NonBlockingSemaphoreInfinite .INSTANCE ;
348
- }
349
-
350
- private boolean tryAcquirePerHost (Object partitionKey ) {
351
- return getFreeConnectionsForHost (partitionKey ).tryAcquire ();
352
- }
353
-
354
- public void acquireChannelLock (Object partitionKey ) throws IOException {
355
- if (!channelPool .isOpen ())
356
- throw PoolAlreadyClosedException .INSTANCE ;
357
- if (!tryAcquireGlobal ())
358
- throw tooManyConnections ;
359
- if (!tryAcquirePerHost (partitionKey )) {
360
- freeChannels .release ();
361
-
362
- throw tooManyConnectionsPerHost ;
363
- }
364
- }
365
-
366
292
private void doClose () {
367
293
openChannels .close ();
368
294
channelPool .destroy ();
@@ -383,16 +309,8 @@ public void closeChannel(Channel channel) {
383
309
Channels .silentlyCloseChannel (channel );
384
310
}
385
311
386
- public void releaseChannelLock (Object partitionKey ) {
387
- freeChannels .release ();
388
- getFreeConnectionsForHost (partitionKey ).release ();
389
- }
390
-
391
312
public void registerOpenChannel (Channel channel , Object partitionKey ) {
392
313
openChannels .add (channel );
393
- if (maxConnectionsPerHostEnabled ) {
394
- channel .attr (partitionKeyAttr ).set (partitionKey );
395
- }
396
314
}
397
315
398
316
private HttpClientCodec newHttpClientCodec () {
@@ -520,4 +438,8 @@ public ClientStats getClientStats() {
520
438
));
521
439
return new ClientStats (statsPerHost );
522
440
}
441
+
442
+ public boolean isOpen () {
443
+ return channelPool .isOpen ();
444
+ }
523
445
}
0 commit comments