Package org.jboss.threads.metadata

Source Code of org.jboss.threads.metadata.ThreadsMetaData

/*
* JBoss, Home of Professional Open Source
* Copyright 2008, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.threads.metadata;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import java.util.Queue;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import static java.lang.Math.max;
import java.lang.annotation.Annotation;
import org.jboss.xb.annotations.JBossXmlSchema;
import org.jboss.beans.metadata.spi.BeanMetaData;
import org.jboss.beans.metadata.spi.ValueMetaData;
import org.jboss.beans.metadata.spi.BeanMetaDataFactory;
import org.jboss.beans.metadata.spi.builder.BeanMetaDataBuilder;
import org.jboss.threads.JBossThreadFactory;
import org.jboss.threads.InterruptHandler;
import org.jboss.threads.SimpleQueueExecutor;
import org.jboss.threads.JBossExecutors;
import org.jboss.threads.RejectionPolicy;
import org.jboss.threads.ArrayQueue;
import org.jboss.threads.JBossThreadPoolExecutor;
import org.jboss.threads.DirectExecutor;
import org.jboss.threads.ThreadPoolExecutorMBean;
import org.jboss.dependency.spi.ControllerMode;
import org.jboss.aop.microcontainer.aspects.jmx.JMX;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlTransient;

/**
*
*/
@JBossXmlSchema(namespace = "urn:jboss:threads:1.0", elementFormDefault = XmlNsForm.QUALIFIED)
@XmlRootElement(name = "threads")
@XmlType(name = "threads")
public final class ThreadsMetaData implements BeanMetaDataFactory {
    private static final class StringEntry implements Map.Entry<String, String> {
        private final String key;
        private final String value;

        private StringEntry(final String key, final String value) {
            this.key = key;
            this.value = value;
        }

        public String getKey() {
            return key;
        }

        public String getValue() {
            return value;
        }

        public String setValue(final String value) {
            throw new UnsupportedOperationException();
        }
    }

    private static StringEntry entry(final String key, final String value) {
        return new StringEntry(key, value);
    }

    private static Map<String, String> stringMap(StringEntry... entries) {
        final HashMap<String, String> hashMap = new HashMap<String, String>(entries.length);
        for (Map.Entry<String, String> e : entries) {
            hashMap.put(e.getKey(), e.getValue());
        }
        return Collections.unmodifiableMap(hashMap);
    }

    private static final Map<String, String> UNIT_NICK_NAMES = stringMap(
            entry("S", "SECONDS"),
            entry("SEC", "SECONDS"),
            entry("M", "MINUTES"),
            entry("MIN", "MINUTES"),
            entry("MS", "MILLISECONDS"),
            entry("NS", "NANOSECONDS"),
            entry("H", "HOURS"),
            entry("D", "DAYS"),
            entry("MON", "MONTHS"),
            entry("W", "WEEKS")
    );

    private List<ThreadGroupMetaData> threadGroups = new ArrayList<ThreadGroupMetaData>();
    private List<ThreadFactoryMetaData> threadFactories = new ArrayList<ThreadFactoryMetaData>();
    private List<ThreadPoolExecutorMetaData> threadPoolExecutors = new ArrayList<ThreadPoolExecutorMetaData>();
    private List<DirectExecutorMetaData> directExecutors = new ArrayList<DirectExecutorMetaData>();
    private List<NotatingExecutorMetaData> notatingExecutors = new ArrayList<NotatingExecutorMetaData>();
    private List<ScheduledThreadPoolExecutorMetaData> scheduledThreadPoolExecutors = new ArrayList<ScheduledThreadPoolExecutorMetaData>();

    public List<ThreadGroupMetaData> getThreadGroups() {
        return threadGroups;
    }

    @XmlElement(name = "thread-group")
    public void setThreadGroups(final List<ThreadGroupMetaData> threadGroups) {
        this.threadGroups = threadGroups;
    }

    public List<ThreadFactoryMetaData> getThreadFactories() {
        return threadFactories;
    }

