com.amazonaws.services.cloudtrail.processinglibrary.factory.ThreadPoolFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.amazonaws.services.cloudtrail.processinglibrary.factory.ThreadPoolFactory.java

Source

/*******************************************************************************
 * Copyright 2010-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 com.amazonaws.services.cloudtrail.processinglibrary.factory;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.amazonaws.services.cloudtrail.processinglibrary.exceptions.ProcessingLibraryException;
import com.amazonaws.services.cloudtrail.processinglibrary.interfaces.ExceptionHandler;
import com.amazonaws.services.cloudtrail.processinglibrary.progress.ProgressState;
import com.amazonaws.services.cloudtrail.processinglibrary.progress.ProgressStatus;
import com.amazonaws.services.cloudtrail.processinglibrary.utils.LibraryUtils;

/**
 * This class creates thread pool for ThreadPoolFactory.
 */
public class ThreadPoolFactory {
    private static final Log logger = LogFactory.getLog(ThreadPoolFactory.class);

    /**
     * Number of current running thread to process CloudTrailSources
     */
    private int threadCount;

    /**
     * The exceptionHandler is used to handle uncaught exception.
     */
    private ExceptionHandler exceptionHandler;

    /**
     * A factory to create an instance of ExecutorService based on configuration
     *
     * @param threadCount number of threads
     * @param exceptionHandler
     */
    public ThreadPoolFactory(int threadCount, ExceptionHandler exceptionHandler) {
        this.threadCount = threadCount;
        this.exceptionHandler = exceptionHandler;
    }

    /**
     * Create an instance of ScheduledExecutorService. We only need single thread to poll messages
     * from the SQS queue.
     *
     * @return ScheduledExecutorService continuous poll messages from SQS queue.
     */
    public ScheduledExecutorService createScheduledThreadPool() {
        return Executors.newScheduledThreadPool(1);
    }

    /**
     * Create an instance of ExecutorService. ExecutorService is AWS CloudTrail Processing Library's main thread pool,
     * used to process each CloudTrailSource. The thread pool queue, size are configurable through
     * ProcessingConfiguration.
     *
     * @return ExecutorService that processes CloudTrailSource
     */
    public ExecutorService createMainThreadPool() {
        LibraryUtils.checkCondition(this.threadCount < 1, "Thread Count cannot be less than 1.");
        return this.createThreadPoolWithBoundedQueue(this.threadCount);

    }

    /**
     * Helper function to create an instance of ExecutorService with bounded queue size.
     *
     * When no more threads or queue slots are available because their bounds would be exceeded, the scheduled thread
     * pool will run the rejected task directly. Unless the executor has been shut down, in which case the task is
     * discarded. Note while scheduled thread poll is running rejected task, scheduled thread pool will not poll
     * more messages to process.
     *
     * @param threadCount number of threads
     * @return an instance of ExecutorService
     */
    private ExecutorService createThreadPoolWithBoundedQueue(int threadCount) {
        BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(threadCount);
        RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.CallerRunsPolicy();
        ExecutorService executorService = new ProcessingLibraryThreadPoolExecutor(threadCount, threadCount, 0,
                TimeUnit.MILLISECONDS, blockingQueue, rejectedExecutionHandler, this.exceptionHandler);
        return executorService;
    }

    /**
     * When unexpected behavior happened, for example runtimeException. ProcessingLibraryThreadPoolExecutor will handle
     * the exception by calling ExceptionHandler provided by end user.
     */
    public class ProcessingLibraryThreadPoolExecutor extends ThreadPoolExecutor {
        private ExceptionHandler exceptionHandler;

        public ProcessingLibraryThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
                TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler,
                ExceptionHandler exceptionHandler) {
            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
            this.exceptionHandler = exceptionHandler;
        }

        @Override
        public void beforeExecute(Thread t, Runnable r) {
            super.beforeExecute(t, r);
            logger.debug("AWS CloudTrail Processing Library created a thread " + t.getName());
        }

        @Override
        public void afterExecute(Runnable r, Throwable t) {
            try {
                if (t != null) {
                    logger.error(
                            "AWS CloudTrail Processing Library encounted an uncaught exception. " + t.getMessage(),
                            t);
                    ProgressStatus status = new ProgressStatus(ProgressState.uncaughtException, null);
                    this.exceptionHandler.handleException(new ProcessingLibraryException(t.getMessage(), status));
                }
            } finally {
                super.afterExecute(r, t);
                logger.debug("AWS CloudTrail Processing Library completed execution of a runnable.");
            }
        }

    }
}