com.sshtools.common.ssh.ExecutorOperationSupport Maven / Gradle / Ivy
/**
* (c) 2002-2021 JADAPTIVE Limited. All Rights Reserved.
*
* This file is part of the Maverick Synergy Java SSH API.
*
* Maverick Synergy is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Maverick Synergy 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Maverick Synergy. If not, see .
*/
package com.sshtools.common.ssh;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import com.sshtools.common.logger.Log;
public abstract class ExecutorOperationSupport {
public static final Integer MESSAGES_INCOMING = ExecutorOperationQueues.generateUniqueQueue("ExecutorOperationSupport.in");
public static final Integer MESSAGES_OUTGOING = ExecutorOperationQueues.generateUniqueQueue("ExecutorOperationSupport.out");
public static final Integer EVENTS = ExecutorOperationQueues.generateUniqueQueue("ExecutorOperationSupport.events");
public static final Integer CALLBACKS = ExecutorOperationQueues.generateUniqueQueue("ExecutorOperationSupport.callbacks");
boolean shutdown = false;
String queueName;
ConcurrentHashMap operationQueues = new ConcurrentHashMap();
protected ExecutorOperationSupport(String queueName) {
this.queueName = queueName;
}
public abstract T getContext();
public void addOutgoingTask(ConnectionAwareTask r) {
addTask(MESSAGES_OUTGOING, r);
}
public void addIncomingTask(ConnectionAwareTask r) {
addTask(MESSAGES_INCOMING, r);
}
public void addTask(Integer queue, ConnectionAwareTask r) {
if(!operationQueues.containsKey(queue)) {
operationQueues.put(queue, new OperationTask());
}
operationQueues.get(queue).addTask(r);
}
public void cleanupOperations(ConnectionAwareTask doCleanup) {
for(OperationTask task : operationQueues.values()) {
if(task.running) {
task.cleanupOperations();
}
}
addTask(ExecutorOperationSupport.EVENTS, doCleanup);
}
class OperationTask implements Runnable {
boolean running = false;
Future> operationFuture = null;
LinkedList subsystemOperations = new LinkedList();
public void run() {
if(Log.isTraceEnabled()) {
Log.trace("{}: Operation task is starting", queueName);
}
do {
executeAllTasks();
if(Log.isTraceEnabled()) {
Log.trace("{}: No more tasks, will wait for a few more seconds before completing task", queueName);
}
synchronized (this) {
running = !subsystemOperations.isEmpty();
}
} while (running);
if(Log.isTraceEnabled()) {
Log.trace("{}: Operation task has ended");
}
}
public synchronized void addTask(Runnable r) {
subsystemOperations.addLast(r);
if (!running) {
running = true;
if(Log.isTraceEnabled()) {
Log.trace("{}: Starting new subsystem task", queueName);
}
operationFuture = getContext().getExecutorService().submit(this);
} else {
notifyAll();
}
}
private void executeAllTasks() {
while (!subsystemOperations.isEmpty()) {
try {
Runnable r = null;
synchronized (this) {
r = subsystemOperations.removeFirst();
}
if (r != null) {
try {
r.run();
} catch (Throwable t) {
t.printStackTrace();
Log.error("{}: Caught exception in operation remainingTasks={}", queueName, subsystemOperations.size(), t);
}
} else {
if(Log.isWarnEnabled()) {
Log.warn("{}: Unexpected null task in operation queue", queueName);
}
}
} catch (Throwable t) {
t.printStackTrace();
Log.error("{}: Caught exception in operation remainingTasks={}", queueName, subsystemOperations.size(), t);
}
}
}
protected synchronized void cleanupOperations() {
if (!shutdown) {
if(Log.isTraceEnabled()) {
Log.trace("{}: Submitting clean up operation to executor service", queueName);
}
getContext().getExecutorService().submit(new Runnable() {
public void run() {
if (operationFuture != null) {
if(Log.isTraceEnabled()) {
Log.trace("{}: Cleaning up operations", queueName);
}
try {
if(Log.isTraceEnabled()) {
Log.trace("{}: Waiting for operations to complete", queueName);
}
operationFuture.get();
if(Log.isTraceEnabled()) {
Log.trace("{}: All operations have completed", queueName);
}
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
}
}
});
shutdown = true;
}
}
}
}