All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.embulk.spi.FileOutputRunner Maven / Gradle / Ivy

package org.embulk.spi;

import java.util.ArrayList;
import java.util.List;
import org.embulk.config.Config;
import org.embulk.config.ConfigDefault;
import org.embulk.config.ConfigDiff;
import org.embulk.config.ConfigSource;
import org.embulk.config.Task;
import org.embulk.config.TaskReport;
import org.embulk.config.TaskSource;
import org.embulk.plugin.PluginType;
import org.embulk.spi.util.EncodersInternal;

public class FileOutputRunner implements OutputPlugin {
    private final FileOutputPlugin fileOutputPlugin;

    public FileOutputRunner(FileOutputPlugin fileOutputPlugin) {
        this.fileOutputPlugin = fileOutputPlugin;
    }

    private interface RunnerTask extends Task {
        @Config("type")
        public PluginType getType();

        @Config("encoders")
        @ConfigDefault("[]")
        public List getEncoderConfigs();

        @Config("formatter")
        public ConfigSource getFormatterConfig();

        public void setFileOutputTaskSource(TaskSource v);

        public TaskSource getFileOutputTaskSource();

        public void setEncoderTaskSources(List v);

        public List getEncoderTaskSources();

        public void setFormatterTaskSource(TaskSource v);

        public TaskSource getFormatterTaskSource();
    }

    protected List newEncoderPlugins(RunnerTask task) {
        return EncodersInternal.newEncoderPlugins(ExecInternal.sessionInternal(), task.getEncoderConfigs());
    }

    protected FormatterPlugin newFormatterPlugin(RunnerTask task) {
        return ExecInternal.newPlugin(FormatterPlugin.class, task.getFormatterConfig().get(PluginType.class, "type"));
    }

    @Override
    public ConfigDiff transaction(ConfigSource config,
            final Schema schema, final int taskCount,
            final OutputPlugin.Control control) {
        final RunnerTask task = loadRunnerTask(config);
        return fileOutputPlugin.transaction(config, taskCount, new RunnerControl(schema, task, control));
    }

    public ConfigDiff resume(TaskSource taskSource,
            Schema schema, int taskCount,
            final OutputPlugin.Control control) {
        final RunnerTask task = loadRunnerTaskFromTaskSource(taskSource);
        return fileOutputPlugin.resume(task.getFileOutputTaskSource(), taskCount, new RunnerControl(schema, task, control));
    }

    private class RunnerControl implements FileOutputPlugin.Control {
        private final Schema schema;
        private final RunnerTask task;
        private final List encoderPlugins;
        private final FormatterPlugin formatterPlugin;
        private final OutputPlugin.Control nextControl;

        public RunnerControl(Schema schema, RunnerTask task, OutputPlugin.Control nextControl) {
            this.schema = schema;
            this.task = task;
            // create plugins earlier than run() to throw exceptions early
            this.encoderPlugins = newEncoderPlugins(task);
            this.formatterPlugin = newFormatterPlugin(task);
            this.nextControl = nextControl;
        }

        @Override
        public List run(final TaskSource fileOutputTaskSource) {
            final List taskReports = new ArrayList();
            EncodersInternal.transaction(encoderPlugins, task.getEncoderConfigs(), new EncodersInternal.Control() {
                    public void run(final List encoderTaskSources) {
                        formatterPlugin.transaction(task.getFormatterConfig(), schema, new FormatterPlugin.Control() {
                                public void run(final TaskSource formatterTaskSource) {
                                    task.setFileOutputTaskSource(fileOutputTaskSource);
                                    task.setEncoderTaskSources(encoderTaskSources);
                                    task.setFormatterTaskSource(formatterTaskSource);
                                    taskReports.addAll(nextControl.run(task.dump()));
                                }
                            });
                    }
                });
            return taskReports;
        }
    }

    public void cleanup(TaskSource taskSource,
            Schema schema, int taskCount,
            List successtaskReports) {
        fileOutputPlugin.cleanup(taskSource, taskCount, successtaskReports);
    }

    @Override
    public TransactionalPageOutput open(TaskSource taskSource, Schema schema, int taskIndex) {
        final RunnerTask task = loadRunnerTaskFromTaskSource(taskSource);
        List encoderPlugins = newEncoderPlugins(task);
        FormatterPlugin formatterPlugin = newFormatterPlugin(task);

        try (AbortTransactionResource aborter = new AbortTransactionResource()) {
            try (CloseResource closer = new CloseResource()) {
                final TransactionalFileOutput finalOutput = fileOutputPlugin.open(task.getFileOutputTaskSource(), taskIndex);
                aborter.abortThis(finalOutput);
                closer.closeThis(finalOutput);

                FileOutput encodedOutput = EncodersInternal.open(encoderPlugins, task.getEncoderTaskSources(), finalOutput);
                closer.closeThis(encodedOutput);

                PageOutput output = formatterPlugin.open(task.getFormatterTaskSource(), schema, encodedOutput);
                closer.closeThis(output);

                TransactionalPageOutput ret = new DelegateTransactionalPageOutput(finalOutput, output);
                aborter.dontAbort();
                closer.dontClose();  // ownership of output is transferred to caller (input plugin). the owner will close output.
                return ret;
            }
        }
    }

    private static class DelegateTransactionalPageOutput implements TransactionalPageOutput {
        private final Transactional tran;
        private final PageOutput output;

        public DelegateTransactionalPageOutput(Transactional tran, PageOutput output) {
            this.tran = tran;
            this.output = output;
        }

        @Override
        public void add(Page page) {
            output.add(page);
        }

        @Override
        public void finish() {
            output.finish();
        }

        @Override
        public void close() {
            output.close();
        }

        @Override
        public void abort() {
            tran.abort();
        }

        @Override
        public TaskReport commit() {
            // TODO check finished
            return tran.commit();
        }
    }

    @SuppressWarnings("deprecation") // https://github.com/embulk/embulk/issues/1301
    public static TaskSource getFileOutputTaskSource(TaskSource runnerTaskSource) {
        return runnerTaskSource.loadTask(RunnerTask.class).getFileOutputTaskSource();
    }

    @SuppressWarnings("deprecation") // https://github.com/embulk/embulk/issues/1301
    private static RunnerTask loadRunnerTask(final ConfigSource config) {
        return config.loadConfig(RunnerTask.class);
    }

    @SuppressWarnings("deprecation") // https://github.com/embulk/embulk/issues/1301
    private static RunnerTask loadRunnerTaskFromTaskSource(final TaskSource taskSource) {
        return taskSource.loadTask(RunnerTask.class);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy