org.pentaho.di.trans.dataservice.optimization.cache.ServiceObserver.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.di.trans.dataservice.optimization.cache.ServiceObserver.java

Source

/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2017 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.trans.dataservice.optimization.cache;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.AbstractFuture;
import com.google.common.util.concurrent.ListenableFuture;
import org.pentaho.di.core.exception.KettleValueException;
import org.pentaho.di.trans.dataservice.DataServiceExecutor;
import org.pentaho.di.core.RowMetaAndData;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.step.RowAdapter;
import org.pentaho.di.trans.step.StepAdapter;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static com.google.common.base.Predicates.instanceOf;

/**
 * @author nhudak
 */
public class ServiceObserver extends AbstractFuture<CachedService> implements Runnable {
    private final DataServiceExecutor executor;

    List<RowMetaAndData> rowMetaAndData = Lists.newArrayList();
    boolean isRunning = true;
    CountDownLatch latch = new CountDownLatch(1);

    public ServiceObserver(DataServiceExecutor executor) {
        this.executor = executor;
    }

    public Iterator<RowMetaAndData> rows() {
        return new Iterator<RowMetaAndData>() {
            int index = 0;

            @Override
            public boolean hasNext() {
                if (rowMetaAndData.size() > index) {
                    return true;
                }
                if (isRunning) {
                    latch = new CountDownLatch(1);
                    try {
                        latch.await(1, TimeUnit.SECONDS);
                        return rowMetaAndData.size() > index;
                    } catch (InterruptedException e) {
                        return rowMetaAndData.size() > index;
                    }
                } else {
                    return rowMetaAndData.size() > index;
                }
            }

            @Override
            public RowMetaAndData next() {
                return rowMetaAndData.get(index++);
            }
        };
    }

    public ListenableFuture<CachedService> install() {
        List<Runnable> serviceReady = executor.getListenerMap().get(DataServiceExecutor.ExecutionPoint.READY);
        if (Iterables.any(serviceReady, instanceOf(ServiceObserver.class))) {
            setException(new IllegalStateException("More than one cache is configured for this data service."));
        } else {
            serviceReady.add(this);
        }
        return this;
    }

    @Override
    public void run() {
        StepInterface serviceStep = executor.getServiceTrans().findRunThread(executor.getService().getStepname());
        serviceStep.addRowListener(new RowAdapter() {
            @Override
            public synchronized void rowWrittenEvent(RowMetaInterface rowMeta, Object[] row) {
                Object[] clonedRow;
                try {
                    clonedRow = rowMeta.cloneRow(row);
                } catch (KettleValueException e) {
                    setException(e);
                    return;
                }
                rowMetaAndData.add(new RowMetaAndData(rowMeta, clonedRow));
                latch.countDown();
            }
        });
        serviceStep.addStepListener(new StepAdapter() {
            @Override
            public void stepFinished(Trans trans, StepMeta stepMeta, StepInterface step) {
                isRunning = false;
                if (executor.getGenTrans().getErrors() > 0) {
                    setException(new KettleException(
                            "Dynamic transformation finished with errors, could not cache results"));
                } else if (step.isStopped()) {
                    set(CachedService.partial(rowMetaAndData, executor));
                } else {
                    set(CachedService.complete(rowMetaAndData));
                }
            }
        });
    }
}