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

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

The 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 com.aerospike.client.AerospikeException;
import com.aerospike.client.cluster.Cluster;
import com.aerospike.client.cluster.Node;

public abstract class AsyncMultiExecutor {
	final EventLoop eventLoop;
	final Cluster cluster;
	private AsyncMultiCommand[] commands;
	private String namespace;
	private AerospikeException exception;
	private long clusterKey;
	private final int infoTimeout;
	private int maxConcurrent;
	private int completedCount;  // Not atomic because all commands run on same event loop thread.
	boolean done;

	public AsyncMultiExecutor(EventLoop eventLoop, Cluster cluster, int infoTimeout) {
		this.eventLoop = eventLoop;
		this.cluster = cluster;
		this.infoTimeout = infoTimeout;
	}

	public void execute(AsyncMultiCommand[] commands, int maxConcurrent) {
		this.commands = commands;
		this.maxConcurrent = (maxConcurrent == 0 || maxConcurrent >= commands.length) ? commands.length : maxConcurrent;

		for (int i = 0; i < this.maxConcurrent; i++) {
			eventLoop.execute(cluster, commands[i]);
		}
	}

	public void executeValidate(final AsyncMultiCommand[] commands, int maxConcurrent, final String namespace) {
		this.commands = commands;
		this.maxConcurrent = (maxConcurrent == 0 || maxConcurrent >= commands.length) ? commands.length : maxConcurrent;
		this.namespace = namespace;

		final int max = this.maxConcurrent;

		AsyncQueryValidate.validateBegin(cluster, eventLoop, new AsyncQueryValidate.BeginListener() {
			@Override
			public void onSuccess(long key) {
				clusterKey = key;
				eventLoop.execute(cluster, commands[0]);

				for (int i = 1; i < max; i++) {
					executeValidateCommand(commands[i]);
				}
			}

			@Override
			public void onFailure(AerospikeException ae) {
				initFailure(ae);
			}
		}, commands[0].node, namespace, infoTimeout);
	}

	private final void executeValidateCommand(final AsyncMultiCommand command) {
		AsyncQueryValidate.validate(cluster, eventLoop, new AsyncQueryValidate.Listener() {
			@Override
			public void onSuccess() {
				eventLoop.execute(cluster, command);
			}

			@Override
			public void onFailure(AerospikeException ae) {
				childFailure(ae);
			}
		}, command.node, namespace, clusterKey, infoTimeout);
	}

	protected final void childSuccess(Node node) {
		if (clusterKey == 0) {
			queryComplete();
		}
		else {
			AsyncQueryValidate.validate(cluster, eventLoop, new AsyncQueryValidate.Listener() {
				@Override
				public void onSuccess() {
					queryComplete();
				}

				@Override
				public void onFailure(AerospikeException ae) {
					childFailure(ae);
				}
			}, node, namespace, clusterKey, infoTimeout);
		}
	}

	private final void queryComplete() {
		completedCount++;

		if (completedCount < commands.length) {
			int nextThread = completedCount + maxConcurrent - 1;

			// Determine if a new command needs to be started.
			if (nextThread < commands.length && ! done) {
				// Start new command.
				if (clusterKey == 0) {
					eventLoop.execute(cluster, commands[nextThread]);
				}
				else {
					executeValidateCommand(commands[nextThread]);
				}
			}
		}
		else {
			// All commands complete. Notify success if an exception has not already occurred.
			if (! done) {
				done = true;

				if (exception == null) {
					onSuccess();
				}
				else {
					onFailure(exception);
				}
			}
		}
	}

	final void childFailure(AerospikeException ae) {
		// There is no need to stop commands if all commands have already completed.
		if (! done) {
			done = true;

			// Send stop signal to all commands.
			for (AsyncMultiCommand command : commands) {
				command.stop();
			}
			onFailure(ae);
		}
	}

	final void reset() {
		this.completedCount = 0;
		this.done = false;
	}

	private final void initFailure(AerospikeException ae) {
		onFailure(ae);
	}

	protected abstract void onSuccess();
	protected abstract void onFailure(AerospikeException ae);
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy