<commit_before>/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2012 The OpenNMS Group, Inc.
 * OpenNMS(R) is Copyright (C) 1999-2012 The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * OpenNMS(R) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with OpenNMS(R).  If not, see:
 *      http://www.gnu.org/licenses/
 *
 * For more information contact:
 *     OpenNMS(R) Licensing <<EMAIL>>
 *     http://www.opennms.org/
 *     http://www.opennms.com/
 *******************************************************************************/

package org.opennms.netmgt.provision.support;

import java.net.BindException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.service.IoProcessor;
import org.apache.mina.core.service.SimpleIoProcessorPool;
import org.apache.mina.core.session.IoSessionInitializer;
import org.apache.mina.transport.socket.SocketConnector;
import org.apache.mina.transport.socket.nio.NioProcessor;
import org.apache.mina.transport.socket.nio.NioSession;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.opennms.core.utils.LogUtils;

/**
 * <p>This {@link ConnectionFactory} type will create a new {@link NioSocketConnector}
 * for every call to {@link #connect(SocketAddress, SocketAddress, IoSessionInitializer)}.
 * This is a naive implementation that does not really take advantage of the asynchronous
 * operations in MINA since it is creating new threads for each socket operation.</p>
 *
 * @author Seth
 * @author ranger
 * @author <NAME>
 */
public class ConnectionFactoryNewConnectorImpl extends ConnectionFactory {

    private static final Executor m_executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    private static final IoProcessor<NioSession> m_processor = new SimpleIoProcessorPool<NioSession>(NioProcessor.class, m_executor);
    private ThreadLocal<Integer> m_port = new ThreadLocal<Integer>();
    private final Object m_portMutex = new Object();

    /**
     * Create a new factory. Private because one should use {@link #getFactory(int)}
     */
    protected ConnectionFactoryNewConnectorImpl(int timeoutInMillis) {
        super(timeoutInMillis);
    }

    private static final NioSocketConnector getSocketConnector(long timeout, IoHandler handler) {
        // Create a new NioSocketConnector
        NioSocketConnector connector = new NioSocketConnector(m_executor, m_processor);

        // Enable SO_REUSEADDR on the socket so that TIMED_WAIT connections that are bound on the
        // same port do not block new outgoing connections. If the connections are blocked, then
        // the following exception will be thrown under heavy load:
        //
        // Caused by: java.net.SocketException: Invalid argument
        //   at sun.nio.ch.Net.connect(Native Method)
        //   at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:500)
        //   at org.apache.mina.transport.socket.nio.NioSocketConnector.connect(NioSocketConnector.java:188)
        //   ...
        //
        // @see http://issues.opennms.org/browse/NMS-5469
        //
        connector.getSessionConfig().setReuseAddress(true);

        // Setting SO_LINGER will prevent TIME_WAIT sockets altogether because TCP connections will be
        // forcefully terminated with RST packets. However, this doesn't seem to be necessary to maintain
        // performance of the outgoing connections. As long as SO_REUSEADDR is set, the operating system
        // and Java appear to recycle the ports effectively although some will remain in TIME_WAIT state.
        //
        // @see http://issues.opennms.org/browse/NMS-5469
        //
        //connector.getSessionConfig().setSoLinger(0);

        connector.setHandler(handler);
        connector.setConnectTimeoutMillis(timeout);
        return connector;
    }

