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

net.scattersphere.util.thread.JobManagerQueueExecutor Maven / Gradle / Ivy

The newest version!
/*
 * Scattersphere
 * Copyright 2014-2015, Scattersphere Project.
 *
 * 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 net.scattersphere.util.thread;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * This is an executor class that takes a job from a queue, and runs it in order of insertion in the job queue.
 *
 * 

This class constructs a {@link StrictBlockingQueue} that can only contain {@link JobExecutionContext} objects. * This function sits on the queue and waits for a job to be injected into the queue (via the {@link #queue} call. * *

As a job is injected and pulled from the queue, it is executed in the current {@link Thread}. After the job * completes, it indicates the completion status on the command line. If an exception state occurs, that is also * echoed on the command line. * *

Once the job completes, the entire process repeats itself until the underlying {@link net.scattersphere.server.Server} * is shutdown, or the executor thread is interrupted. * *

TODO: Check to see if Guava has any classes that make this easier to perform. * * Created by kenji on 11/27/14. */ public class JobManagerQueueExecutor extends Thread { private volatile JobExecutionContext status; private volatile JobManagerThread jmThread; private final AtomicBoolean isRunning; private final StrictBlockingQueue queuedJobs; private final Logger LOG = LoggerFactory.getLogger(JobManagerQueueExecutor.class); /** * Constructor. Takes in a name of the thread for debugging purposes. * * @param threadName The name of the current executor thread. */ public JobManagerQueueExecutor(String threadName) { super(threadName); status = null; jmThread = null; isRunning = new AtomicBoolean(false); int threadsAvailable = Runtime.getRuntime().availableProcessors(); this.queuedJobs = new StrictBlockingQueue<>(threadsAvailable * 16); this.queuedJobs.addAllowedClass(JobExecutionContext.class); } /** * Offers a new job to run. Once queued, the {@link #run} method will grab the job when available, and execute it. * * @param job The {@link JobExecutionContext} object to run. */ public void queue(JobExecutionContext job) { job.getJobContext().setJobResult(JobExecutionResult.QUEUED); queuedJobs.add(job); } /** * This is the runnable function that waits for new jobs to be offered to the queue, taking each one in FIFO order, * executing it, and logging the results. */ public void run() { isRunning.set(true); while(isRunning.get()) { try { status = queuedJobs.take(); jmThread = new JobManagerThread(status); LOG.info("[{}] new job received: thread={}", this.getName(), jmThread); jmThread.started(() -> { status.getJobContext().setJobResult(JobExecutionResult.RUNNING); status.getJobContext().setJobStart(); JobManagerCache.instance().addRunningJob(status); }) .completed(() -> { status.getJobContext().setJobResult(JobExecutionResult.COMPLETED); status.getJobContext().setJobEnd(); JobManagerCache.instance().removeRunningJob(status); JobManagerCache.instance().addCompletedJob(status); LOG.info("[{}] complete: elapsed={}ms", this.getName(), (status.getJobContext().getJobEnd() - status.getJobContext().getJobStart())); }) .exception(ex -> { LOG.info("[{}] exception state", this.getName(), ex); if (ex instanceof RuntimeException) { Exception cause = (Exception) ex.getCause(); if (cause instanceof InterruptedException) { status.getJobContext().setJobResult(JobExecutionResult.STOPPED, cause); } else { status.getJobContext().setJobResult(JobExecutionResult.FAILED, ex); } } else { status.getJobContext().setJobResult(JobExecutionResult.FAILED, ex); } status.getJobContext().setJobEnd(); JobManagerCache.instance().removeRunningJob(status); JobManagerCache.instance().addFailedJob(status); }) .start(); LOG.info("[{}] joining thread, waiting to complete.", this.getName()); jmThread.join(); LOG.info("[{}] join of thread complete, thread execution done: {}", this.getName(), status.getJobContext()); status = null; } catch (InterruptedException e) { LOG.info("Job Manager Queue Executor thread interrupted. Exiting."); return; } } } /** * This function stops a job by ID. * * @param jobId {@code String} containing the ID of the job to stop. * @param reason The reason for stopping the job. * @return {@code true} if the job was stopped, {@code false} otherwise. */ public boolean stop(String jobId, String reason) { if (status != null && status.getJobContext().getJobId().equals(jobId)) { status.getJobContext().setJobStopReason(reason); jmThread.interrupt(); return true; } AtomicInteger removedJobsCount = new AtomicInteger(0); // TODO // Improve this lambda to include a find/insert (findAll) queuedJobs.stream() .forEach(job -> { if (job.getJobContext().getJobId().equals(jobId)) { job.getJobContext().setJobStopReason(reason); removedJobsCount.incrementAndGet(); queuedJobs.remove(job); } }); return removedJobsCount.get() > 0; } /** * Indicates whether or not a job by ID is currently queued to be run. * * @param jobId The Job ID to search for. * @return {@code true} if the job is queued, {@code false} otherwise. */ public boolean isQueued(String jobId) { AtomicInteger jobsCount = new AtomicInteger(0); // TODO // Improve this lambda to do a find/insert (findAll) queuedJobs.stream() .forEach(job -> { if (job.getJobContext().getJobId().equals(jobId)) { jobsCount.incrementAndGet(); } }); return jobsCount.get() > 0; } /** * Returns a list of queued jobs for this executor. * * @return {@link List} of {@link net.scattersphere.util.thread.JobExecutionContext} objects. */ public List getQueuedJobs() { List returnList = new ArrayList<>(); returnList.addAll(queuedJobs); return returnList; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy