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

com.ibm.jbatch.container.impl.ExecutionTransitioner Maven / Gradle / Ivy

There is a newer version: 1.0
Show newest version
/*
 * Copyright 2012 International Business Machines Corp.
 * 
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership. 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.ibm.jbatch.container.impl;

import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Logger;

import javax.batch.runtime.BatchStatus;

import com.ibm.jbatch.container.IController;
import com.ibm.jbatch.container.IExecutionElementController;
import com.ibm.jbatch.container.context.impl.JobContextImpl;
import com.ibm.jbatch.container.context.impl.StepContextImpl;
import com.ibm.jbatch.container.exception.BatchContainerRuntimeException;
import com.ibm.jbatch.container.jobinstance.RuntimeJobExecution;
import com.ibm.jbatch.container.jsl.ExecutionElement;
import com.ibm.jbatch.container.jsl.IllegalTransitionException;
import com.ibm.jbatch.container.jsl.Transition;
import com.ibm.jbatch.container.jsl.TransitionElement;
import com.ibm.jbatch.container.navigator.ModelNavigator;
import com.ibm.jbatch.container.status.ExtendedBatchStatus;
import com.ibm.jbatch.container.status.ExecutionStatus;
import com.ibm.jbatch.container.util.PartitionDataWrapper;
import com.ibm.jbatch.jsl.model.Decision;
import com.ibm.jbatch.jsl.model.End;
import com.ibm.jbatch.jsl.model.Fail;
import com.ibm.jbatch.jsl.model.Flow;
import com.ibm.jbatch.jsl.model.JSLJob;
import com.ibm.jbatch.jsl.model.Split;
import com.ibm.jbatch.jsl.model.Step;
import com.ibm.jbatch.jsl.model.Stop;

public class ExecutionTransitioner {

	private final static String CLASSNAME = ExecutionTransitioner.class.getName();
	private final static Logger logger = Logger.getLogger(CLASSNAME);

	private RuntimeJobExecution jobExecution;
	private long rootJobExecutionId;
	private ModelNavigator modelNavigator;
	
	// 'volatile' since it receives stop on separate thread.
	private volatile IExecutionElementController currentStoppableElementController;
	private IExecutionElementController previousElementController;
	private ExecutionElement currentExecutionElement = null;
	private ExecutionElement previousExecutionElement = null;

	
	private JobContextImpl jobContext;
	private BlockingQueue analyzerQueue = null;
	
	private List stepExecIds;
	
	public ExecutionTransitioner(RuntimeJobExecution jobExecution, long rootJobExecutionId, ModelNavigator modelNavigator) {
		this.jobExecution = jobExecution;
		this.rootJobExecutionId = rootJobExecutionId;
		this.modelNavigator = modelNavigator;
		this.jobContext = jobExecution.getJobContext(); 
	}
	
	public ExecutionTransitioner(RuntimeJobExecution jobExecution, long rootJobExecutionId, ModelNavigator jobNavigator, BlockingQueue analyzerQueue) {
		this.jobExecution = jobExecution;
		this.rootJobExecutionId = rootJobExecutionId;
		this.modelNavigator = jobNavigator;
		this.jobContext = jobExecution.getJobContext(); 
		this.analyzerQueue = analyzerQueue;
	}
	
	/**
	 * Used for job and flow.
	 * @return
	 */
	public ExecutionStatus doExecutionLoop() {

		final String methodName = "doExecutionLoop";
		
		try {
			currentExecutionElement = modelNavigator.getFirstExecutionElement(jobExecution.getRestartOn());
		} catch (IllegalTransitionException e) {
			String errorMsg = "Could not transition to first execution element within job.";
			logger.warning(errorMsg);
			throw new IllegalArgumentException(errorMsg, e);
		}

		logger.fine("First execution element = " + currentExecutionElement.getId());

		while (true) {

			if (jobContext.getBatchStatus().equals(BatchStatus.STOPPING)) {
				logger.fine(methodName + " Exiting execution loop as job is now in stopping state.");
				return new ExecutionStatus(ExtendedBatchStatus.JOB_OPERATOR_STOPPING);
			}
			
			IExecutionElementController currentElementController = getNextElementController();
			currentStoppableElementController = currentElementController;
			
			ExecutionStatus status = currentElementController.execute();

			// Nothing special for decision or step except to get exit status.  For flow and split we want to bubble up though.
			if ((currentExecutionElement instanceof Split) || (currentExecutionElement instanceof Flow)) {
				// Exit status and restartOn should both be in the job context.
				if (!status.getExtendedBatchStatus().equals(ExtendedBatchStatus.NORMAL_COMPLETION)) {
					logger.fine("Breaking out of loop with return status = " + status.getExtendedBatchStatus().name());
					return status;
				}
			} 

			// Seems like this should only happen if an Error is thrown at the step level, since normally a step-level
			// exception is caught and the fact that it was thrown capture in the ExecutionStatus
			if (jobContext.getBatchStatus().equals(BatchStatus.FAILED)) {
				String errorMsg = "Sub-execution returned its own BatchStatus of FAILED.  Deal with this by throwing exception to the next layer.";
				logger.warning(errorMsg);
				throw new BatchContainerRuntimeException(errorMsg);
			}

			// set the execution element controller to null so we don't try to call stop on it after the element has finished executing
			currentStoppableElementController = null;
			
			logger.fine("Done executing element=" + currentExecutionElement.getId() + ", exitStatus=" + status.getExitStatus());

			if (jobContext.getBatchStatus().equals(BatchStatus.STOPPING)) {
				logger.fine(methodName + " Exiting as job has been stopped");
				return new ExecutionStatus(ExtendedBatchStatus.JOB_OPERATOR_STOPPING);
			}

			Transition nextTransition = null;
			try {
				nextTransition = modelNavigator.getNextTransition(currentExecutionElement, status);
			} catch (IllegalTransitionException e) {
				String errorMsg = "Problem transitioning to next execution element.";
				logger.warning(errorMsg);
				throw new BatchContainerRuntimeException(errorMsg, e);
			} 

			//
			// We will find ourselves in one of four states now.  
			// 
			// 1. Finished transitioning after a normal execution, but nothing to do 'next'.
			// 2. We just executed a step which through an exception, but didn't match a transition element.
			// 3. We are going to 'next' to another execution element (and jump back to the top of this '
			//    'while'-loop.
			// 4. We matched a terminating transition element (,  or  : " + transitionElement + " with restartOn=" + restartOn + 
					" , and JSL exit status = " + exitStatusFromJSL);

			retVal = new ExecutionStatus(ExtendedBatchStatus.JSL_STOP);
			
			if (exitStatusFromJSL != null) {
				jobContext.setExitStatus(exitStatusFromJSL);  
				retVal.setExitStatus(exitStatusFromJSL);  
			}
			if (restartOn != null) {
				jobContext.setRestartOn(restartOn);				
				retVal.setRestartOn(restartOn);				
			}
		} else if (transitionElement instanceof End) {

			End endElement = (End)transitionElement;
			String exitStatusFromJSL = endElement.getExitStatus();
			logger.fine("Next transition element is an  : " + transitionElement + 
					" with JSL exit status = " + exitStatusFromJSL);
			retVal = new ExecutionStatus(ExtendedBatchStatus.JSL_END);
			if (exitStatusFromJSL != null) {
				jobContext.setExitStatus(exitStatusFromJSL);  
				retVal.setExitStatus(exitStatusFromJSL);  
			}
		} else if (transitionElement instanceof Fail) {

			Fail failElement = (Fail)transitionElement;
			String exitStatusFromJSL = failElement.getExitStatus();
			logger.fine("Next transition element is a  : " + transitionElement + 
					" with JSL exit status = " + exitStatusFromJSL);
			retVal = new ExecutionStatus(ExtendedBatchStatus.JSL_FAIL);
			if (exitStatusFromJSL != null) {
				jobContext.setExitStatus(exitStatusFromJSL);  
				retVal.setExitStatus(exitStatusFromJSL);  
			}
		} else {
			throw new IllegalStateException("Not sure how we'd get here...aborting.");
		}
		return retVal;
	}

	public IController getCurrentStoppableElementController() {
		return currentStoppableElementController;
	}

    public List getStepExecIds() {
        return stepExecIds;
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy