PageRenderTime 19ms CodeModel.GetById 7ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/hazelcast/src/main/java/com/hazelcast/nio/SocketConnector.java

https://bitbucket.org/gabral6_gmailcom/hazelcast
Java | 173 lines | 140 code | 11 blank | 22 comment | 20 complexity | fb6c04fa406272ac8140115e76379994 MD5 | raw file
  1/*
  2 * Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.
  3 *
  4 * Licensed under the Apache License, Version 2.0 (the "License");
  5 * you may not use this file except in compliance with the License.
  6 * You may obtain a copy of the License at
  7 *
  8 * http://www.apache.org/licenses/LICENSE-2.0
  9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed under the License is distributed on an "AS IS" BASIS,
 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 * See the License for the specific language governing permissions and
 14 * limitations under the License.
 15 */
 16
 17package com.hazelcast.nio;
 18
 19import com.hazelcast.logging.ILogger;
 20import com.hazelcast.util.AddressUtil;
 21
 22import java.io.IOException;
 23import java.net.*;
 24import java.nio.channels.SocketChannel;
 25import java.util.Collection;
 26import java.util.logging.Level;
 27
 28public class SocketConnector implements Runnable {
 29
 30    private final ConnectionManager connectionManager;
 31    private final Address address;
 32    private final ILogger logger;
 33    private final boolean silent;
 34
 35    public SocketConnector(ConnectionManager connectionManager, Address address, boolean silent) {
 36        this.connectionManager = connectionManager;
 37        this.address = address;
 38        this.logger = connectionManager.ioService.getLogger(this.getClass().getName());
 39        this.silent = silent;
 40    }
 41
 42    public void run() {
 43        if (!connectionManager.isLive()) {
 44            String message = "ConnectionManager is not live, connection attempt to " +
 45                             address + " is cancelled!";
 46            log(Level.FINEST, message);
 47            return;
 48        }
 49        try {
 50            connectionManager.ioService.onIOThreadStart();
 51            log(Level.FINEST, "Starting to connect to " + address);
 52            final Address thisAddress = connectionManager.ioService.getThisAddress();
 53            if (address.isIPv4()) {
 54                // remote is IPv4; connect...
 55                tryToConnect(address.getInetSocketAddress(), 0);
 56            } else if (thisAddress.isIPv6() && thisAddress.getScopeId() != null) {
 57                // Both remote and this addresses are IPv6.
 58                // This is a local IPv6 address and scope id is known.
 59                // find correct inet6 address for remote and connect...
 60                final Inet6Address inetAddress = AddressUtil
 61                        .getInetAddressFor((Inet6Address) address.getInetAddress(), thisAddress.getScopeId());
 62                tryToConnect(new InetSocketAddress(inetAddress, address.getPort()), 0);
 63            } else {
 64                // remote is IPv6 and this is either IPv4 or a global IPv6.
 65                // find possible remote inet6 addresses and try each one to connect...
 66                final Collection<Inet6Address> possibleInetAddresses = AddressUtil.getPossibleInetAddressesFor(
 67                        (Inet6Address) address.getInetAddress());
 68                final Level level = silent ? Level.FINEST : Level.INFO;
 69                log(level, "Trying to connect possible IPv6 addresses: " + possibleInetAddresses);
 70                boolean connected = false;
 71                Exception error = null;
 72                for (Inet6Address inetAddress : possibleInetAddresses) {
 73                    try {
 74                        tryToConnect(new InetSocketAddress(inetAddress, address.getPort()), 3000);
 75                        connected = true;
 76                        break;
 77                    } catch (Exception e) {
 78                        error = e;
 79                    }
 80                }
 81                if (!connected) {
 82                    // could not connect any of addresses
 83                    throw error;
 84                }
 85            }
 86        } catch (Throwable e) {
 87            logger.log(Level.FINEST, e.getMessage(), e);
 88            connectionManager.failedConnection(address, e, silent);
 89        }
 90    }
 91
 92    private void tryToConnect(final InetSocketAddress socketAddress, final int timeout)
 93            throws Exception {
 94        final SocketChannel socketChannel = SocketChannel.open();
 95        connectionManager.initSocket(socketChannel.socket());
 96        bindSocket(socketChannel);
 97        final String message = "Connecting to " + socketAddress
 98                               + ", timeout: " + timeout
 99                               + ", bind-any: " + connectionManager.ioService.isSocketBindAny();
100        log(Level.FINEST, message);
101        try {
102            socketChannel.configureBlocking(true);
103            if (timeout > 0) {
104                socketChannel.socket().connect(socketAddress, timeout);
105            } else {
106                socketChannel.connect(socketAddress);
107            }
108            log(Level.FINEST, "Successfully connected to: " + address + " using socket " + socketChannel.socket());
109            MemberSocketInterceptor memberSocketInterceptor = connectionManager.getMemberSocketInterceptor();
110            if (memberSocketInterceptor != null) {
111                log(Level.FINEST, "Calling member socket interceptor: " + memberSocketInterceptor
112                   + " for " + socketChannel);
113                memberSocketInterceptor.onConnect(socketChannel.socket());
114            }
115            socketChannel.configureBlocking(false);
116            final SocketChannelWrapper socketChannelWrapper = connectionManager
117                    .wrapSocketChannel(socketChannel, true);
118            Connection connection = connectionManager.assignSocketChannel(socketChannelWrapper);
119            connectionManager.sendBindRequest(connection, address, true);
120        } catch (Exception e) {
121            closeSocket(socketChannel);
122            final Level level = silent ? Level.FINEST : Level.INFO;
123            log(level, "Could not connect to: "
124                                      + socketAddress + ". Reason: " + e.getClass().getSimpleName()
125                                      + "[" + e.getMessage() + "]");
126            throw e;
127        }
128    }
129
130    private void bindSocket(final SocketChannel socketChannel) throws IOException {
131        final InetAddress inetAddress;
132        if (connectionManager.ioService.isSocketBindAny()) {
133            inetAddress = null;
134        } else {
135            final Address thisAddress = connectionManager.ioService.getThisAddress();
136            inetAddress = thisAddress.getInetAddress();
137        }
138        final Socket socket = socketChannel.socket();
139        if (connectionManager.useAnyOutboundPort()) {
140            final SocketAddress socketAddress = new InetSocketAddress(inetAddress, 0);
141            socket.bind(socketAddress);
142        } else {
143            IOException ex = null;
144            final int retryCount = connectionManager.getOutboundPortCount() * 2;
145            for (int i = 0; i < retryCount; i++) {
146                final int port = connectionManager.acquireOutboundPort();
147                final SocketAddress socketAddress = new InetSocketAddress(inetAddress, port);
148                try {
149                    socket.bind(socketAddress);
150                    return;
151                } catch (IOException e) {
152                    ex = e;
153                    log(Level.FINEST, "Could not bind port[ " + port + "]: " +  e.getMessage());
154                }
155            }
156            throw ex;
157        }
158    }
159
160    private void closeSocket(final SocketChannel socketChannel) {
161        if (socketChannel != null) {
162            try {
163                socketChannel.close();
164            } catch (final IOException ignored) {
165            }
166        }
167    }
168
169    private void log(Level level, String message) {
170        logger.log(level, message);
171        connectionManager.ioService.getSystemLogService().logConnection(message);
172    }
173}