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

com.ibm.batch.container.impl.SplitControllerImpl Maven / Gradle / Ivy

The 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.batch.container.impl;

import java.io.Externalizable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.batch.operations.JobOperator.BatchStatus;

import jsr352.batch.jsl.Flow;
import jsr352.batch.jsl.JSLJob;
import jsr352.batch.jsl.Split;

import com.ibm.batch.container.AbortedBeforeStartException;
import com.ibm.batch.container.IExecutionElementController;
import com.ibm.batch.container.context.impl.StepContextImpl;
import com.ibm.batch.container.exception.BatchContainerRuntimeException;
import com.ibm.batch.container.jobinstance.ParallelJobExecution;
import com.ibm.batch.container.jobinstance.RuntimeJobExecutionImpl;
import com.ibm.batch.container.services.ServicesManager;
import com.ibm.batch.container.services.ServicesManager.ServiceType;
import com.ibm.batch.container.util.PartitionDataWrapper;

public class SplitControllerImpl implements IExecutionElementController {

    private final static String sourceClass = SplitControllerImpl.class.getName();
    private final static Logger logger = Logger.getLogger(sourceClass);
	
	private final RuntimeJobExecutionImpl jobExecutionImpl;
    
	private volatile List parallelJobExecs;

	private final ServicesManager servicesManager;
	private final BatchKernelImpl batchKernel;
    
	final List subJobs = new ArrayList();
	
    protected Split split;

    public SplitControllerImpl(RuntimeJobExecutionImpl jobExecutionImpl, Split split) {
        this.jobExecutionImpl = jobExecutionImpl;
        this.split = split;
        
		servicesManager = ServicesManager.getInstance();
		batchKernel = (BatchKernelImpl) servicesManager.getService(ServiceType.BATCH_KERNEL_SERVICE);
        
    }

    @Override
    public void stop() { 

		// It's possible we may try to stop a split before any
		// sub steps have been started.

		synchronized (subJobs) {
		
			if (parallelJobExecs != null) {
				for (ParallelJobExecution subJob : parallelJobExecs) {
					try {
						batchKernel.stopJob(subJob.getJobExecution().getInstanceId());
					} catch (Exception e) {
						// TODO - Is this what we want to know.  
						// Blow up if it happens to force the issue.
						throw new IllegalStateException(e);
					}
				}
			}
		}
        
    }

    @Override
    public String execute() throws AbortedBeforeStartException {
        String sourceMethod = "execute";
        if (logger.isLoggable(Level.FINER)) {
            logger.entering(sourceClass, sourceMethod);
        }
        
        List flows = this.split.getFlow();
        
		// Build all sub jobs from flows in split
		synchronized (subJobs) {
			
			for (Flow flow : flows) {
				subJobs.add(PartitionedStepBuilder.buildSubJob(jobExecutionImpl.getExecutionId(), this.split, flow, null));
			}
			
			// Then execute all subjobs in parallel
			//FIXME Right now we don't pass any job parameters along for a split!!! I don't think this is right
			//FIXME Each flow in a split should probably get a copy of the job params
			parallelJobExecs = batchKernel.startParallelJobs(subJobs, null, null);

		}
        
		// Then wait for the all the parallel jobs to end/stop/fail/complete
		// etc..
		// This is like a call to Thread.join()
		for (final ParallelJobExecution subJob : parallelJobExecs) {
			subJob.waitForResult();
		}
		

		//FIXME
		//check the batch status of each subJob after it's done to see if it stopped or failed
		for (final ParallelJobExecution subJob : parallelJobExecs) {
			BatchStatus batchStatus = subJob.getJobExecution().getJobContext().getBatchStatus();
			if (batchStatus.equals(BatchStatus.FAILED)) {
				if (logger.isLoggable(Level.FINE)) {
					logger.fine("Subjob " + subJob.getJobExecution().getExecutionId() + "ended with status '" + batchStatus + "'" );
					logger.fine("Starting logical transaction rollback.");
				}
				
				break;
			} else if (batchStatus.equals(BatchStatus.STOPPED)){
				if (logger.isLoggable(Level.FINE)) {
					logger.fine("Subjob " + subJob.getJobExecution().getExecutionId() + "ended with status '" + batchStatus + "'" );
					logger.fine("Starting logical transaction rollback.");
				}
				break;
			}
		}
		
        if (logger.isLoggable(Level.FINER)) {
            logger.exiting(sourceMethod, sourceMethod);
        }

        return "SPLIT_CONTROLLER_RETURN_VALUE";
        
    }

    public void setStepContext(StepContextImpl stepContext) {
        throw new BatchContainerRuntimeException("Incorrect usage: step context is not in scope within a flow.");
    }

    @Override
    public void setAnalyzerQueue(LinkedBlockingQueue analyzerQueue) {
        // no-op
    }

	public List getParallelJobExecs() {
		return parallelJobExecs;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy