Search in sources :

Example 6 with StepListener

use of org.pentaho.di.trans.step.StepListener in project pentaho-kettle by pentaho.

the class Trans method startThreads.

/**
 * Starts the threads prepared by prepareThreads(). Before you start the threads, you can add RowListeners to them.
 *
 * @throws KettleException if there is a communication error with a remote output socket.
 */
public void startThreads() throws KettleException {
    // Now prepare to start all the threads...
    // 
    nrOfFinishedSteps = 0;
    nrOfActiveSteps = 0;
    ExtensionPointHandler.callExtensionPoint(log, KettleExtensionPoint.TransformationStartThreads.id, this);
    fireTransStartedListeners();
    for (int i = 0; i < steps.size(); i++) {
        final StepMetaDataCombi sid = steps.get(i);
        sid.step.markStart();
        sid.step.initBeforeStart();
        // also attach a Step Listener to detect when we're done...
        // 
        StepListener stepListener = new StepListener() {

            @Override
            public void stepActive(Trans trans, StepMeta stepMeta, StepInterface step) {
                nrOfActiveSteps++;
                if (nrOfActiveSteps == 1) {
                    // PDI-5229 sync added
                    synchronized (transListeners) {
                        for (TransListener listener : transListeners) {
                            listener.transActive(Trans.this);
                        }
                    }
                }
            }

            @Override
            public void stepFinished(Trans trans, StepMeta stepMeta, StepInterface step) {
                synchronized (Trans.this) {
                    nrOfFinishedSteps++;
                    if (nrOfFinishedSteps >= steps.size()) {
                        // Set the finished flag
                        // 
                        setFinished(true);
                        // Grab the performance statistics one last time (if enabled)
                        // 
                        addStepPerformanceSnapShot();
                        try {
                            fireTransFinishedListeners();
                        } catch (Exception e) {
                            step.setErrors(step.getErrors() + 1L);
                            log.logError(getName() + " : " + BaseMessages.getString(PKG, "Trans.Log.UnexpectedErrorAtTransformationEnd"), e);
                        }
                    }
                    // 
                    if (step.getErrors() > 0) {
                        log.logMinimal(BaseMessages.getString(PKG, "Trans.Log.TransformationDetectedErrors"));
                        log.logMinimal(BaseMessages.getString(PKG, "Trans.Log.TransformationIsKillingTheOtherSteps"));
                        killAllNoWait();
                    }
                }
            }
        };
        // 
        if (sid.step instanceof BaseStep) {
            ((BaseStep) sid.step).getStepListeners().add(0, stepListener);
        } else {
            sid.step.addStepListener(stepListener);
        }
    }
    if (transMeta.isCapturingStepPerformanceSnapShots()) {
        stepPerformanceSnapshotSeqNr = new AtomicInteger(0);
        stepPerformanceSnapShots = new ConcurrentHashMap<>();
        // Calculate the maximum number of snapshots to be kept in memory
        // 
        String limitString = environmentSubstitute(transMeta.getStepPerformanceCapturingSizeLimit());
        if (Utils.isEmpty(limitString)) {
            limitString = EnvUtil.getSystemProperty(Const.KETTLE_STEP_PERFORMANCE_SNAPSHOT_LIMIT);
        }
        stepPerformanceSnapshotSizeLimit = Const.toInt(limitString, 0);
        // Set a timer to collect the performance data from the running threads...
        // 
        stepPerformanceSnapShotTimer = new Timer("stepPerformanceSnapShot Timer: " + transMeta.getName());
        TimerTask timerTask = new TimerTask() {

            @Override
            public void run() {
                if (!isFinished()) {
                    addStepPerformanceSnapShot();
                }
            }
        };
        stepPerformanceSnapShotTimer.schedule(timerTask, 100, transMeta.getStepPerformanceCapturingDelay());
    }
    // Now start a thread to monitor the running transformation...
    // 
    setFinished(false);
    setPaused(false);
    setStopped(false);
    transFinishedBlockingQueue = new ArrayBlockingQueue<>(TRANS_FINISHED_BLOCKING_QUEUE_SIZE);
    TransListener transListener = new TransAdapter() {

        @Override
        public void transFinished(Trans trans) {
            try {
                shutdownHeartbeat(trans != null ? trans.heartbeat : null);
                if (trans != null && transMeta.getParent() == null && trans.parentJob == null && trans.parentTrans == null) {
                    if (log.isDetailed() && transMeta.getMetaFileCache() != null) {
                        transMeta.getMetaFileCache().logCacheSummary(log);
                    }
                    transMeta.setMetaFileCache(null);
                }
                ExtensionPointHandler.callExtensionPoint(log, KettleExtensionPoint.TransformationFinish.id, trans);
            } catch (KettleException e) {
                throw new RuntimeException("Error calling extension point at end of transformation", e);
            }
            // 
            if (transMeta.isCapturingStepPerformanceSnapShots() && stepPerformanceSnapShotTimer != null) {
                stepPerformanceSnapShotTimer.cancel();
            }
            transMeta.disposeEmbeddedMetastoreProvider();
            setFinished(true);
            // no longer running
            setRunning(false);
            log.snap(Metrics.METRIC_TRANSFORMATION_EXECUTION_STOP);
            // If the user ran with metrics gathering enabled and a metrics logging table is configured, add another
            // listener...
            // 
            MetricsLogTable metricsLogTable = transMeta.getMetricsLogTable();
            if (metricsLogTable.isDefined()) {
                try {
                    writeMetricsInformation();
                } catch (Exception e) {
                    log.logError("Error writing metrics information", e);
                    errors.incrementAndGet();
                }
            }
            // 
            if (transMeta.isUsingUniqueConnections()) {
                trans.closeUniqueDatabaseConnections(getResult());
            }
            // release unused vfs connections
            KettleVFS.freeUnusedResources();
        }
    };
    // This should always be done first so that the other listeners achieve a clean state to start from (setFinished and
    // so on)
    // 
    transListeners.add(0, transListener);
    setRunning(true);
    switch(transMeta.getTransformationType()) {
        case Normal:
            // 
            for (int i = 0; i < steps.size(); i++) {
                final StepMetaDataCombi combi = steps.get(i);
                RunThread runThread = new RunThread(combi);
                Thread thread = new Thread(runThread);
                thread.setName(getName() + " - " + combi.stepname);
                ExtensionPointHandler.callExtensionPoint(log, KettleExtensionPoint.StepBeforeStart.id, combi);
                // Call an extension point at the end of the step
                // 
                combi.step.addStepListener(new StepAdapter() {

                    @Override
                    public void stepFinished(Trans trans, StepMeta stepMeta, StepInterface step) {
                        try {
                            ExtensionPointHandler.callExtensionPoint(log, KettleExtensionPoint.StepFinished.id, combi);
                        } catch (KettleException e) {
                            throw new RuntimeException("Unexpected error in calling extension point upon step finish", e);
                        }
                    }
                });
                thread.start();
            }
            break;
        case SerialSingleThreaded:
            new Thread(new Runnable() {

                @Override
                public void run() {
                    try {
                        // 
                        for (StepMetaDataCombi combi : steps) {
                            combi.step.setUsingThreadPriorityManagment(false);
                        }
                        // 
                        // This is a single threaded version...
                        // 
                        // Sort the steps from start to finish...
                        // 
                        Collections.sort(steps, new Comparator<StepMetaDataCombi>() {

                            @Override
                            public int compare(StepMetaDataCombi c1, StepMetaDataCombi c2) {
                                boolean c1BeforeC2 = transMeta.findPrevious(c2.stepMeta, c1.stepMeta);
                                if (c1BeforeC2) {
                                    return -1;
                                } else {
                                    return 1;
                                }
                            }
                        });
                        boolean[] stepDone = new boolean[steps.size()];
                        int nrDone = 0;
                        while (nrDone < steps.size() && !isStopped()) {
                            for (int i = 0; i < steps.size() && !isStopped(); i++) {
                                StepMetaDataCombi combi = steps.get(i);
                                if (!stepDone[i]) {
                                    boolean cont = combi.step.processRow(combi.meta, combi.data);
                                    if (!cont) {
                                        stepDone[i] = true;
                                        nrDone++;
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        errors.addAndGet(1);
                        log.logError("Error executing single threaded", e);
                    } finally {
                        for (StepMetaDataCombi combi : steps) {
                            combi.step.dispose(combi.meta, combi.data);
                            combi.step.markStop();
                        }
                    }
                }
            }).start();
            break;
        case SingleThreaded:
            // 
            break;
        default:
            break;
    }
    ExtensionPointHandler.callExtensionPoint(log, KettleExtensionPoint.TransformationStart.id, this);
    heartbeat = startHeartbeat(getHeartbeatIntervalInSeconds());
    if (steps.isEmpty()) {
        fireTransFinishedListeners();
    }
    if (log.isDetailed()) {
        log.logDetailed(BaseMessages.getString(PKG, "Trans.Log.TransformationHasAllocated", String.valueOf(steps.size()), String.valueOf(rowsets.size())));
    }
}
Also used : KettleException(org.pentaho.di.core.exception.KettleException) MetricsLogTable(org.pentaho.di.core.logging.MetricsLogTable) ValueMetaString(org.pentaho.di.core.row.value.ValueMetaString) StepInterface(org.pentaho.di.trans.step.StepInterface) TimerTask(java.util.TimerTask) StepAdapter(org.pentaho.di.trans.step.StepAdapter) StepMetaDataCombi(org.pentaho.di.trans.step.StepMetaDataCombi) RunThread(org.pentaho.di.trans.step.RunThread) BaseStep(org.pentaho.di.trans.step.BaseStep) StepMeta(org.pentaho.di.trans.step.StepMeta) KettleExtensionPoint(org.pentaho.di.core.extension.KettleExtensionPoint) UnknownParamException(org.pentaho.di.core.parameters.UnknownParamException) KettleValueException(org.pentaho.di.core.exception.KettleValueException) KettleTransException(org.pentaho.di.core.exception.KettleTransException) DuplicateParamException(org.pentaho.di.core.parameters.DuplicateParamException) KettleFileException(org.pentaho.di.core.exception.KettleFileException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) KettleException(org.pentaho.di.core.exception.KettleException) KettleDatabaseException(org.pentaho.di.core.exception.KettleDatabaseException) RunThread(org.pentaho.di.trans.step.RunThread) StepInitThread(org.pentaho.di.trans.step.StepInitThread) Timer(java.util.Timer) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) StepListener(org.pentaho.di.trans.step.StepListener)

Aggregations

StepListener (org.pentaho.di.trans.step.StepListener)6 Test (org.junit.Test)5 RowListener (org.pentaho.di.trans.step.RowListener)4 StepMeta (org.pentaho.di.trans.step.StepMeta)4 ValueMetaString (org.pentaho.di.core.row.value.ValueMetaString)3 DataServiceExecutor (org.pentaho.di.trans.dataservice.DataServiceExecutor)3 StepInterface (org.pentaho.di.trans.step.StepInterface)3 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 DataOutputStream (java.io.DataOutputStream)2 InOrder (org.mockito.InOrder)2 Matchers.anyString (org.mockito.Matchers.anyString)2 RowMetaAndData (org.pentaho.di.core.RowMetaAndData)2 RowMetaInterface (org.pentaho.di.core.row.RowMetaInterface)2 SQL (org.pentaho.di.core.sql.SQL)2 RowProducer (org.pentaho.di.trans.RowProducer)2 TransListener (org.pentaho.di.trans.TransListener)2 PushDownOptimizationMeta (org.pentaho.di.trans.dataservice.optimization.PushDownOptimizationMeta)2 IMetaStore (org.pentaho.metastore.api.IMetaStore)2 FluentIterable (com.google.common.collect.FluentIterable)1 ListenableFuture (com.google.common.util.concurrent.ListenableFuture)1