org.jpac.RemoteSignalOutputDaemon Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elbfisch.core Show documentation
Show all versions of elbfisch.core Show documentation
Open-source runtime system for component-based implementation of automation solutions with Java
The newest version!
/**
* PROJECT : Elbfisch - java process automation controller (jPac)
* MODULE : RemoteSignalOutputDaemon.java
* VERSION : -
* DATE : -
* PURPOSE :
* AUTHOR : Bernd Schuster, MSK Gesellschaft fuer Automatisierung mbH, Schenefeld
* REMARKS : -
* CHANGES : CH#n
*
* This file is part of the jPac process automation controller.
* jPac is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* jPac 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the jPac If not, see .
*/
package org.jpac;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
/**
* handles the communication with a remote jPac instance. Will be automatically started, if a remote jPac instance is involved.
* @author berndschuster
*/
@Deprecated
public class RemoteSignalOutputDaemon extends Thread{
static Logger Log = LoggerFactory.getLogger("jpac.Remote");
static final long STOPTDAEMONTIMEOUT = 3000000000L;// 3 sec.
static final int CONNECTRETRYTIME = 5000; // 5 sec.
static final int DEFAULTPUSHTIME = 1000; // 1 sec.
private boolean stopRunning;
private RemoteSignalConnection remoteSignalConnection;
private boolean online;
private RemoteSignalFrame recentRemoteSignalFrame;
private CyclicBuffer frameBuffer;
private RemoteSignalHandler remoteSignalHandler;
private RemoteSignalFrame lastFrameTransferred;
public RemoteSignalOutputDaemon(RemoteSignalConnection remoteSignalConnection) {
super();
this.remoteSignalConnection = remoteSignalConnection;
this.stopRunning = false;
this.frameBuffer = new CyclicBuffer(10);
this.recentRemoteSignalFrame = null;
this.remoteSignalHandler = null;
this.lastFrameTransferred = new RemoteSignalFrame();
this.online = false;
}
@Override
public void run(){
boolean done = false;
boolean newFrameArrived = false;
boolean atLeastOneFrameArrived = false;
RemoteSignalFrame remoteSignalFrame = null;
String jPacInstance = JPac.getInstance().getInstanceIdentifier();
setName("RemoteSignalOutputDaemon");
try{
if(Log.isDebugEnabled()) Log.debug("remote signal output to JPac instance " + remoteSignalConnection.getRemoteJPacInstance() + " started ...");
do{
online = connectSignals();
while(online && !stopRunning){
try{
newFrameArrived = !frameBuffer.waitUntilFilled(DEFAULTPUSHTIME);
if (online && !stopRunning){
if (newFrameArrived){
atLeastOneFrameArrived = true;
remoteSignalFrame = frameBuffer.get();
Log.debug("pushing frame to " + remoteSignalConnection.getHost() + ": " + remoteSignalFrame);
getRemoteSignalHandler().push(jPacInstance,remoteSignalFrame);
//store this frame for cyclic repetition
lastFrameTransferred.copy(remoteSignalFrame);
//release received frame
frameBuffer.release();
}
else{
//send last frame transferred periodically
if (atLeastOneFrameArrived){
Log.debug("pushing last frame to " + remoteSignalConnection.getHost() + ": " + remoteSignalFrame);
getRemoteSignalHandler().push(jPacInstance, lastFrameTransferred);
}
}
}
}
catch(java.rmi.RemoteException exc){
Log.error("Connection to remote JPac instance " + remoteSignalConnection.getRemoteJPacInstance() + " lost !!!");
online = false;
}
}
}
while(!stopRunning);
}
catch(Exception exc){
Log.error("Error: ", exc);
}
catch(Error exc){
Log.error("Error: ", exc);
}
finally{
if(Log.isDebugEnabled()) Log.debug("remote signal output to JPac instance " + remoteSignalConnection.getRemoteJPacInstance() + " stopped");
if (online){
try{
getRemoteSignalHandler().disconnect(jPacInstance);
}
catch(Exception exc){
Log.error("Error: ", exc);
}
}
online = false;
}
}
public void stopDaemon(){
if (Log.isDebugEnabled()) Log.debug(" stopping RemoteSignalOutputDaemon for " + remoteSignalConnection.getRemoteJPacInstance());
stopRunning = true;
// long timeoutTime = System.nanoTime() + STOPTDAEMONTIMEOUT;
// while(getState() != State.TERMINATED && System.nanoTime() < timeoutTime);
// if (System.nanoTime() < timeoutTime){
// if (Log.isInfoEnabled()) Log.info(" RemoteSignalOutputDaemon for " + remoteSignalConnection.getRemoteJPacInstance() + " stopped");
// }
// else{
// Log.error(" failed to stop RemoteSignalOutputDaemon for " + remoteSignalConnection.getRemoteJPacInstance() + " status: " + getState());
// }
}
public CyclicBuffer getFrameBuffer(){
return this.frameBuffer;
}
@Override
public String toString(){
return getClass().getCanonicalName() + "(" + remoteSignalConnection.getRemoteJPacInstance() + ")";
}
public boolean push(RemoteSignalFrame remoteSignalFrame){
RemoteSignalFrame frame = null;
synchronized(this){
try{
if (!online){
//if the connection to the remote JPac instance is offline
//first remove the contence of the frame buffer,
//so that the remote host will receive the recent state of
//the pushed signals, when it goes online again
frameBuffer.clear();
}
//if online check, if at least one of the signals to be transported has changed to avoid needless traffic
if ((!remoteSignalFrame.signalsEqual(recentRemoteSignalFrame)) && online){
//if so, push the new frame into the cyclic buffer
if (frameBuffer.isFull()){
//if the frame buffer is full, drop the oldest entry !!!!!
RemoteSignalFrame droppedFrame = null;
droppedFrame = frameBuffer.get();
frameBuffer.release();
Log.error("remote signal frame " + droppedFrame + " dropped for remote JPac instance " + remoteSignalConnection.getRemoteJPacInstance());
}
//get the next free entry
frame = frameBuffer.occupy();
//and (re)initialize it, if necessary
if (frame == null || frame.structureDifferent(remoteSignalFrame)){
if (frame != null && Log.isDebugEnabled()) Log.debug("frame structure changed for remote JPac instance " + remoteSignalConnection.getRemoteJPacInstance());
frame = remoteSignalFrame.clone();
}
else{
//or take over the contence of the new frame
frame.copy(remoteSignalFrame);
}
//actualize the cycle number
frame.setCycleNumber(remoteSignalFrame.getCycleNumber());
//and push the new frame into the queue
frameBuffer.put(frame);
//keep in mind this recent frame for comparison in future cycles
if (recentRemoteSignalFrame == null || recentRemoteSignalFrame.structureDifferent(frame)){
recentRemoteSignalFrame = frame.clone();
}
else{
recentRemoteSignalFrame.copy(frame);
}
if (Log.isDebugEnabled()) Log.debug("frame queued for transfer to remote JPac instance " + remoteSignalConnection.getRemoteJPacInstance());//+ " = " + frame);
}
}
catch(Exception exc){
Log.error("Error:", exc);
}
catch(Error exc){
Log.error("Error:", exc);
}
}
return online;
}
private boolean connectSignals() throws Exception{
boolean connected = false;
String jPacInstance = JPac.getInstance().getInstanceIdentifier();
remoteSignalHandler = null;//force renewal of the remote signal handler;
if (Log.isDebugEnabled()) Log.debug("try to connect to " + remoteSignalConnection.getHost() + " ...");
do{
try{
if (isReachable(remoteSignalConnection)){
//if remote instance is reachable, connect desired signals.
getRemoteSignalHandler().connect(jPacInstance, remoteSignalConnection.getOutputSignals());
connected = true;
if (Log.isDebugEnabled()) Log.debug("... connected to " + remoteSignalConnection.getHost());
}
}
catch(Exception exc){
if (Log.isDebugEnabled()) Log.debug("connection failed: ",exc);
}
catch(Error exc){
Log.error("other errors: ", exc);
throw new Exception(exc);
}
if (!connected && !stopRunning){
//wait a period of time before trying it once more
try{Thread.sleep(CONNECTRETRYTIME);}catch(InterruptedException exc){};
}
}
while(!connected && !stopRunning);
return connected;
}
private boolean isReachable(RemoteSignalConnection remoteSignalConnection){
boolean reachable = false;
try{
//try to connect to remote signal service
Socket socket = new Socket(remoteSignalConnection.getHost(), remoteSignalConnection.getPort());
//if succeeded, close it at once
socket.close();
reachable = true;
}
catch(Exception exc){
reachable = false;
}
return reachable;
}
RemoteSignalHandler getRemoteSignalHandler() throws RemoteException, NotBoundException, MalformedURLException, UnknownHostException{
if (remoteSignalHandler == null){
remoteSignalHandler = (RemoteSignalHandler) Naming.lookup("//" + remoteSignalConnection.getRemoteJPacInstance() + "/" + "RemoteSignalService");
}
return remoteSignalHandler;
}
}