    /**
     * <p>Connect to a remote socket. If org.opennms.netmgt.provision.maxConcurrentConnections<commit_msg>Changed the ConnectionFactoryNewConnectorImpl to use the default constructor for the MINA NioSocketConnector. This will recycle the thread and the IoProcessor for the connector during each connection which seems to be necessary for MINA to reliably continue to connect in the face of many connection failures. Fixes bug NMS-6412.<commit_after>/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2012 The OpenNMS Group, Inc.
 * OpenNMS(R) is Copyright (C) 1999-2012 The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * OpenNMS(R) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with OpenNMS(R).  If not, see:
 *      http://www.gnu.org/licenses/
 *
 * For more information contact:
 *     OpenNMS(R) Licensing <<EMAIL>>
 *     http://www.opennms.org/
 *     http://www.opennms.com/
 *******************************************************************************/

package org.opennms.netmgt.provision.support;

import java.net.BindException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.service.IoProcessor;
import org.apache.mina.core.service.SimpleIoProcessorPool;
import org.apache.mina.core.session.IoSessionInitializer;
import org.apache.mina.transport.socket.SocketConnector;
import org.apache.mina.transport.socket.nio.NioProcessor;
import org.apache.mina.transport.socket.nio.NioSession;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.opennms.core.utils.LogUtils;

/**
 * <p>This {@link ConnectionFactory} type will create a new {@link NioSocketConnector}
 * for every call to {@link #connect(SocketAddress, SocketAddress, IoSessionInitializer)}.
 * This is a naive implementation that does not really take advantage of the asynchronous
 * operations in MINA since it is creating new threads for each socket operation.</p>
 *
 * @author Seth
 * @author ranger
 * @author <NAME>
 */
public class ConnectionFactoryNewConnectorImpl extends ConnectionFactory {

    //private static final Executor m_executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    //private static final IoProcessor<NioSession> m_processor = new SimpleIoProcessorPool<NioSession>(NioProcessor.class, m_executor);
    private ThreadLocal<Integer> m_port = new ThreadLocal<Integer>();
    private final Object m_portMutex = new Object();

    /**
     * Create a new factory. Private because one should use {@link #getFactory(int)}
     */
    protected ConnectionFactoryNewConnectorImpl(int timeoutInMillis) {
        super(timeoutInMillis);
    }

    private static final NioSocketConnector getSocketConnector(long timeout, IoHandler handler) {
        // Create a new NioSocketConnector
        //NioSocketConnector connector = new NioSocketConnector(m_executor, m_processor);

        // To address bug NMS-6412, I'm changing this to use the default constructor so that the
        // Executor pool and IoProcessor pools are created and destroyed for every connector.
        // This slows things down but might be an acceptable tradeoff for more reliable detection.
        //
        // @see http://issues.opennms.org/browse/NMS-6412
        //
        NioSocketConnector connector = new NioSocketConnector(Runtime.getRuntime().availableProcessors());

        // Enable SO_REUSEADDR on the socket so that TIMED_WAIT connections that are bound on the
        // same port do not block new outgoing connections. If the connections are blocked, then
        // the following exception will be thrown under heavy load:
        //
        // Caused by: java.net.SocketException: Invalid argument
        //   at sun.nio.ch.Net.connect(Native Method)
        //   at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:500)
        //   at org.apache.mina.transport.socket.nio.NioSocketConnector.connect(NioSocketConnector.java:188)
        //   ...
        //
        // @see http://issues.opennms.org/browse/NMS-5469
        //
        connector.getSessionConfig().setReuseAddress(true);

        // Setting SO_LINGER will prevent TIME_WAIT sockets altogether because TCP connections will be
        // forcefully terminated with RST packets. However, this doesn't seem to be necessary to maintain
        // performance of the outgoing connections. As long as SO_REUSEADDR is set, the operating system
        // and Java appear to recycle the ports effectively although some will remain in TIME_WAIT state.
        //
        // @see http://issues.opennms.org/browse/NMS-5469
        //
        //connector.getSessionConfig().setSoLinger(0);

        connector.setHandler(handler);
        connector.setConnectTimeoutMillis(timeout);
        return connector;
    }

    /**
     * <p>Connect to a remote socket. If org.opennms.netmgt.provision.maxConcurrentConnections
{'fraction_non_alphanumeric': 0.11493822538375141, 'fraction_numerical': 0.00636465743167353, 'mean_word_length': 3.696703296703297, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3027422', 'n_tokens_mistral': 2907, 'n_tokens_neox': 2825, 'n_words': 913}