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

io.zbus.mq.MqClientPool Maven / Gradle / Ivy

package io.zbus.mq;

import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

import io.zbus.mq.MqClientPool.Pool.ObjectFactory;
import io.zbus.mq.Protocol.ServerAddress;
import io.zbus.mq.logging.Logger;
import io.zbus.mq.logging.LoggerFactory;
import io.zbus.mq.net.EventLoop; 

public class MqClientPool implements Closeable {
	private Pool pool;
	private MqClientFactory factory;

	private ServerAddress serverAddress;
	private final int clientPoolSize;
	private EventLoop eventDriver;

	public MqClientPool(String serverAddress, int clientPoolSize, EventLoop eventDriver) {
		this.clientPoolSize = clientPoolSize;
		if (eventDriver != null) {
			this.eventDriver = eventDriver.duplicate();
		} else {
			this.eventDriver = new EventLoop();
		}
		this.serverAddress = new ServerAddress(serverAddress, this.eventDriver.isSslEnabled());

		this.factory = new MqClientFactory(serverAddress, eventDriver);
		this.pool = new Pool(factory, this.clientPoolSize);

	}

	public MqClientPool(String serverAddress, int clientPoolSize) {
		this(serverAddress, clientPoolSize, null);
	}

	public MqClientPool(String serverAddress) {
		this(serverAddress, 64);
	}

	public MqClient borrowClient() {
		try {
			MqClient client = this.pool.borrowObject();
			return client;
		} catch (Exception e) {
			throw new MqException(e.getMessage(), e);
		}
	}

	public void returnClient(MqClient... client) {
		if (client == null || client.length == 0)
			return;
		for (MqClient c : client) {
			this.pool.returnObject(c);
		}
	}

	public MqClient createClient() {
		return factory.createObject();
	}

	public ServerAddress serverAddress() {
		return serverAddress;
	}

	@Override
	public void close() throws IOException {
		if (this.pool != null) {
			this.pool.close();
			eventDriver.close();
			this.pool = null;
		}
	}

	public static class MqClientFactory implements ObjectFactory, Closeable {
		private static final Logger log = LoggerFactory.getLogger(MqClientFactory.class);

		protected final String serverAddress;
		protected EventLoop eventLoop;
		protected boolean ownEventDriver = false;

		public MqClientFactory(String serverAddress, EventLoop eventLoop) {
			this.serverAddress = serverAddress;
			this.eventLoop = eventLoop;
		}

		public String getServerAddress() {
			return serverAddress;
		}

		public MqClient createObject() {
			return new MqClient(serverAddress, eventLoop);
		}

		@Override
		public boolean validateObject(MqClient client) {
			if (client == null)
				return false;
			return client.hasConnected();
		}

		@Override
		public void destroyObject(MqClient client) {
			try {
				client.close();
			} catch (IOException e) {
				log.error(e.getMessage(), e);
			}
		}

		@Override
		public void close() throws IOException {
			if (ownEventDriver && eventLoop != null) {
				eventLoop.close();
				eventLoop = null;
			}
		}
	}

	public static class Pool implements Closeable {
		public static interface ObjectFactory {

			T createObject() throws Exception;

			void destroyObject(T obj);

			boolean validateObject(T obj);
		}

		private ObjectFactory factory;
		private BlockingQueue queue = null;
		private final int maxTotal;
		private final AtomicInteger activeCount = new AtomicInteger(0);

		public Pool(ObjectFactory factory, int maxTotal) {
			this.factory = factory;

			this.maxTotal = maxTotal;
			this.queue = new ArrayBlockingQueue(maxTotal);
		}

		@Override
		public void close() throws IOException {
			T obj = null;
			while ((obj = queue.poll()) != null) {
				factory.destroyObject(obj);
			}
		}

		public T borrowObject() throws Exception {
			T obj = null;
			if (activeCount.get() >= maxTotal) {
				obj = queue.take();
				return obj;
			}
			obj = queue.poll();
			if (obj != null)
				return obj;

			obj = factory.createObject();
			activeCount.incrementAndGet();

			return obj;
		}

		public void returnObject(T obj) {
			if (!factory.validateObject(obj)) {
				activeCount.decrementAndGet();
				factory.destroyObject(obj);
				return;
			}
			queue.offer(obj);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy