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

be.bagofwords.jobs.JobRunner Maven / Gradle / Ivy

package be.bagofwords.jobs;


import be.bagofwords.application.CloseableComponent;
import be.bagofwords.application.annotations.BowComponent;
import be.bagofwords.counts.WindowOfCounts;
import be.bagofwords.iterator.CloseableIterator;
import be.bagofwords.iterator.DataIterable;
import be.bagofwords.ui.UI;
import be.bagofwords.util.OccasionalAction;
import be.bagofwords.util.SafeThread;
import be.bagofwords.util.Utils;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

@BowComponent
public class JobRunner implements CloseableComponent {

    private final List runningJobs;
    private boolean terminateRequested = false;

    public JobRunner() {
        runningJobs = new ArrayList<>();
    }

    public  void runPartitionedJobs(final int numOfPartitions, int numOfThreads, final String name, DataIterable iterable, final PartitionableJob job) {
        runPartitionedJobs(true, numOfPartitions, numOfThreads, name, iterable, job);
    }

    public  void runPartitionedJobs(final boolean printProgress, int numOfPartitions, int numOfThreads, final String name, DataIterable iterable, final PartitionableJob job) {
        final JobStatus jobStatus = new JobStatus(name, iterable.apprSize(), numOfPartitions);
        synchronized (runningJobs) {
            runningJobs.add(jobStatus);
        }
        OccasionalAction action = new OccasionalAction(10000) {
            @Override
            protected void doAction(T curr) {
                if (printProgress) {
                    String outS = createOutputString(jobStatus);
                    UI.write(outS);
                }
            }
        };
        for (; jobStatus.getCurrentPartition() < numOfPartitions; jobStatus.setCurrentPartition(jobStatus.getCurrentPartition() + 1)) {
            CloseableIterator iterator = iterable.iterator();
            ExecuteActionRunnable[] threads = new ExecuteActionRunnable[numOfThreads];
            for (int i = 0; i < threads.length; i++) {
                threads[i] = new ExecuteActionRunnable<>(jobStatus, name + "_" + i, job, iterator, action);
                threads[i].start();
            }
            boolean allFinished = false;
            Throwable receivedException = null;
            while (!allFinished) {
                Utils.threadSleep(200);
                allFinished = true;
                if (terminateRequested) {
                    for (ExecuteActionRunnable thread : threads) {
                        thread.terminateAndWaitForFinish();
                        receivedException = new RuntimeException("Termination of application was requested.");
                    }
                } else {
                    for (ExecuteActionRunnable thread : threads) {
                        if (thread.getExp() != null) {
                            //Terminate all other threads
                            for (ExecuteActionRunnable runner : threads) {
                                runner.terminateAndWaitForFinish();
                            }
                            receivedException = thread.getExp();
                        }
                        allFinished &= thread.isFinished();
                    }
                }
            }
            iterator.close();
            if (jobStatus.getCurrentPartition() == 0) {
                jobStatus.setNumberOfObjects(jobStatus.getWindowedCounts().getTotalCounts()); //Set estimated size of iterator to actual size
            }
            if (receivedException != null) {
                throw new RuntimeException(receivedException);
            }
        }
        synchronized (runningJobs) {
            runningJobs.remove(jobStatus);
        }
    }

    private  String createOutputString(JobStatus jobStatus) {
        long did = jobStatus.getWindowedCounts().getTotalCounts();
        long todo = jobStatus.getNumberOfObjects() * jobStatus.getNumberOfPartitions() - did;
        long didInIteration = did - jobStatus.getNumberOfObjects() * jobStatus.getCurrentPartition();
        String outS = "[Progress " + jobStatus.getName() + "]";
        if (jobStatus.getNumberOfPartitions() > 1) {
            outS += " " + jobStatus.getCurrentPartition() + "/" + jobStatus.getNumberOfPartitions();
        }
        outS += " did " + didInIteration + " of " + jobStatus.getNumberOfObjects();
        String endString;
        if (todo > 0) {
            endString = " end is " + new Date(System.currentTimeMillis() + jobStatus.getWindowedCounts().getNeededTime(todo));
        } else {
            endString = " should finish any second now";
        }
        return outS + endString;
    }

    public  void runJob(int numOfThreads, final String name, DataIterable iterable, final Job job) {
        runJob(true, numOfThreads, name, iterable, job);
    }

    public  void runJob(final boolean printProgress, int numOfThreads, final String name, DataIterable iterable, final Job job) {
        runPartitionedJobs(printProgress, 1, numOfThreads, name, iterable, (partition, target) -> job.doAction(target));
    }

    public  void runJob(final String name, DataIterable iterable, final Job job) {
        runJob(true, 1, name, iterable, job);
    }

    public String createHtmlStatus() {
        StringBuilder sb = new StringBuilder();
        sb.append("

Job Runner

"); synchronized (runningJobs) { if (runningJobs.isEmpty()) { sb.append("No jobs currently running."); } else { sb.append("Currently running " + runningJobs.size() + " jobs
"); for (JobStatus runningJob : runningJobs) { sb.append("
" + createOutputString(runningJob) + "
"); } } } return sb.toString(); } @Override public void terminate() { terminateRequested = true; } private static class ExecuteActionRunnable extends SafeThread { private final PartitionableJob job; private final Iterator iterator; private Throwable exp; private final OccasionalAction action; private final JobStatus jobStatus; public ExecuteActionRunnable(JobStatus jobStatus, String nameOfThread, PartitionableJob job, Iterator iterator, OccasionalAction action) { super(nameOfThread, false); this.job = job; this.iterator = iterator; this.jobStatus = jobStatus; this.action = action; } public Throwable getExp() { return exp; } @Override public void runInt() { try { boolean finished = false; while (!finished && !isTerminateRequested()) { T next = null; synchronized (iterator) { if (iterator.hasNext()) { next = iterator.next(); } else { finished = true; } } if (next != null) { job.doAction(jobStatus.getCurrentPartition(), next); jobStatus.getWindowedCounts().addCount(); action.doOccasionalAction(next); } } } catch (Throwable exp) { this.exp = exp; } } } private class JobStatus { private final String name; private final WindowOfCounts windowedCounts; private final int numberOfPartitions; private long numberOfObjects; private int currentPartition; private JobStatus(String name, long numberOfObjects, int numberOfPartitions) { this.name = name; this.numberOfObjects = numberOfObjects; this.numberOfPartitions = numberOfPartitions; this.windowedCounts = new WindowOfCounts(60000); this.currentPartition = 0; } public long getNumberOfObjects() { return numberOfObjects; } public void setNumberOfObjects(long numberOfObjects) { this.numberOfObjects = numberOfObjects; } public WindowOfCounts getWindowedCounts() { return windowedCounts; } public int getCurrentPartition() { return currentPartition; } public void setCurrentPartition(int currentPartition) { this.currentPartition = currentPartition; } public String getName() { return name; } public int getNumberOfPartitions() { return numberOfPartitions; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy