Package org.geoserver.monitor

Source Code of org.geoserver.monitor.PipeliningTaskQueue

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.monitor;

import java.util.ArrayList;
import java.util.Map;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geotools.util.logging.Logging;

/**
* A task queue that groups tasks by key and ensures that tasks with same key
* execute serially.
*
* @author Justin Deoliveira, OpenGeo
*
* @param <K> The key type.
*/
public class PipeliningTaskQueue<K> implements Runnable {

    static Logger LOGGER = Logging.getLogger("org.geoserver.monitor");
   
    ConcurrentHashMap<K, Queue<Pipelineable<K>>> pipelines;
    ScheduledExecutorService executor;
    ExecutorService tasks;
   
    public PipeliningTaskQueue() {
        pipelines = new ConcurrentHashMap();
        tasks = Executors.newCachedThreadPool();
    }
   
    public void start() {
        executor = Executors.newScheduledThreadPool(4);
        executor.scheduleAtFixedRate(this, 0, 10, TimeUnit.MILLISECONDS);
        executor.scheduleAtFixedRate(this, 0, 10, TimeUnit.MILLISECONDS);
        executor.scheduleAtFixedRate(this, 0, 10, TimeUnit.MILLISECONDS);
        executor.scheduleAtFixedRate(this, 0, 10, TimeUnit.MILLISECONDS);
    }
   
    public void stop() {
        executor.shutdown();
        executor = null;
       
        tasks.shutdown();
        tasks = null;
    }
   
    public void execute(K key, Runnable task) {
        execute(key, task, "");
    }
   
    public void execute(K key, Runnable task, String desc) {
        Queue<Pipelineable<K>> pipeline = pipelines.get(key);
        if (pipeline == null) {
            synchronized (pipelines) {
                pipeline = pipelines.get(key);
                if (pipeline == null) {
                    pipeline = new ConcurrentLinkedQueue();
                    pipelines.put(key, pipeline);
                }
            }
        }
       
        if (LOGGER.isLoggable(Level.FINEST)) {
            LOGGER.finest("Queuing task into pipeline " + key);
        }
        pipeline.add(new Pipelineable<K>(key, task));
    }
   
   
    public void clear(K key) {
        pipelines.remove(key);
    }
   
    public void shutdown() {
        executor.shutdown();
        tasks.shutdown();
       
    }
    public void run() {
       
        for (Queue<Pipelineable<K>> pipeline : pipelines.values()) {
            Pipelineable<K> job = pipeline.peek();
            if (job != null) {
                if (!job.lock.tryLock()) continue; //another thread already handling this job
               
                if (job.future != null) {
                    //job has been submitted, if it is done remove it from
                    // the queue
                    if (job.future.isDone()) {
                        if (LOGGER.isLoggable(Level.FINEST)) {
                            LOGGER.finest("Removing task from queue " + job.key);
                        }
                        pipeline.remove();
                    }
                }
                else {
                    //start the job
                    if (LOGGER.isLoggable(Level.FINEST)) {
                        LOGGER.finest("Executing task in queue " + job.key);
                    }
                    job.future = tasks.submit(job.task);
                }
               
                job.lock.unlock();
            }
        }
     }
   
    public class Pipelineable<K> {
       
        K key;
        Runnable task;
        Future<?> future;
        Lock lock;
        String desc;
       
        public Pipelineable(K key, Runnable task) {
            this.key = key;
            this.task = task;
            this.lock = new ReentrantLock();
        }
    }
    public void print() {
       for (Map.Entry<K, Queue<Pipelineable<K>>> e : pipelines.entrySet()) {
           System.out.print(e.getKey());
           for (Pipelineable<K> p : e.getValue()) {
               System.out.print(p.desc + " ");
           }
           System.out.println();
       }
    }
}
TOP

Related Classes of org.geoserver.monitor.PipeliningTaskQueue

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.