    @XmlElement(name = "thread-factory")
    public void setThreadFactories(final List<ThreadFactoryMetaData> threadFactories) {
        this.threadFactories = threadFactories;
    }

    public List<ThreadPoolExecutorMetaData> getThreadPoolExecutors() {
        return threadPoolExecutors;
    }

    @XmlElement(name = "thread-pool-executor")
    public void setThreadPoolExecutors(final List<ThreadPoolExecutorMetaData> threadPoolExecutors) {
        this.threadPoolExecutors = threadPoolExecutors;
    }

    public List<DirectExecutorMetaData> getDirectExecutors() {
        return directExecutors;
    }

    @XmlElement(name = "direct-executor")
    public void setDirectExecutors(final List<DirectExecutorMetaData> directExecutors) {
        this.directExecutors = directExecutors;
    }

    public List<NotatingExecutorMetaData> getNotatingExecutors() {
        return notatingExecutors;
    }

    @XmlElement(name = "notating-executor")
    public void setNotatingExecutors(final List<NotatingExecutorMetaData> notatingExecutors) {
        this.notatingExecutors = notatingExecutors;
    }

    public List<ScheduledThreadPoolExecutorMetaData> getScheduledThreadPoolExecutors() {
        return scheduledThreadPoolExecutors;
    }

    @XmlElement(name = "scheduled-thread-pool-executor")
    public void setScheduledThreadPoolExecutors(final List<ScheduledThreadPoolExecutorMetaData> scheduledThreadPoolExecutors) {
        this.scheduledThreadPoolExecutors = scheduledThreadPoolExecutors;
    }

