All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rapidoid.net.impl.RapidoidClientLoop Maven / Gradle / Ivy

The newest version!
/*-
 * #%L
 * rapidoid-net
 * %%
 * Copyright (C) 2014 - 2018 Nikolche Mihajlovski and contributors
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

package org.rapidoid.net.impl;


import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;
import org.rapidoid.cls.Cls;
import org.rapidoid.net.NetworkingParams;
import org.rapidoid.net.Protocol;
import org.rapidoid.net.TCPClient;
import org.rapidoid.net.TCPClientInfo;
import org.rapidoid.net.abstracts.ChannelHolder;
import org.rapidoid.u.U;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;

@Authors("Nikolche Mihajlovski")
@Since("5.5.0")
public class RapidoidClientLoop extends AbstractEventLoop implements TCPClient, TCPClientInfo {

	private final NetworkingParams net;

	// initial number of connections to the default server
	private final int connections;

	private final boolean autoReconnect;

	private final SSLContext sslContext;

	private volatile ExtendedWorker[] ioWorkers;

	// round-robin workers for new connections
	private int currentWorkerInd = 0;

	public RapidoidClientLoop(NetworkingParams net, boolean autoReconnect, int connections, SSLContext sslContext) {
		super("client");

		this.net = net;
		this.autoReconnect = autoReconnect;
		this.connections = connections;
		this.sslContext = sslContext;
	}

	@Override
	protected void doProcessing() {
	}

	@Override
	protected final void beforeLoop() {
		try {
			openSockets();
		} catch (IOException e) {
			throw U.rte("Cannot open socket!", e);
		}
	}

	private void openSockets() throws IOException {
		ioWorkers = new ExtendedWorker[net.workers()];

		for (int i = 0; i < ioWorkers.length; i++) {
			RapidoidHelper helper = Cls.newInstance(net.helperClass(), net.exchangeClass());
			String workerName = "client" + (i + 1);
			ioWorkers[i] = new ExtendedWorker(workerName, helper, net, sslContext);

			new Thread(ioWorkers[i], workerName).start();
		}

		for (int i = 0; i < ioWorkers.length; i++) {
			ioWorkers[i].waitToStart();
		}
	}

	@Override
	public synchronized ChannelHolder connect(String serverHost, int serverPort, Protocol clientProtocol,
	                                          boolean autoreconnecting, ConnState state) {

		InetSocketAddress addr = new InetSocketAddress(serverHost, serverPort);
		SocketChannel socketChannel = openSocket();

		ChannelHolderImpl holder = new ChannelHolderImpl();

		try {
			ExtendedWorker targetWorker = ioWorkers[currentWorkerInd];
			ConnectionTarget target = new ConnectionTarget(socketChannel, addr, clientProtocol, holder, autoreconnecting, state);
			targetWorker.connect(target);

		} catch (IOException e) {
			throw U.rte("Cannot create a TCP client connection!", e);
		}

		switchToNextWorker();
		return holder;
	}

	@Override
	public synchronized ChannelHolder[] connect(String serverHost, int serverPort, Protocol clientProtocol,
	                                            int connectionsN, boolean autoreconnecting, ConnState state) {

		ChannelHolder[] holders = new ChannelHolder[connectionsN];

		for (int i = 0; i < connectionsN; i++) {
			holders[i] = connect(serverHost, serverPort, clientProtocol, autoreconnecting, state);
		}

		return holders;
	}

	private synchronized void switchToNextWorker() {
		currentWorkerInd++;
		if (currentWorkerInd == ioWorkers.length) {
			currentWorkerInd = 0;
		}
	}

	protected static SocketChannel openSocket() {
		try {
			SocketChannel socketChannel = SocketChannel.open();

			if (!socketChannel.isOpen()) {
				throw U.rte("Cannot open socket!");
			}

			return socketChannel;
		} catch (IOException e) {
			throw U.rte("Cannot open socket!", e);
		}
	}

	@Override
	public synchronized TCPClient start() {
		new Thread(this, "client").start();

		super.start();

		connect(net.address(), net.port(), net.protocol(), connections, autoReconnect, null);

		return this;
	}

	@Override
	public synchronized TCPClient shutdown() {
		stopLoop();

		for (ExtendedWorker worker : ioWorkers) {
			worker.stopLoop();
		}

		return super.shutdown();
	}

	@Override
	public TCPClientInfo info() {
		return this;
	}

	@Override
	public long messagesProcessed() {
		long total = 0;

		for (int i = 0; i < ioWorkers.length; i++) {
			total += ioWorkers[i].getMessagesProcessed();
		}

		return total;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy