io.edurt.datacap.pinot.com.ning.http.client.providers.grizzly.ConnectionManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of datacap-shaded-pinot Show documentation
Show all versions of datacap-shaded-pinot Show documentation
DataCap - Shaded for Apache Pinot
/*
* Copyright (c) 2012-2015 Sonatype, Inc. All rights reserved.
*
* This program is licensed to you under the Apache License Version 2.0,
* and you may not use this file except in compliance with the Apache License Version 2.0.
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the Apache License Version 2.0 is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
*/
package io.edurt.datacap.pinot.com.ning.http.client.providers.grizzly;
import io.edurt.datacap.pinot.com.ning.http.client.AsyncHttpClientConfig;
import io.edurt.datacap.pinot.com.ning.http.client.ProxyServer;
import io.edurt.datacap.pinot.com.ning.http.client.Request;
import io.edurt.datacap.pinot.com.ning.http.client.uri.Uri;
import io.edurt.datacap.pinot.com.ning.http.util.ProxyUtils;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.glassfish.grizzly.CompletionHandler;
import org.glassfish.grizzly.Connection;
import org.glassfish.grizzly.ConnectorHandler;
import org.glassfish.grizzly.GrizzlyFuture;
import org.glassfish.grizzly.connectionpool.Endpoint;
import org.glassfish.grizzly.connectionpool.MultiEndpointPool;
import org.glassfish.grizzly.nio.transport.TCPNIOConnectorHandler;
import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
import org.glassfish.grizzly.utils.Exceptions;
/**
* Connection manager
*
* @author Grizzly team
*/
class ConnectionManager {
private final boolean poolingEnabled;
private final MultiEndpointPool pool;
private final TCPNIOTransport transport;
private final TCPNIOConnectorHandler defaultConnectionHandler;
private final GrizzlyAsyncHttpProvider provider;
private final AsyncHttpClientConfig config;
private final boolean poolingSSLConnections;
private final Map endpointMap =
new ConcurrentHashMap();
// -------------------------------------------------------- Constructors
ConnectionManager(final GrizzlyAsyncHttpProvider provider,
final TCPNIOTransport transport,
final GrizzlyAsyncHttpProviderConfig providerConfig) {
this.transport = transport;
this.provider = provider;
config = provider.getClientConfig();
this.poolingEnabled = config.isAllowPoolingConnections();
this.poolingSSLConnections = config.isAllowPoolingSslConnections();
defaultConnectionHandler = TCPNIOConnectorHandler.builder(transport).build();
if (providerConfig != null && providerConfig.getConnectionPool() != null) {
pool = providerConfig.getConnectionPool();
} else {
if (poolingEnabled) {
final MultiEndpointPool.Builder builder
= MultiEndpointPool.builder(SocketAddress.class)
.connectTimeout(config.getConnectTimeout(), TimeUnit.MILLISECONDS)
.asyncPollTimeout(config.getConnectTimeout(), TimeUnit.MILLISECONDS)
.maxConnectionsTotal(config.getMaxConnections())
.maxConnectionsPerEndpoint(config.getMaxConnectionsPerHost())
.keepAliveTimeout(config.getPooledConnectionIdleTimeout(), TimeUnit.MILLISECONDS)
.connectorHandler(defaultConnectionHandler)
.connectionTTL(config.getConnectionTTL(), TimeUnit.MILLISECONDS)
.failFastWhenMaxSizeReached(true);
if (!poolingSSLConnections) {
builder.endpointPoolCustomizer(new NoSSLPoolCustomizer());
}
pool = builder.build();
} else {
pool = MultiEndpointPool.builder(SocketAddress.class)
.connectTimeout(config.getConnectTimeout(), TimeUnit.MILLISECONDS)
.asyncPollTimeout(config.getConnectTimeout(), TimeUnit.MILLISECONDS)
.maxConnectionsTotal(config.getMaxConnections())
.maxConnectionsPerEndpoint(config.getMaxConnectionsPerHost())
.keepAliveTimeout(0, TimeUnit.MILLISECONDS) // no pool
.connectorHandler(defaultConnectionHandler)
.failFastWhenMaxSizeReached(true)
.build();
}
}
}
// ----------------------------------------------------- Private Methods
void openAsync(final Request request,
final CompletionHandler completionHandler)
throws IOException {
final ProxyServer proxy = ProxyUtils.getProxyServer(config, request);
final String scheme;
final String host;
final int port;
if (proxy != null) {
scheme = proxy.getProtocol().getProtocol();
host = proxy.getHost();
port = getPort(scheme, proxy.getPort());
} else {
final Uri uri = request.getUri();
scheme = uri.getScheme();
host = uri.getHost();
port = getPort(scheme, uri.getPort());
}
final boolean isSecure = Utils.isSecure(scheme);
final String partitionId = getPartitionId(request, proxy);
Endpoint endpoint = endpointMap.get(partitionId);
if (endpoint == null) {
endpoint = new AhcEndpoint(partitionId,
isSecure, host, port, request.getLocalAddress(),
createConnectorHandler(isSecure, host));
endpointMap.put(partitionId, endpoint);
}
pool.take(endpoint, completionHandler);
}
Connection openSync(final Request request)
throws IOException {
final ProxyServer proxy = ProxyUtils.getProxyServer(config, request);
final String scheme;
final String host;
final int port;
if (proxy != null) {
scheme = proxy.getProtocol().getProtocol();
host = proxy.getHost();
port = getPort(scheme, proxy.getPort());
} else {
final Uri uri = request.getUri();
scheme = uri.getScheme();
host = uri.getHost();
port = getPort(scheme, uri.getPort());
}
final boolean isSecure = Utils.isSecure(scheme);
final String partitionId = getPartitionId(request, proxy);
Endpoint endpoint = endpointMap.get(partitionId);
if (endpoint == null) {
endpoint = new AhcEndpoint(partitionId,
isSecure, host, port, request.getLocalAddress(),
createConnectorHandler(isSecure, host));
endpointMap.put(partitionId, endpoint);
}
Connection c = pool.poll(endpoint);
if (c == null) {
final Future future =
createConnectorHandler(isSecure, host).connect(
new InetSocketAddress(host, port),
request.getLocalAddress() != null
? new InetSocketAddress(request.getLocalAddress(), 0)
: null);
final int cTimeout = config.getConnectTimeout();
try {
c = cTimeout > 0
? future.get(cTimeout, TimeUnit.MILLISECONDS)
: future.get();
} catch (ExecutionException ee) {
throw Exceptions.makeIOException(ee.getCause());
} catch (Exception e) {
throw Exceptions.makeIOException(e);
} finally {
future.cancel(false);
}
}
assert c != null; // either connection is not null or exception thrown
return c;
}
boolean returnConnection(final Connection c) {
return pool.release(c);
}
void destroy() {
pool.close();
}
private static String getPartitionId(Request request,
ProxyServer proxyServer) {
return request.getConnectionPoolPartitioning()
.getPartitionId(request.getUri(), proxyServer);
}
private static int getPort(final String scheme, final int p) {
int port = p;
if (port == -1) {
final String protocol = scheme.toLowerCase(Locale.ENGLISH);
if ("http".equals(protocol) || "ws".equals(protocol)) {
port = 80;
} else if ("https".equals(protocol) || "wss".equals(protocol)) {
port = 443;
} else {
throw new IllegalArgumentException("Unknown protocol: " + protocol);
}
}
return port;
}
private ConnectorHandler createConnectorHandler(
final boolean isSecure, final String host) {
return isSecure && config.getHostnameVerifier() != null
? new TCPNIOConnectorHandler(transport) {
@Override
protected void preConfigure(final Connection connection) {
super.preConfigure(connection);
HostnameVerifierListener.assignHostnameVerifyTask(
connection, config.getHostnameVerifier(), host, null);
}
}
: defaultConnectionHandler;
}
private class AhcEndpoint extends Endpoint {
private final String partitionId;
private final boolean isSecure;
private final String host;
private final int port;
private final InetAddress localAddress;
private final ConnectorHandler connectorHandler;
private AhcEndpoint(final String partitionId,
final boolean isSecure,
final String host, final int port,
final InetAddress localAddress,
final ConnectorHandler connectorHandler) {
this.partitionId = partitionId;
this.isSecure = isSecure;
this.host = host;
this.port = port;
this.localAddress = localAddress;
this.connectorHandler = connectorHandler;
}
public boolean isSecure() {
return isSecure;
}
@Override
public Object getId() {
return partitionId;
}
@Override
public GrizzlyFuture connect() {
return (GrizzlyFuture) connectorHandler.connect(
new InetSocketAddress(host, port),
localAddress != null
? new InetSocketAddress(localAddress, 0)
: null);
}
}
private class NoSSLPoolCustomizer
implements MultiEndpointPool.EndpointPoolCustomizer {
@Override
public void customize(final Endpoint endpoint,
final MultiEndpointPool.EndpointPoolBuilder builder) {
final AhcEndpoint ahcEndpoint = (AhcEndpoint) endpoint;
if (ahcEndpoint.isSecure()) {
builder.keepAliveTimeout(0, TimeUnit.SECONDS); // don't pool
}
}
}
} // END ConnectionManager