    @XmlTransient
    public List<BeanMetaData> getBeans() {
        List<BeanMetaData> beanMetaDataList = new ArrayList<BeanMetaData>();
        for (ThreadGroupMetaData metaData : threadGroups) {
            final String name = metaData.getName();
            final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, ThreadGroup.class.getName());
            builder.setMode(ControllerMode.ON_DEMAND);
            final String parent = metaData.getParent();
            if (parent != null && parent.length() > 0) {
                builder.addConstructorParameter(ThreadGroup.class.getName(), builder.createInject(parent));
            }
            builder.addConstructorParameter(String.class.getName(), builder.createValue(name));
            if (metaData.isDaemon() != null) {
                builder.addPropertyMetaData("daemon", builder.createValue(metaData.isDaemon()));
            }
            final Integer maxPriorityMeta = metaData.getMaxPriority();
            if (maxPriorityMeta != null) {
                builder.addPropertyMetaData("maxPriority", builder.createValue(maxPriorityMeta));
            }
            builder.ignoreStop();
            builder.ignoreDestroy();
            beanMetaDataList.add(builder.getBeanMetaData());
        }
        for (ThreadFactoryMetaData metaData : threadFactories) {
            final String name = metaData.getName();
            final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, JBossThreadFactory.class.getName());
            builder.setMode(ControllerMode.ON_DEMAND);
            final String group = metaData.getGroup();
            builder.addConstructorParameter(ThreadGroup.class.getName(), group == null ? builder.createNull() : builder.createInject(group));
            final Boolean daemon = metaData.getDaemon();
            builder.addConstructorParameter(Boolean.class.getName(), daemon == null ? builder.createNull() : builder.createValue(daemon));
            final Integer priorityMeta = metaData.getInitialPriority();
            final Integer actualPriorityMeta;
            if (priorityMeta != null) {
                actualPriorityMeta = priorityMeta;
            } else {
                actualPriorityMeta = null;
            }
            builder.addConstructorParameter(Integer.class.getName(), actualPriorityMeta == null ? builder.createNull() : builder.createValue(actualPriorityMeta));
            builder.addConstructorParameter(String.class.getName(), builder.createValue(metaData.getThreadNamePattern()));
            final List<ValueMetaData> interruptHandlers = builder.createArray(InterruptHandler[].class.getName(), InterruptHandler.class.getName());
            for (InterruptHandlerRefMetaData ihmd : metaData.getInterruptHandlers()) {
                interruptHandlers.add(builder.createInject(ihmd.getName()));
            }
            builder.addConstructorParameter(InterruptHandler[].class.getName(), (ValueMetaData) interruptHandlers);
            final ExceptionHandlerRefMetaData ehmd = metaData.getExceptionHandler();
            builder.addConstructorParameter(Thread.UncaughtExceptionHandler.class.getName(), ehmd == null ? builder.createNull() : builder.createInject(ehmd.getName()));
            final Long stackSize = metaData.getStackSize();
            builder.addConstructorParameter(Long.class.getName(), stackSize == null ? builder.createNull() : builder.createValue(stackSize));
            beanMetaDataList.add(builder.getBeanMetaData());
        }
        for (ThreadPoolExecutorMetaData metaData : threadPoolExecutors) {
            final String name = metaData.getName();
            final PoolSizeMetaData corePoolSizeMetaData = metaData.getCorePoolSize();
            final int corePoolSize;
            if (corePoolSizeMetaData == null) {
                corePoolSize = 0;
            } else {
                corePoolSize = max(calcPoolSize(corePoolSizeMetaData), 0);
            }
            final PoolSizeMetaData maxPoolSizeMetaData = metaData.getMaxPoolSize();
            final int maxPoolSize;
            if (maxPoolSizeMetaData == null) {
                maxPoolSize = max(corePoolSize, 1);
            } else {
                maxPoolSize = max(calcPoolSize(maxPoolSizeMetaData), max(1, corePoolSize));
            }
            final TimeMetaData timeMetaData = metaData.getKeepAliveTime();
            final long time;
            final TimeUnit unit;
            if (timeMetaData == null) {
                time = Long.MAX_VALUE;
                unit = TimeUnit.NANOSECONDS;
            } else {
                time = max(0L, timeMetaData.getTime());
                final String unitName = timeMetaData.getUnit();

                if (unitName == null) {
                    unit = TimeUnit.MILLISECONDS;
                } else {
                    final String upperUnitName = unitName.toUpperCase();
                    if (UNIT_NICK_NAMES.containsKey(upperUnitName)) {
                        unit = TimeUnit.valueOf(UNIT_NICK_NAMES.get(upperUnitName));
                    } else {
                        unit = TimeUnit.valueOf(upperUnitName);
                    }
                }
            }
            final String threadFactory = metaData.getThreadFactory();
            if (threadFactory == null) {
                throw new IllegalArgumentException("threadFactory is not defined");
            }
            final Integer queueLength = metaData.getQueueLength();
            final RejectPolicyMetaData rejectPolicyMetaData = metaData.getRejectPolicyMetaData();
            final String policyName = rejectPolicyMetaData == null ? "block" : rejectPolicyMetaData.getName();
            final BeanMetaDataBuilder executorBuilder;
            // here is where we decide which thread pool implementation to use
            // right now, our criteria is simple - if blocking is desired or if core threads can time out, use the queue executor instead
            if (metaData.isAllowCoreTimeout() || "block".equals(policyName)) {
                // use SimpleQueueExecutor
                executorBuilder = BeanMetaDataBuilder.createBuilder(SimpleQueueExecutor.class.getName());
                final RejectionPolicy rejectionPolicy;
                final ValueMetaData handoffExecutorValue;
                if ("abort".equals(policyName)) {
                    rejectionPolicy = RejectionPolicy.ABORT;
                    handoffExecutorValue = executorBuilder.createNull();
                } else if ("block".equals(policyName)) {
                    rejectionPolicy = RejectionPolicy.BLOCK;
                    handoffExecutorValue = executorBuilder.createNull();
                } else if ("caller-runs".equals(policyName)) {
                    rejectionPolicy = RejectionPolicy.HANDOFF;
                    handoffExecutorValue = executorBuilder.createValue(JBossExecutors.directExecutor());
                } else if ("discard".equals(policyName)) {
                    rejectionPolicy = RejectionPolicy.DISCARD;
                    handoffExecutorValue = executorBuilder.createNull();
                } else if ("discard-oldest".equals(policyName)) {
                    rejectionPolicy = RejectionPolicy.DISCARD_OLDEST;
                    handoffExecutorValue = executorBuilder.createNull();
                } else if ("handoff".equals(policyName)) {
                    rejectionPolicy = RejectionPolicy.HANDOFF;
                    handoffExecutorValue = executorBuilder.createInject(rejectPolicyMetaData.getExecutorName());
                } else {
                    throw new IllegalStateException();
                }
                final Queue<Runnable> queue;
                if (queueLength == null) {
                    queue = new LinkedList<Runnable>();
                } else {
                    queue = new ArrayQueue<Runnable>(queueLength.intValue());
                }
                executorBuilder.addConstructorParameter(String.class.getName(), name);
                executorBuilder.addConstructorParameter("int", Integer.valueOf(corePoolSize));
                executorBuilder.addConstructorParameter("int", Integer.valueOf(maxPoolSize));
                executorBuilder.addConstructorParameter("long", Long.valueOf(time));
                executorBuilder.addConstructorParameter(TimeUnit.class.getName(), unit);
                executorBuilder.addConstructorParameter(Queue.class.getName(), executorBuilder.createValue(queue));
                executorBuilder.addConstructorParameter(ThreadFactory.class.getName(), executorBuilder.createInject(threadFactory));
                executorBuilder.addConstructorParameter(RejectionPolicy.class.getName(), rejectionPolicy);
                executorBuilder.addConstructorParameter(Executor.class.getName(), handoffExecutorValue);
                if (metaData.isAllowCoreTimeout()) {
                    executorBuilder.addPropertyMetaData("allowCoreTimeout", Boolean.TRUE);
                }
            } else {
                // use ThreadPoolExecutor
                executorBuilder = BeanMetaDataBuilder.createBuilder(JBossThreadPoolExecutor.class.getName());
                final ValueMetaData policyValue;
                if ("abort".equals(policyName)) {
                    policyValue = executorBuilder.createValue(JBossExecutors.abortPolicy());
                } else if ("block".equals(policyName)) {
                    throw new IllegalStateException();
                } else if ("caller-runs".equals(policyName)) {
                    policyValue = executorBuilder.createValue(JBossExecutors.callerRunsPolicy());
                } else if ("discard".equals(policyName)) {
                    policyValue = executorBuilder.createValue(JBossExecutors.discardPolicy());
                } else if ("discard-oldest".equals(policyName)) {
                    policyValue = executorBuilder.createValue(JBossExecutors.discardOldestPolicy());
                } else if ("handoff".equals(policyName)) {
                    final BeanMetaDataBuilder policyBuilder = BeanMetaDataBuilder.createBuilder(RejectedExecutionHandler.class.getName());
                    policyBuilder.setFactoryClass(JBossExecutors.class.getName());
                    policyBuilder.setFactoryMethod("handoffPolicy");
                    policyBuilder.addConstructorParameter(Executor.class.getName(), policyBuilder.createInject(rejectPolicyMetaData.getExecutorName()));
                    policyValue = policyBuilder.getBeanMetaData();
                } else {
                    throw new IllegalStateException();
                }
                final BlockingQueue<Runnable> queue;
                if (queueLength == null) {
                    // todo: try LinkedTransferQueue
                    queue = new LinkedBlockingQueue<Runnable>();
                } else {
                    queue = new ArrayBlockingQueue<Runnable>(queueLength.intValue());
                }
                executorBuilder.addConstructorParameter(String.class.getName(), name);
                executorBuilder.addConstructorParameter("int", Integer.valueOf(corePoolSize));
                executorBuilder.addConstructorParameter("int", Integer.valueOf(maxPoolSize));
                executorBuilder.addConstructorParameter("long", Long.valueOf(time));
                executorBuilder.addConstructorParameter(TimeUnit.class.getName(), unit);
                executorBuilder.addConstructorParameter(BlockingQueue.class.getName(), executorBuilder.createValue(queue));
                executorBuilder.addConstructorParameter(ThreadFactory.class.getName(), executorBuilder.createInject(threadFactory));
                executorBuilder.addConstructorParameter(RejectedExecutionHandler.class.getName(), policyValue);
            }
            executorBuilder.addAnnotation(new JMX() {
                public Class<?> exposedInterface() {
                    return ThreadPoolExecutorMBean.class;
                }

                public String name() {
                    return "jboss.threads:service=ThreadPoolExecutor,name=" + name;
                }

                public boolean registerDirectly() {
                    return false;
                }

                public Class<? extends Annotation> annotationType() {
                    return JMX.class;
                }
            });
            executorBuilder.setMode(ControllerMode.ON_DEMAND);
//            final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, ExecutorService.class.getName());
//            builder.setFactoryClass(JBossExecutors.class.getName());
//            builder.setFactoryMethod("protectedExecutorService");
//            builder.addConstructorParameter(Executor.class.getName(), executorBuilder.getBeanMetaData());
//            builder.setMode(ControllerMode.ON_DEMAND);
//            beanMetaDataList.add(builder.getBeanMetaData());
            executorBuilder.setName(name);
            beanMetaDataList.add(executorBuilder.getBeanMetaData());
        }
        for (DirectExecutorMetaData metaData : directExecutors) {
            final String name = metaData.getName();
            final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, ExecutorService.class.getName());
            builder.setFactoryClass(JBossExecutors.class.getName());
            builder.setFactoryMethod("directExecutorService");
            builder.setMode(ControllerMode.ON_DEMAND);
            beanMetaDataList.add(builder.getBeanMetaData());
        }
        for (NotatingExecutorMetaData metaData : notatingExecutors) {
            final String name = metaData.getName();
            final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, DirectExecutor.class.getName());
            builder.setMode(ControllerMode.ON_DEMAND);
            builder.setFactoryClass(JBossExecutors.class.getName());
            builder.setFactoryMethod("notatingExecutor");
            builder.addConstructorParameter(Executor.class.getName(), builder.createInject(metaData.getParent()));
            builder.addConstructorParameter(String.class.getName(), metaData.getNote());
            beanMetaDataList.add(builder.getBeanMetaData());
        }
        for (ScheduledThreadPoolExecutorMetaData metaData : scheduledThreadPoolExecutors) {
            final String name = metaData.getName();
            final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, ScheduledThreadPoolExecutor.class.getName());
            builder.setMode(ControllerMode.ON_DEMAND);
            final PoolSizeMetaData poolSizeMetaData = metaData.getPoolSize();
            final int size;
            if (poolSizeMetaData != null) {
                size = max(1, calcPoolSize(poolSizeMetaData));
            } else {
                size = 1;
            }
            builder.addConstructorParameter("int", Integer.valueOf(size));
            final String threadFactoryName = metaData.getThreadFactory();
            if (threadFactoryName != null) {
                builder.addConstructorParameter(ThreadFactory.class.getName(), builder.createInject(threadFactoryName));
            }
            beanMetaDataList.add(builder.getBeanMetaData());
        }
        return beanMetaDataList;
    }

    private static int calcPoolSize(PoolSizeMetaData poolSizeMetaData) {
        float count = poolSizeMetaData.getCount();
        float perCpu = poolSizeMetaData.getPerCpu();
        if (Float.isNaN(count) || Float.isInfinite(count) || count < 0.0f) {
            count = 0.0f;
        }
        if (Float.isNaN(perCpu) || Float.isInfinite(perCpu) || perCpu < 0.0f) {
            perCpu = 0.0f;
        }
        return Math.round(count + ((float) Runtime.getRuntime().availableProcessors()) * perCpu);
    }
}
TOP

Related Classes of org.jboss.threads.metadata.ThreadsMetaData

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.