/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.component.execution.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import de.rcenvironment.core.component.api.ComponentConstants;
import de.rcenvironment.core.component.execution.api.ComponentExecutionContext;
import de.rcenvironment.core.component.execution.api.ComponentExecutionController;
import de.rcenvironment.core.component.execution.api.ComponentExecutionException;
import de.rcenvironment.core.component.execution.api.ComponentState;
import de.rcenvironment.core.component.execution.api.WorkflowExecutionControllerCallbackService;
import de.rcenvironment.core.component.model.endpoint.api.EndpointDatum;
import de.rcenvironment.core.utils.common.StringUtils;
import de.rcenvironment.core.utils.common.rpc.RemoteOperationException;
import de.rcenvironment.core.utils.incubator.DebugSettings;
/**
* Implementation of {@link ComponentExecutionController}.
*
* @author Doreen Seider
*/
public class ComponentExecutionControllerImpl implements ComponentExecutionController {
private static final Log LOG = LogFactory.getLog(ComponentExecutionControllerImpl.class);
private static final boolean VERBOSE_LOGGING = DebugSettings.getVerboseLoggingEnabled(ComponentExecutionControllerImpl.class);
private static ComponentExecutionRelatedInstancesFactory compExeInstancesFactory;
private ComponentExecutionRelatedInstances compExeRelatedInstances;
private String compInstanceName;
private Object verifyLock = new Object();
@Deprecated
public ComponentExecutionControllerImpl() {}
public ComponentExecutionControllerImpl(ComponentExecutionContext compExeCtx,
WorkflowExecutionControllerCallbackService wfExeCtrlBridge, long currentTimestampOffWorkflowNode) {
this.compInstanceName = compExeCtx.getInstanceName();
int timestampOffsetToWorkfowNode = (int) (currentTimestampOffWorkflowNode - System.currentTimeMillis());
compExeRelatedInstances = new ComponentExecutionRelatedInstances();
compExeRelatedInstances.compExeCtx = compExeCtx;
compExeRelatedInstances.timestampOffsetToWorkfowNode = timestampOffsetToWorkfowNode;
compExeRelatedInstances.wfExeCtrlBridge = wfExeCtrlBridge;
compExeRelatedInstances.compExeStorageBridge =
compExeInstancesFactory.createComponentExecutionStorageBridge(compExeRelatedInstances);
compExeRelatedInstances.compStateMachine = compExeInstancesFactory.createComponentStateMachine(compExeRelatedInstances);
compExeRelatedInstances.compExeScheduler = compExeInstancesFactory.createComponentExecutionScheduler(compExeRelatedInstances);
}
@Override
public void prepare() {
compExeRelatedInstances.compStateMachine
.postEvent(new ComponentStateMachineEvent(ComponentStateMachineEventType.PREPARE_REQUESTED));
}
@Override
public void start() {
compExeRelatedInstances.compStateMachine.postEvent(new ComponentStateMachineEvent(ComponentStateMachineEventType.START_REQUESTED));
}
@Override
public void pause() {
compExeRelatedInstances.compStateMachine.postEvent(new ComponentStateMachineEvent(ComponentStateMachineEventType.PAUSE_REQUESTED));
}
@Override
public void resume() {
compExeRelatedInstances.compStateMachine.postEvent(new ComponentStateMachineEvent(ComponentStateMachineEventType.RESUME_REQUESTED));
}
@Override
public void restart() {
throw new UnsupportedOperationException("Restarting components not yet implemented");
}
@Override
public void cancel() {
compExeRelatedInstances.compStateMachine.postEvent(new ComponentStateMachineEvent(ComponentStateMachineEventType.CANCEL_REQUESTED));
}
@Override
public boolean cancelSync(long timeoutMsec) throws InterruptedException {
cancel();
final int waitIntervalMsec = 400;
long startTime = System.currentTimeMillis();
do {
Thread.sleep(waitIntervalMsec);
if (ComponentConstants.FINAL_COMPONENT_STATES.contains(compExeRelatedInstances.compStateMachine.getState())) {
return true;
}
} while (System.currentTimeMillis() - startTime > timeoutMsec);
return false;
}
@Override
public void dispose() {
compExeRelatedInstances.compStateMachine
.postEvent(new ComponentStateMachineEvent(ComponentStateMachineEventType.DISPOSE_REQUESTED));
}
@Override
public void onEndpointDatumReceived(final EndpointDatum endpointDatum) {
compExeRelatedInstances.compExeScheduler.validateAndQueueEndpointDatum(endpointDatum);
if (VERBOSE_LOGGING) {
LOG.debug(StringUtils.format("Received at %s@%s: %s (from %s)", endpointDatum.getInputName(), compInstanceName,
endpointDatum.getValue(), endpointDatum.getOutputsComponentExecutionIdentifier()));
}
}
@Override
public void onSendingEndointDatumFailed(EndpointDatum endpointDatum, RemoteOperationException e) {
compExeRelatedInstances.compStateMachine
.postEvent(new ComponentStateMachineEvent(ComponentStateMachineEventType.PROCESSING_INPUTS_FAILED,
new ComponentExecutionException(StringUtils.format("Failed to send output value to input '%s' of '%s' at %s",
endpointDatum.getInputName(), endpointDatum.getInputsComponentInstanceName(),
endpointDatum.getInputsNodeId()), e)));
}
@Override
public ComponentState getState() {
return compExeRelatedInstances.compStateMachine.getState();
}
@Override
public String getVerificationToken() {
return compExeRelatedInstances.compStateMachine.getVerificationToken();
}
@Override
public boolean isWorkflowControllerReachable() {
return compExeRelatedInstances.compStateMachine.isWorkflowControllerReachable();
}
@Override
public boolean verifyResults(String verificationToken, boolean verified) {
synchronized (verifyLock) {
if (compExeRelatedInstances.compStateMachine.getVerificationToken() == null
|| !compExeRelatedInstances.compStateMachine.getVerificationToken().equals(verificationToken)) {
return false;
}
if (verified) {
compExeRelatedInstances.compStateMachine
.postEvent(new ComponentStateMachineEvent(ComponentStateMachineEventType.RESULTS_APPROVED));
} else {
compExeRelatedInstances.compStateMachine
.postEvent(new ComponentStateMachineEvent(ComponentStateMachineEventType.RESULTS_REJECTED));
}
return true;
}
}
protected void bindComponentExecutionRelatedInstancesFactory(ComponentExecutionRelatedInstancesFactory newService) {
ComponentExecutionControllerImpl.compExeInstancesFactory = newService;
}
protected ComponentExecutionRelatedInstances geComponentExecutionRelatedInstances() {
return compExeRelatedInstances;
}
}