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

com.aerospike.client.async.NettyEventLoops Maven / Gradle / Ivy

Go to download

Aerospike Java client interface to Aerospike database server. Uses Bouncy Castle crypto library for RIPEMD-160 hashing.

There is a newer version: 9.0.0
Show newest version
/*
 * Copyright 2012-2023 Aerospike, Inc.
 *
 * Portions may be licensed to Aerospike, Inc. under one or more contributor
 * license agreements WHICH ARE COMPATIBLE WITH THE APACHE LICENSE, VERSION 2.0.
 *
 * 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.
 */
package com.aerospike.client.async;

import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;

import com.aerospike.client.AerospikeException;

import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollSocketChannel;
import io.netty.channel.kqueue.KQueueEventLoopGroup;
import io.netty.channel.kqueue.KQueueSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.incubator.channel.uring.IOUringEventLoopGroup;
import io.netty.incubator.channel.uring.IOUringSocketChannel;
import io.netty.util.concurrent.EventExecutor;

/**
 * Aerospike wrapper around netty event loops.
 * Implements the Aerospike EventLoops interface.
 */
public final class NettyEventLoops implements EventLoops {

	private final Map eventLoopMap;
	private final NettyEventLoop[] eventLoopArray;
	private final EventLoopGroup group;
	final EventLoopType eventLoopType;
	private int eventIter;

	/**
	 * Create Aerospike event loop wrappers from given netty event loops.
	 */
	public NettyEventLoops(EventLoopGroup group) {
		this(new EventPolicy(), group);
	}

	/**
	 * Create Aerospike event loop wrappers from given netty event loops.
	 * The type of event loop is determined from the event loop group instance.
	 */
	public NettyEventLoops(EventPolicy policy, EventLoopGroup group) {
		this(policy, group, getEventLoopType(group));
	}

	/**
	 * Create Aerospike event loop wrappers from given netty event loops and specified event loop type.
	 */
	public NettyEventLoops(EventPolicy policy, EventLoopGroup group, EventLoopType type) {
		if (policy.minTimeout < 5) {
			throw new AerospikeException("Invalid minTimeout " + policy.minTimeout + ". Must be at least 5ms.");
		}
		this.group = group;
		this.eventLoopType = type;

		ArrayList list = new ArrayList();
		Iterator iter = group.iterator();
		int count = 0;

		while (iter.hasNext()) {
			EventExecutor eventExecutor = iter.next();
			list.add(new NettyEventLoop(policy, (io.netty.channel.EventLoop)eventExecutor, this, count++));
		}

		eventLoopArray = list.toArray(new NettyEventLoop[count]);
		eventLoopMap = new IdentityHashMap(count);

		for (NettyEventLoop eventLoop : eventLoopArray) {
			eventLoopMap.put(eventLoop.eventLoop, eventLoop);
		}

		// Start timer in each event loop thread.
		for (NettyEventLoop eventLoop : eventLoopArray) {
			eventLoop.execute(new Runnable() {
				public void run() {
					eventLoop.timer.start();
				}
			});
		}
	}

	private static EventLoopType getEventLoopType(EventLoopGroup group) {
		// Wrap each instanceof comparison in a try/catch block because these classes reference
		// libraries that are optional and might not be specified in the build file (pom.xml).
		// This is preferable to using a "getClass().getSimpleName()" switch statement because
		// that requires exact classname equality and does not handle custom classes that might
		// inherit from these classes.
		try {
			if (group instanceof NioEventLoopGroup) {
				return EventLoopType.NETTY_NIO;
			}
		}
		catch (NoClassDefFoundError e) {
		}

		try {
			if (group instanceof EpollEventLoopGroup) {
				return EventLoopType.NETTY_EPOLL;
			}
		}
		catch (NoClassDefFoundError e) {
		}

		try {
			if (group instanceof KQueueEventLoopGroup) {
				return EventLoopType.NETTY_KQUEUE;
			}
		}
		catch (NoClassDefFoundError e) {
		}

		try {
			if (group instanceof IOUringEventLoopGroup) {
				return EventLoopType.NETTY_IOURING;
			}
		}
		catch (NoClassDefFoundError e) {
		}

		throw new AerospikeException("Unexpected EventLoopGroup");
	}

	/**
	 * Return SocketChannel class to use in NettyChannelBuilder.
	 */
	public Class getSocketChannelClass() {
		switch (eventLoopType) {
		default:
		case NETTY_NIO:
			return NioSocketChannel.class;

		case NETTY_EPOLL:
			return EpollSocketChannel.class;

		case NETTY_KQUEUE:
			return KQueueSocketChannel.class;

		case NETTY_IOURING:
			return IOUringSocketChannel.class;
		}
	}

	/**
	 * Return corresponding Aerospike event loop given netty event loop.
	 */
	public NettyEventLoop get(EventExecutor eventExecutor) {
		return eventLoopMap.get(eventExecutor);
	}

	/**
	 * Return array of Aerospike event loops.
	 */
	@Override
	public NettyEventLoop[] getArray() {
		return eventLoopArray;
	}

	/**
	 * Return number of event loops in this group.
	 */
	@Override
	public int getSize() {
		return eventLoopArray.length;
	}

	/**
	 * Return Aerospike event loop given array index..
	 */
	@Override
	public NettyEventLoop get(int index) {
		return eventLoopArray[index];
	}

	/**
	 * Return next Aerospike event loop in round-robin fashion.
	 */
	@Override
	public NettyEventLoop next() {
		int iter = eventIter++; // Not atomic by design
		iter = iter % eventLoopArray.length;

		if (iter < 0) {
			iter += eventLoopArray.length;
		}
		return eventLoopArray[iter];
	}

	@Override
	public void close() {
		group.shutdownGracefully();
		/*
		for (NettyEventLoop el : eventLoopArray) {
			el.timer.printRemaining();
		}*/
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy