dk.statsbiblioteket.doms.radiotv.extractor.transcoder.ProcessorChainThreadPool.java Source code

Java tutorial

Introduction

Here is the source code for dk.statsbiblioteket.doms.radiotv.extractor.transcoder.ProcessorChainThreadPool.java

Source

/* $Id$
 * $Revision$
 * $Date$
 * $Author$
 *
 * The Netarchive Suite - Software to harvest and preserve websites
 * Copyright 2004-2009 Det Kongelige Bibliotek and Statsbiblioteket, Denmark
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 *   USA
 */
package dk.statsbiblioteket.doms.radiotv.extractor.transcoder;

import dk.statsbiblioteket.doms.radiotv.extractor.Constants;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.log4j.Logger;

import javax.servlet.ServletConfig;
import java.util.Comparator;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

public class ProcessorChainThreadPool {

    private static final Logger log = Logger.getLogger(ProcessorChainThreadPool.class);

    /**
     * Singleton instance
     */
    private static ProcessorChainThreadPool instance;
    private static BlockingQueue<ProcessorChainThread> theQueue;
    private static GenericObjectPool thePool;
    private static int maxActiveProcesses;

    /**
     * Singleton.
     */
    private ProcessorChainThreadPool(ServletConfig config) {
        theQueue = new LinkedBlockingQueue<ProcessorChainThread>();
        //theQueue = new PriorityBlockingQueue(1000, new ThreadComparator());
        maxActiveProcesses = Integer.parseInt(Util.getInitParameter(config, Constants.MAX_ACTIVE_PROCESSING));
        log.info("Creating thread pool with max active processes = " + maxActiveProcesses);
        thePool = new GenericObjectPool(new BasePoolableObjectFactory() {
            @Override
            public Object makeObject() throws Exception {
                return new Object();
            }
        }, maxActiveProcesses);
    }

    public static synchronized ProcessorChainThreadPool getInstance(ServletConfig config) {
        if (instance == null) {
            instance = new ProcessorChainThreadPool(config);
            startHarvestingThread();
        }
        return instance;
    }

    public static synchronized void addProcessorChainThread(ProcessorChainThread thread) {
        getInstance(thread.getConfig());
        theQueue.add(thread);
    }

    private static void startHarvestingThread() {
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    try {
                        ProcessorChainThread theThread = theQueue.take();
                        try {
                            Object lockObject = thePool.borrowObject();
                            theThread.getRequest().setLockObject(lockObject);
                            theThread.getRequest().setThePool(thePool);
                            log.info("Locking request '" + theThread.getRequest().getPid() + "' with '" + lockObject
                                    + "");
                            theThread.start();
                        } catch (Exception e) {
                            log.error("Unexpected error starting transcoding process", e);
                        }
                    } catch (InterruptedException e) {
                        log.error("Unexpected error, trying to recover", e);
                    }
                }
            }
        }.start();
    }

    public int getPosition(TranscodeRequest request) {
        Iterator<ProcessorChainThread> threads = theQueue.iterator();
        int position = 0;
        while (threads.hasNext()) {
            position++;
            final TranscodeRequest thisRequest = threads.next().getRequest();
            if (thisRequest.getKey().equals(request.getKey())
                    && thisRequest.getServiceType().equals(request.getServiceType())) {
                log.info("Request '" + request.getPid() + "' has position " + position + " in queue");
                log.info("Queue size is " + theQueue.size());
                return position;
            }
        }
        ;
        return 0;
    }

    private static class ThreadComparator implements Comparator<ProcessorChainThread> {

        @Override
        public int compare(ProcessorChainThread o1, ProcessorChainThread o2) {
            ServiceTypeEnum type1 = o1.getRequest().getServiceType();
            ServiceTypeEnum type2 = o1.getRequest().getServiceType();
            if (type1.equals(ServiceTypeEnum.PREVIEW_GENERATION)
                    && type2.equals(ServiceTypeEnum.THUMBNAIL_GENERATION)) {
                return 1;
            } else if (type2.equals(ServiceTypeEnum.PREVIEW_GENERATION)
                    && type1.equals(ServiceTypeEnum.THUMBNAIL_GENERATION)) {
                return -1;
            } else if (o1.getTimestamp().equals(o2.getTimestamp())) {
                return 0;
            } else if (o1.getTimestamp() > o2.getTimestamp()) {
                return -1;
            } else {
                return 1;
            }
        }
    }

}