/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* 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 org.pentaho.di.core.gui;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.util.EnvUtil;
import org.pentaho.di.job.JobEntryResult;
import org.pentaho.di.job.JobMeta;
import org.pentaho.di.job.entry.JobEntryCopy;
/**
* Responsible for tracking the execution of a job as a hierarchy.
*
* @author Matt
* @since 30-mar-2006
*
*/
public class JobTracker {
/**
* The trackers for each individual job entry.
* Since we invoke LinkedList.removeFirst() there is no sense in lurking the field behind the interface
*/
private LinkedList<JobTracker> jobTrackers;
/** If the jobTrackers list is empty, then this is the result */
private JobEntryResult result;
/** The parent job tracker, null if this is the root */
private JobTracker parentJobTracker;
private String jobName;
private String jobFilename;
private int maxChildren;
private final ReentrantReadWriteLock lock;
/**
* @param jobMeta
* the job metadata to keep track of (with maximum 5000 children)
*/
public JobTracker( JobMeta jobMeta ) {
this( jobMeta, Const.toInt( EnvUtil.getSystemProperty( Const.KETTLE_MAX_JOB_TRACKER_SIZE ), 5000 ) );
}
/**
* @param jobMeta
* The job metadata to track
* @param maxChildren
* The maximum number of children to keep track of (1000 is the default)
*/
public JobTracker( JobMeta jobMeta, int maxChildren ) {
if ( jobMeta != null ) {
this.jobName = jobMeta.getName();
this.jobFilename = jobMeta.getFilename();
}
this.jobTrackers = new LinkedList<JobTracker>();
this.maxChildren = maxChildren;
this.lock = new ReentrantReadWriteLock();
}
/**
* Creates a jobtracker with a single result (maxChildren children are kept)
*
* @param jobMeta
* the job metadata to keep track of
* @param result
* the job entry result to track.
*/
public JobTracker( JobMeta jobMeta, JobEntryResult result ) {
this( jobMeta );
this.result = result;
}
/**
* Creates a jobtracker with a single result
*
* @param jobMeta
* the job metadata to keep track of
* @param maxChildren
* The maximum number of children to keep track of
* @param result
* the job entry result to track.
*/
public JobTracker( JobMeta jobMeta, int maxChildren, JobEntryResult result ) {
this( jobMeta, maxChildren );
this.result = result;
}
public void addJobTracker( JobTracker jobTracker ) {
lock.writeLock().lock();
try {
jobTrackers.add( jobTracker );
while ( jobTrackers.size() > maxChildren ) {
// Use remove instead of subList
jobTrackers.removeFirst();
}
} finally {
lock.writeLock().unlock();
}
}
public JobTracker getJobTracker( int i ) {
lock.readLock().lock();
try {
return jobTrackers.get( i );
} finally {
lock.readLock().unlock();
}
}
public int nrJobTrackers() {
lock.readLock().lock();
try {
return jobTrackers.size();
} finally {
lock.readLock().unlock();
}
}
/**
* Returns a list that contains all job trackers. The list is created as a defensive copy of internal trackers'
* storage.
* @return list of job trackers
*/
public List<JobTracker> getJobTrackers() {
lock.readLock().lock();
try {
return new ArrayList<JobTracker>( jobTrackers );
} finally {
lock.readLock().unlock();
}
}
/**
* @param jobTrackers
* The jobTrackers to set.
*/
public void setJobTrackers( List<JobTracker> jobTrackers ) {
lock.writeLock().lock();
try {
this.jobTrackers.clear();
this.jobTrackers.addAll( jobTrackers );
} finally {
lock.writeLock().unlock();
}
}
/**
* @return Returns the result.
*/
public JobEntryResult getJobEntryResult() {
return result;
}
/**
* @param result
* The result to set.
*/
public void setJobEntryResult( JobEntryResult result ) {
this.result = result;
}
public void clear() {
lock.writeLock().lock();
try {
jobTrackers.clear();
result = null;
} finally {
lock.writeLock().unlock();
}
}
/**
* Finds the JobTracker for the job entry specified. Use this to
*
* @param jobEntryCopy
* The entry to search the job tracker for
* @return The JobTracker of null if none could be found...
*/
public JobTracker findJobTracker( JobEntryCopy jobEntryCopy ) {
if ( jobEntryCopy.getName() == null ) {
return null;
}
lock.readLock().lock();
try {
ListIterator<JobTracker> it = jobTrackers.listIterator( jobTrackers.size() );
while ( it.hasPrevious() ) {
JobTracker tracker = it.previous();
JobEntryResult result = tracker.getJobEntryResult();
if ( result != null ) {
if ( jobEntryCopy.getName().equals( result.getJobEntryName() )
&& jobEntryCopy.getNr() == result.getJobEntryNr() ) {
return tracker;
}
}
}
} finally {
lock.readLock().unlock();
}
return null;
}
/**
* @return Returns the parentJobTracker.
*/
public JobTracker getParentJobTracker() {
return parentJobTracker;
}
/**
* @param parentJobTracker
* The parentJobTracker to set.
*/
public void setParentJobTracker( JobTracker parentJobTracker ) {
this.parentJobTracker = parentJobTracker;
}
public int getTotalNumberOfItems() {
lock.readLock().lock();
try {
int total = 1; // 1 = this one
for ( JobTracker jobTracker : jobTrackers ) {
total += jobTracker.getTotalNumberOfItems();
}
return total;
} finally {
lock.readLock().unlock();
}
}
/**
* @return the jobFilename
*/
public String getJobFilename() {
return jobFilename;
}
/**
* @param jobFilename
* the jobFilename to set
*/
public void setJobFilename( String jobFilename ) {
this.jobFilename = jobFilename;
}
/**
* @return the jobName
*/
public String getJobName() {
return jobName;
}
/**
* @param jobName
* the jobName to set
*/
public void setJobName( String jobName ) {
this.jobName = jobName;
}
/**
* @return the maxChildren
*/
public int getMaxChildren() {
return maxChildren;
}
/**
* @param maxChildren
* the maxChildren to set
*/
public void setMaxChildren( int maxChildren ) {
this.maxChildren = maxChildren;
}
}