/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.component.execution.internal; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicReference; import org.apache.commons.logging.LogFactory; import de.rcenvironment.core.communication.api.CommunicationService; import de.rcenvironment.core.communication.api.PlatformService; import de.rcenvironment.core.communication.common.LogicalNodeId; import de.rcenvironment.core.communication.common.ResolvableNodeId; import de.rcenvironment.core.component.execution.api.ComponentExecutionContext; import de.rcenvironment.core.component.execution.api.ComponentExecutionControllerService; import de.rcenvironment.core.component.execution.api.ComponentExecutionException; import de.rcenvironment.core.component.execution.api.ComponentExecutionInformation; import de.rcenvironment.core.component.execution.api.ComponentExecutionService; import de.rcenvironment.core.component.execution.api.ComponentState; import de.rcenvironment.core.component.execution.api.ExecutionControllerException; import de.rcenvironment.core.component.execution.api.RemotableComponentExecutionControllerService; import de.rcenvironment.core.toolkitbridge.transitional.ConcurrencyUtils; import de.rcenvironment.core.utils.common.rpc.RemoteOperationException; import de.rcenvironment.toolkit.modules.concurrency.api.AsyncExceptionListener; import de.rcenvironment.toolkit.modules.concurrency.api.CallablesGroup; import de.rcenvironment.toolkit.modules.concurrency.api.TaskDescription; /** * Implementation of {@link ComponentExecutionService}. * * @author Doreen Seider * @author Robert Mischke (id and caching adaptations) */ public class ComponentExecutionServiceImpl implements ComponentExecutionService { private CommunicationService communicationService; private ComponentExecutionControllerService cmpExeCtrlService; private PlatformService platformService; @Override public String init(ComponentExecutionContext executionContext, String authToken, Long referenceTimestamp) throws RemoteOperationException, ComponentExecutionException { return getExecutionControllerService(executionContext.getNodeId()) .createExecutionController(executionContext, authToken, referenceTimestamp); } @Override public void pause(String executionId, ResolvableNodeId node) throws ExecutionControllerException, RemoteOperationException { getExecutionControllerService(node).performPause(executionId); } @Override public void resume(String executionId, ResolvableNodeId node) throws ExecutionControllerException, RemoteOperationException { getExecutionControllerService(node).performResume(executionId); } @Override public void cancel(String executionId, ResolvableNodeId node) throws ExecutionControllerException, RemoteOperationException { getExecutionControllerService(node).performCancel(executionId); } @Override public void dispose(String executionId, ResolvableNodeId node) throws ExecutionControllerException, RemoteOperationException { getExecutionControllerService(node).performDispose(executionId); } @Override public void prepare(String executionId, ResolvableNodeId node) throws ExecutionControllerException, RemoteOperationException { getExecutionControllerService(node).performPrepare(executionId); } @Override public void start(String executionId, ResolvableNodeId node) throws ExecutionControllerException, RemoteOperationException { getExecutionControllerService(node).performStart(executionId); } @Override public ComponentState getComponentState(String executionId, ResolvableNodeId node) throws ExecutionControllerException, RemoteOperationException { return getExecutionControllerService(node).getComponentState(executionId); } @Override public ComponentExecutionInformation getComponentExecutionInformation(final String verificationToken) throws RemoteOperationException { final AtomicReference<RemoteOperationException> remoteOperationExceptionRef = new AtomicReference<RemoteOperationException>(null); CallablesGroup<ComponentExecutionInformation> callablesGroup = ConcurrencyUtils.getFactory().createCallablesGroup(ComponentExecutionInformation.class); for (LogicalNodeId logicalNodeId : communicationService.getReachableLogicalNodes()) { final LogicalNodeId nodeId = logicalNodeId; callablesGroup.add(new Callable<ComponentExecutionInformation>() { @TaskDescription("Fetching component information") @Override public ComponentExecutionInformation call() throws Exception { ComponentExecutionInformation compExeInfo = getExecutionControllerService(nodeId).getComponentExecutionInformation(verificationToken); if (compExeInfo != null) { return compExeInfo; } return null; } }); List<ComponentExecutionInformation> compExeInfos = callablesGroup.executeParallel(new AsyncExceptionListener() { @Override public void onAsyncException(Exception e) { if (e instanceof RemoteOperationException && remoteOperationExceptionRef.get() == null) { remoteOperationExceptionRef.set((RemoteOperationException) e); } LogFactory.getLog(ComponentExecutionServiceImpl.class) .error("Error in asychronous request when retrieving component execution information for a verification key", e); } }); if (remoteOperationExceptionRef.get() != null) { throw remoteOperationExceptionRef.get(); } for (ComponentExecutionInformation compExeInfo : compExeInfos) { if (compExeInfo != null) { return compExeInfo; } } } return null; } @Override public boolean verifyResults(String executionId, ResolvableNodeId node, String verificationToken, boolean verified) throws ExecutionControllerException, RemoteOperationException { return getExecutionControllerService(node).performVerifyResults(executionId, verificationToken, verified); } @Override public Set<ComponentExecutionInformation> getLocalComponentExecutionInformations() { return new HashSet<ComponentExecutionInformation>(cmpExeCtrlService.getComponentExecutionInformations()); } private RemotableComponentExecutionControllerService getExecutionControllerService(ResolvableNodeId node) { if (platformService.matchesLocalInstance(node)) { return cmpExeCtrlService; } else { // fetching the service proxy on each call, assuming that it will be cached centrally if necessary return communicationService.getRemotableService(RemotableComponentExecutionControllerService.class, node); } } protected void bindCommunicationService(CommunicationService newService) { communicationService = newService; } protected void bindPlatformService(PlatformService newService) { platformService = newService; } protected void bindComponentExecutionControllerService(ComponentExecutionControllerService newService) { cmpExeCtrlService = newService; } }