com.yahoo.yqlplus.engine.internal.generate.ProgramInvocation.java Source code

Java tutorial

Introduction

Here is the source code for com.yahoo.yqlplus.engine.internal.generate.ProgramInvocation.java

Source

/*
 * Copyright (c) 2016 Yahoo Inc.
 * Licensed under the terms of the Apache version 2.0 license.
 * See LICENSE file for terms.
 */

package com.yahoo.yqlplus.engine.internal.generate;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.yahoo.yqlplus.api.types.YQLType;
import com.yahoo.yqlplus.api.types.YQLTypeException;
import com.yahoo.yqlplus.engine.TaskContext;
import com.yahoo.yqlplus.engine.api.InvocationResultHandler;
import com.yahoo.yqlplus.engine.api.NativeEncoding;
import com.yahoo.yqlplus.engine.api.NativeInvocationResultHandler;
import com.yahoo.yqlplus.engine.internal.bytecode.types.gambit.GambitRuntime;
import com.yahoo.yqlplus.engine.internal.bytecode.types.gambit.YQLRuntimeException;
import com.yahoo.yqlplus.engine.internal.java.runtime.TimeoutHandler;
import com.yahoo.yqlplus.engine.internal.scope.ScopedTracingExecutor;

import javax.inject.Named;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;

public abstract class ProgramInvocation {
    private volatile InvocationResultHandler resultHandler;

    @Inject
    public Injector injector;

    @Inject
    @Named("programExecutor")
    public ListeningExecutorService tasks;

    @Inject
    @Named("timeout")
    public ScheduledExecutorService timers;

    @Inject
    @Named("rootContext")
    public TaskContext rootContext;

    @Inject
    public TimeoutHandler timeouts;

    public void execute(Runnable runnable) {
        tasks.submit(wrap(runnable));
    }

    private Runnable wrap(final Runnable run) {
        return new Runnable() {
            @Override
            public void run() {
                try {
                    run.run();
                } catch (Exception e) {
                    fail(e);
                } catch (Error e) {
                    fail(e);
                    throw e;
                }
            }
        };
    }

    public void executeAll(Runnable one) {
        wrap(one).run();
    }

    public void executeAll(Runnable... runnables) {
        for (int i = 0; i < runnables.length - 1; ++i) {
            execute(runnables[i]);
        }
        wrap(runnables[runnables.length - 1]).run();
    }

    protected void missingArgument(String name, YQLType expectedType) {
        throw new IllegalArgumentException(
                "Missing required program argument '" + name + "' (type '" + expectedType + "')");
    }

    public <ROW> void addAll(List<ROW> rows, List<ROW> inputs) {
        if (inputs == null) {
            return;
        }
        for (ROW row : inputs) {
            if (row != null) {
                rows.add(row);
            }
        }
    }

    public <ROW> void addAll(List<ROW> rows, Iterable<ROW> inputs) {
        if (inputs == null) {
            return;
        }
        for (ROW row : inputs) {
            if (row != null) {
                rows.add(row);
            }
        }
    }

    public <ROW> void addAll(List<ROW> rows, Collection<ROW> inputs) {
        if (inputs == null) {
            return;
        }
        for (ROW row : inputs) {
            if (row != null) {
                rows.add(row);
            }
        }
    }

    public List<Object> singleton(Object input) {
        if (input != null) {
            return ImmutableList.of(input);
        } else {
            return ImmutableList.of();
        }
    }

    public <ROW> List<ROW> sort(List<ROW> rows, Comparator<ROW> comparator) {
        Collections.sort(rows, comparator);
        return rows;
    }

    public void invoke(InvocationResultHandler resultHandler, Map<String, Object> arguments) {
        this.resultHandler = resultHandler;
        try {
            readArguments(arguments);
            run();
        } catch (Exception e) {
            fail(e);
        } catch (Error e) {
            fail(e);
            throw e;
        }
    }

    public void invoke(NativeEncoding encoding, NativeInvocationResultHandler resultHandler,
            Map<String, Object> arguments) {
        invoke(new NativeEncodingAdapter(encoding, resultHandler, getNativeSerializer()), arguments);
    }

    protected abstract void readArguments(Map<String, Object> arguments);

    public final void succeed(String name, Object out) {
        resultHandler.succeed(name, out);
    }

    public final void fail(String name, Throwable failure) {
        resultHandler.fail(name, extractCause(failure));
    }

    private Throwable extractCause(Throwable failure) {
        while ((failure instanceof YQLRuntimeException || failure instanceof ExecutionException)
                && failure.getCause() != null) {
            failure = failure.getCause();
        }
        return failure;
    }

    public final void end() {
        resultHandler.end();
    }

    public final void fail(Throwable t) {
        resultHandler.fail(extractCause(t));
    }

    public final void notComparable(Object target, int line, int offset) {
        throw new YQLTypeException("L" + line + ":" + offset + ": unable to compare " + target);
    }

    protected abstract void run() throws Exception;

    protected abstract NativeSerialization getNativeSerializer();

    public final Injector getInjector() {
        return injector;
    }

    public final GambitRuntime getRuntime(TaskContext context) {
        final ListeningExecutorService tasks = ((ScopedTracingExecutor) this.tasks).createSubExecutor(context);
        return new GambitRuntime() {
            @Override
            public ListenableFuture<List<Object>> scatter(List<Callable<Object>> targets) {
                List<ListenableFuture<Object>> resultList = Lists.newArrayListWithExpectedSize(targets.size());
                for (Callable<Object> out : targets) {
                    resultList.add(fork(out));
                }
                return Futures.allAsList(resultList);
            }

            @Override
            public ListenableFuture<List<Object>> scatterAsync(List<Callable<ListenableFuture<Object>>> targets) {
                List<ListenableFuture<Object>> resultList = Lists.newArrayListWithExpectedSize(targets.size());
                for (Callable<ListenableFuture<Object>> out : targets) {
                    resultList.add(forkAsync(out));
                }
                return Futures.allAsList(resultList);
            }

            @Override
            public ListenableFuture<Object> fork(Callable<Object> target) {
                return tasks.submit(target);
            }

            @Override
            public ListenableFuture<Object> forkAsync(Callable<ListenableFuture<Object>> target) {
                return Futures.dereference(tasks.submit(target));
            }
        };
    }
}