use of org.pentaho.di.job.entry.JobEntryInterface in project pentaho-kettle by pentaho.
the class JobTest method executeWithPreviousCheckpointTest.
/**
* Tests the re-execution of a sub-job with a checkpoint and Previous Results (Called by JobExecutor - Job Calling
* another Job) The called Job is set to Repeat
*/
@Test
public void executeWithPreviousCheckpointTest() {
setupJobMockExecution();
try {
when(mockedJob.execute(anyInt(), any(Result.class))).thenCallRealMethod();
JobEntryCopy startJobEntryCopy = mock(JobEntryCopy.class);
Result startJobEntryResult = mock(Result.class);
JobEntryInterface mockJobEntryInterface = mock(JobEntryInterface.class, withSettings().extraInterfaces(VariableSpace.class));
when(startJobEntryCopy.getEntry()).thenReturn(mockJobEntryInterface);
when(mockJobEntryInterface.getLogChannel()).thenReturn(mockedLogChannel);
when(mockJobEntryInterface.clone()).thenReturn(mockJobEntryInterface);
when(startJobEntryResult.clone()).thenReturn(startJobEntryResult);
setInternalState(mockedJob, "startJobEntryCopy", startJobEntryCopy);
setInternalState(mockedJob, "startJobEntryResult", startJobEntryResult);
when(mockJobEntryInterface.execute(startJobEntryResult, 0)).thenReturn(new Result());
mockedJob.execute(0, new Result());
// Verify that the execute used the start point supplied with result supplied instead of starting from the start
verify(mockJobEntryInterface, times(1)).execute(eq(startJobEntryResult), eq(0));
verify(mockedJobEntrySpecial, times(0)).execute(any(Result.class), anyInt());
} catch (KettleException e) {
Assert.fail("Could not execute job");
}
}
use of org.pentaho.di.job.entry.JobEntryInterface in project pentaho-kettle by pentaho.
the class Job method execute.
/**
* Execute a job entry recursively and move to the next job entry automatically.<br>
* Uses a back-tracking algorithm.<br>
*
* @param nr
* @param prev_result
* @param jobEntryCopy
* @param previous
* @param reason
* @return
* @throws KettleException
*/
private Result execute(final int nr, Result prev_result, final JobEntryCopy jobEntryCopy, JobEntryCopy previous, String reason) throws KettleException {
Result res = null;
if (isStopped()) {
res = new Result(nr);
res.stopped = true;
return res;
}
// if we didn't have a previous result, create one, otherwise, copy the content...
//
final Result newResult;
Result prevResult = null;
if (prev_result != null) {
prevResult = prev_result.clone();
} else {
prevResult = new Result();
}
JobExecutionExtension extension = new JobExecutionExtension(this, prevResult, jobEntryCopy, true);
ExtensionPointHandler.callExtensionPoint(log, KettleExtensionPoint.JobBeforeJobEntryExecution.id, extension);
if (extension.result != null) {
prevResult = extension.result;
}
if (!extension.executeEntry) {
newResult = prevResult;
} else {
if (log.isDetailed()) {
log.logDetailed("exec(" + nr + ", " + (prev_result != null ? prev_result.getNrErrors() : 0) + ", " + (jobEntryCopy != null ? jobEntryCopy.toString() : "null") + ")");
}
// Which entry is next?
JobEntryInterface jobEntryInterface = jobEntryCopy.getEntry();
jobEntryInterface.getLogChannel().setLogLevel(logLevel);
// Track the fact that we are going to launch the next job entry...
JobEntryResult jerBefore = new JobEntryResult(null, null, BaseMessages.getString(PKG, "Job.Comment.JobStarted"), reason, jobEntryCopy.getName(), jobEntryCopy.getNr(), environmentSubstitute(jobEntryCopy.getEntry().getFilename()));
jobTracker.addJobTracker(new JobTracker(jobMeta, jerBefore));
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(jobEntryInterface.getClass().getClassLoader());
// Execute this entry...
JobEntryInterface cloneJei = (JobEntryInterface) jobEntryInterface.clone();
((VariableSpace) cloneJei).copyVariablesFrom(this);
cloneJei.setRepository(rep);
if (rep != null) {
cloneJei.setMetaStore(rep.getMetaStore());
}
cloneJei.setParentJob(this);
cloneJei.setParentJobMeta(this.getJobMeta());
final long start = System.currentTimeMillis();
cloneJei.getLogChannel().logDetailed("Starting job entry");
for (JobEntryListener jobEntryListener : jobEntryListeners) {
jobEntryListener.beforeExecution(this, jobEntryCopy, cloneJei);
}
if (interactive) {
if (jobEntryCopy.isTransformation()) {
getActiveJobEntryTransformations().put(jobEntryCopy, (JobEntryTrans) cloneJei);
}
if (jobEntryCopy.isJob()) {
getActiveJobEntryJobs().put(jobEntryCopy, (JobEntryJob) cloneJei);
}
}
log.snap(Metrics.METRIC_JOBENTRY_START, cloneJei.toString());
newResult = cloneJei.execute(prevResult, nr);
log.snap(Metrics.METRIC_JOBENTRY_STOP, cloneJei.toString());
final long end = System.currentTimeMillis();
if (interactive) {
if (jobEntryCopy.isTransformation()) {
getActiveJobEntryTransformations().remove(jobEntryCopy);
}
if (jobEntryCopy.isJob()) {
getActiveJobEntryJobs().remove(jobEntryCopy);
}
}
if (cloneJei instanceof JobEntryTrans) {
String throughput = newResult.getReadWriteThroughput((int) ((end - start) / 1000));
if (throughput != null) {
log.logMinimal(throughput);
}
}
for (JobEntryListener jobEntryListener : jobEntryListeners) {
jobEntryListener.afterExecution(this, jobEntryCopy, cloneJei, newResult);
}
Thread.currentThread().setContextClassLoader(cl);
addErrors((int) newResult.getNrErrors());
// Also capture the logging text after the execution...
//
LoggingBuffer loggingBuffer = KettleLogStore.getAppender();
StringBuffer logTextBuffer = loggingBuffer.getBuffer(cloneJei.getLogChannel().getLogChannelId(), false);
newResult.setLogText(logTextBuffer.toString() + newResult.getLogText());
// Save this result as well...
//
JobEntryResult jerAfter = new JobEntryResult(newResult, cloneJei.getLogChannel().getLogChannelId(), BaseMessages.getString(PKG, "Job.Comment.JobFinished"), null, jobEntryCopy.getName(), jobEntryCopy.getNr(), environmentSubstitute(jobEntryCopy.getEntry().getFilename()));
jobTracker.addJobTracker(new JobTracker(jobMeta, jerAfter));
synchronized (jobEntryResults) {
jobEntryResults.add(jerAfter);
//
if (maxJobEntriesLogged > 0) {
while (jobEntryResults.size() > maxJobEntriesLogged) {
// Remove the oldest.
jobEntryResults.removeFirst();
}
}
}
}
extension = new JobExecutionExtension(this, prevResult, jobEntryCopy, extension.executeEntry);
ExtensionPointHandler.callExtensionPoint(log, KettleExtensionPoint.JobAfterJobEntryExecution.id, extension);
// Try all next job entries.
//
// Keep track of all the threads we fired in case of parallel execution...
// Keep track of the results of these executions too.
//
final List<Thread> threads = new ArrayList<Thread>();
// next 2 lists is being modified concurrently so must be synchronized for this case.
final Queue<Result> threadResults = new ConcurrentLinkedQueue<Result>();
final Queue<KettleException> threadExceptions = new ConcurrentLinkedQueue<KettleException>();
final List<JobEntryCopy> threadEntries = new ArrayList<JobEntryCopy>();
// Launch only those where the hop indicates true or false
//
int nrNext = jobMeta.findNrNextJobEntries(jobEntryCopy);
for (int i = 0; i < nrNext && !isStopped(); i++) {
// The next entry is...
final JobEntryCopy nextEntry = jobMeta.findNextJobEntry(jobEntryCopy, i);
// See if we need to execute this...
final JobHopMeta hi = jobMeta.findJobHop(jobEntryCopy, nextEntry);
// The next comment...
final String nextComment;
if (hi.isUnconditional()) {
nextComment = BaseMessages.getString(PKG, "Job.Comment.FollowedUnconditional");
} else {
if (newResult.getResult()) {
nextComment = BaseMessages.getString(PKG, "Job.Comment.FollowedSuccess");
} else {
nextComment = BaseMessages.getString(PKG, "Job.Comment.FollowedFailure");
}
}
//
if (hi.isUnconditional() || (jobEntryCopy.evaluates() && (!(hi.getEvaluation() ^ newResult.getResult())))) {
// Start this next step!
if (log.isBasic()) {
log.logBasic(BaseMessages.getString(PKG, "Job.Log.StartingEntry", nextEntry.getName()));
}
// When an evaluation is executed the errors e.g. should not be reset.
if (nextEntry.resetErrorsBeforeExecution()) {
newResult.setNrErrors(0);
}
//
if (jobEntryCopy.isLaunchingInParallel()) {
threadEntries.add(nextEntry);
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Result threadResult = execute(nr + 1, newResult, nextEntry, jobEntryCopy, nextComment);
threadResults.add(threadResult);
} catch (Throwable e) {
log.logError(Const.getStackTracker(e));
threadExceptions.add(new KettleException(BaseMessages.getString(PKG, "Job.Log.UnexpectedError", nextEntry.toString()), e));
Result threadResult = new Result();
threadResult.setResult(false);
threadResult.setNrErrors(1L);
threadResults.add(threadResult);
}
}
};
Thread thread = new Thread(runnable);
threads.add(thread);
thread.start();
if (log.isBasic()) {
log.logBasic(BaseMessages.getString(PKG, "Job.Log.LaunchedJobEntryInParallel", nextEntry.getName()));
}
} else {
try {
// Same as before: blocks until it's done
//
res = execute(nr + 1, newResult, nextEntry, jobEntryCopy, nextComment);
} catch (Throwable e) {
log.logError(Const.getStackTracker(e));
throw new KettleException(BaseMessages.getString(PKG, "Job.Log.UnexpectedError", nextEntry.toString()), e);
}
if (log.isBasic()) {
log.logBasic(BaseMessages.getString(PKG, "Job.Log.FinishedJobEntry", nextEntry.getName(), res.getResult() + ""));
}
}
}
}
//
if (jobEntryCopy.isLaunchingInParallel()) {
for (int i = 0; i < threads.size(); i++) {
Thread thread = threads.get(i);
JobEntryCopy nextEntry = threadEntries.get(i);
try {
thread.join();
} catch (InterruptedException e) {
log.logError(jobMeta.toString(), BaseMessages.getString(PKG, "Job.Log.UnexpectedErrorWhileWaitingForJobEntry", nextEntry.getName()));
threadExceptions.add(new KettleException(BaseMessages.getString(PKG, "Job.Log.UnexpectedErrorWhileWaitingForJobEntry", nextEntry.getName()), e));
}
}
// if(log.isBasic()) log.logBasic(BaseMessages.getString(PKG,
// "Job.Log.FinishedJobEntry",startpoint.getName(),res.getResult()+""));
}
// In this case, return the previous result.
if (res == null) {
res = prevResult;
}
//
if (threadExceptions.size() > 0) {
res.setResult(false);
res.setNrErrors(threadExceptions.size());
for (KettleException e : threadExceptions) {
log.logError(jobMeta.toString(), e.getMessage(), e);
}
//
throw threadExceptions.poll();
}
//
for (Result threadResult : threadResults) {
res.add(threadResult);
}
//
if (res.getNrErrors() > 0) {
res.setResult(false);
}
return res;
}
use of org.pentaho.di.job.entry.JobEntryInterface in project pentaho-kettle by pentaho.
the class JobMeta method checkJobEntries.
/**
* Check all job entries within the job. Each Job Entry has the opportunity to check their own settings.
*
* @param remarks List of CheckResult remarks inserted into by each JobEntry
* @param only_selected true if you only want to check the selected jobs
* @param monitor Progress monitor (not presently in use)
*/
public void checkJobEntries(List<CheckResultInterface> remarks, boolean only_selected, ProgressMonitorListener monitor, VariableSpace space, Repository repository, IMetaStore metaStore) {
// Empty remarks
remarks.clear();
if (monitor != null) {
monitor.beginTask(BaseMessages.getString(PKG, "JobMeta.Monitor.VerifyingThisJobEntryTask.Title"), jobcopies.size() + 2);
}
boolean stop_checking = false;
for (int i = 0; i < jobcopies.size() && !stop_checking; i++) {
// get the job entry copy
JobEntryCopy copy = jobcopies.get(i);
if ((!only_selected) || (only_selected && copy.isSelected())) {
JobEntryInterface entry = copy.getEntry();
if (entry != null) {
if (monitor != null) {
monitor.subTask(BaseMessages.getString(PKG, "JobMeta.Monitor.VerifyingJobEntry.Title", entry.getName()));
}
entry.check(remarks, this, space, repository, metaStore);
compatibleEntryCheck(entry, remarks);
if (monitor != null) {
// progress bar...
monitor.worked(1);
if (monitor.isCanceled()) {
stop_checking = true;
}
}
}
}
if (monitor != null) {
monitor.worked(1);
}
}
if (monitor != null) {
monitor.done();
}
}
use of org.pentaho.di.job.entry.JobEntryInterface in project pentaho-kettle by pentaho.
the class JobMeta method findJobEntry.
/**
* Find job entry.
*
* @param full_name_nr the full_name_nr
* @return the job entry copy
*/
public JobEntryCopy findJobEntry(String full_name_nr) {
int i;
for (i = 0; i < nrJobEntries(); i++) {
JobEntryCopy jec = getJobEntry(i);
JobEntryInterface je = jec.getEntry();
if (je.toString().equalsIgnoreCase(full_name_nr)) {
return jec;
}
}
return null;
}
use of org.pentaho.di.job.entry.JobEntryInterface in project pentaho-kettle by pentaho.
the class JobEntryLogTable method getLogRecord.
/**
* This method calculates all the values that are required
*
* @param id
* the id to use or -1 if no id is needed
* @param status
* the log status to use
* @param subject
* the object to log
* @param parent
* the parent to which the object belongs
*/
public RowMetaAndData getLogRecord(LogStatus status, Object subject, Object parent) {
if (subject == null || subject instanceof JobEntryCopy) {
JobEntryCopy jobEntryCopy = (JobEntryCopy) subject;
Job parentJob = (Job) parent;
RowMetaAndData row = new RowMetaAndData();
for (LogTableField field : fields) {
if (field.isEnabled()) {
Object value = null;
if (subject != null) {
JobEntryInterface jobEntry = jobEntryCopy.getEntry();
JobTracker jobTracker = parentJob.getJobTracker();
JobTracker entryTracker = jobTracker.findJobTracker(jobEntryCopy);
JobEntryResult jobEntryResult = null;
if (entryTracker != null) {
jobEntryResult = entryTracker.getJobEntryResult();
}
Result result = null;
if (jobEntryResult != null) {
result = jobEntryResult.getResult();
}
switch(ID.valueOf(field.getId())) {
case ID_BATCH:
value = new Long(parentJob.getBatchId());
break;
case CHANNEL_ID:
value = jobEntry.getLogChannel().getLogChannelId();
break;
case LOG_DATE:
value = new Date();
break;
case JOBNAME:
value = parentJob.getJobname();
break;
case JOBENTRYNAME:
value = jobEntry.getName();
break;
case LINES_READ:
value = new Long(result != null ? result.getNrLinesRead() : 0);
break;
case LINES_WRITTEN:
value = new Long(result != null ? result.getNrLinesWritten() : 0);
break;
case LINES_UPDATED:
value = new Long(result != null ? result.getNrLinesUpdated() : 0);
break;
case LINES_INPUT:
value = new Long(result != null ? result.getNrLinesInput() : 0);
break;
case LINES_OUTPUT:
value = new Long(result != null ? result.getNrLinesOutput() : 0);
break;
case LINES_REJECTED:
value = new Long(result != null ? result.getNrLinesRejected() : 0);
break;
case ERRORS:
value = new Long(result != null ? result.getNrErrors() : 0);
break;
case RESULT:
value = new Boolean(result != null ? result.getResult() : false);
break;
case NR_RESULT_FILES:
value = new Long(result != null && result.getResultFiles() != null ? result.getResultFiles().size() : 0);
break;
case NR_RESULT_ROWS:
value = new Long(result != null && result.getRows() != null ? result.getRows().size() : 0);
break;
case LOG_FIELD:
if (result != null) {
value = result.getLogText();
}
break;
case COPY_NR:
value = new Long(jobEntryCopy.getNr());
break;
default:
break;
}
}
row.addValue(field.getFieldName(), field.getDataType(), value);
row.getRowMeta().getValueMeta(row.size() - 1).setLength(field.getLength());
}
}
return row;
} else {
return null;
}
}
Aggregations