Package co.paralleluniverse.common.monitoring

Source Code of co.paralleluniverse.common.monitoring.MonitoringServices

/*
* Copyright (c) 2011-2014, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*   or (per the licensee's choosing)
* under the terms of the GNU Lesser General Public License version 3.0
* as published by the Free Software Foundation.
*/
package co.paralleluniverse.common.monitoring;

import co.paralleluniverse.concurrent.util.ThreadUtil;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.Date;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.timer.Timer;

/**
*
* @author pron
*/
public final class MonitoringServices implements MonitoringServicesMXBean {
    public static final MonitoringServices instance = new MonitoringServices();

    public static MonitoringServices getInstance() {
        return instance;
    }
    private final Timer timer = new Timer();
    private int perfTimerPeriod = 5000;
    private int structuralTimerPeriod = 30000;
    private boolean perfTimerStarted;
    private boolean structuralTimerStarted;
    private int perfTimerListeners;
    private int structuralTimerListeners;

    private MonitoringServices() {
        registerMBean();
        perfTimerListeners = 0;
        structuralTimerListeners = 0;

        killTimerOnExit();

        startPerformanceUpdates();
    }

    private synchronized void manageTimer() {
        if (!timer.isActive()) {
            if ((perfTimerStarted && perfTimerListeners > 0) || (structuralTimerStarted && structuralTimerListeners > 0))
                timer.start();
        } else {
            if ((!perfTimerStarted || perfTimerListeners == 0) && (!structuralTimerStarted || structuralTimerListeners == 0))
                timer.stop();
        }
    }

    private void registerMBean() {
        try {
            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
            ObjectName mxbeanName = new ObjectName("co.paralleluniverse:name=MonitoringServices");
            mbs.registerMBean(this, mxbeanName);
        } catch (InstanceAlreadyExistsException ex) {
            throw new RuntimeException(ex);
        } catch (MBeanRegistrationException ex) {
            ex.printStackTrace();
        } catch (NotCompliantMBeanException ex) {
            throw new AssertionError(ex);
        } catch (MalformedObjectNameException ex) {
            throw new AssertionError(ex);
        }
    }

    @Override
    public synchronized int getPerformanceTimerPeriod() {
        return perfTimerPeriod;
    }

    @Override
    public synchronized void setPerformanceTimerPeriod(int perfTimerPeriod) {
        if (perfTimerPeriod != this.perfTimerPeriod) {
            this.perfTimerPeriod = perfTimerPeriod;
            if (perfTimerStarted) {
                stopPerformanceUpdates();
                startPerformanceUpdates();
            }
        }
    }

    @Override
    public synchronized boolean isPerformanceUpdates() {
        return perfTimerStarted;
    }

    @Override
    public synchronized void setPerformanceUpdates(boolean value) {
        if (value == perfTimerStarted)
            return;
        if (!perfTimerStarted)
            startPerformanceUpdates();
        else
            stopPerformanceUpdates();
    }

    @Override
    public synchronized void startPerformanceUpdates() {
        if (!perfTimerStarted) {
            timer.addNotification("perfTimer", null, null, new Date(System.currentTimeMillis()), perfTimerPeriod);
            this.perfTimerStarted = true;
        }
        manageTimer();
    }

    @Override
    public synchronized void stopPerformanceUpdates() {
        if (perfTimerStarted) {
            try {
                timer.removeNotifications("perfTimer");
                this.perfTimerStarted = false;
            } catch (InstanceNotFoundException ex) {
            }
        }
        manageTimer();
    }

    public synchronized void addPerfNotificationListener(NotificationListener listener, Object handback) {
        timer.addNotificationListener(listener, new NotificationFilter() {
            @Override
            public boolean isNotificationEnabled(Notification notification) {
                return "perfTimer".equals(notification.getType());
            }
        }, handback);
        perfTimerListeners++;
        manageTimer();
    }

    public synchronized void removePerfNotificationListener(NotificationListener listener) {
        try {
            timer.removeNotificationListener(listener);
            perfTimerListeners--;
            manageTimer();
        } catch (ListenerNotFoundException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public synchronized boolean isStructuralUpdates() {
        return structuralTimerStarted;
    }

    @Override
    public synchronized void setStructuralUpdates(boolean value) {
        if (value == structuralTimerStarted)
            return;
        if (!structuralTimerStarted)
            startStructuralUpdates();
        else
            stopStructuralUpdates();
    }

    @Override
    public synchronized void startStructuralUpdates() {
        if (!structuralTimerStarted) {
            timer.addNotification("structTimer", null, null, new Date(System.currentTimeMillis()), structuralTimerPeriod);
            this.structuralTimerStarted = true;
        }
        manageTimer();
    }

    @Override
    public synchronized void stopStructuralUpdates() {
        if (structuralTimerStarted) {
            try {
                timer.removeNotifications("structTimer");
                this.structuralTimerStarted = false;
            } catch (InstanceNotFoundException ex) {
            }
        }
        manageTimer();
    }

    @Override
    public synchronized int getStructuraltimerPeriod() {
        return structuralTimerPeriod;
    }

    @Override
    public synchronized void setStructuraltimerPeriod(int structuralTimerPeriod) {
        if (structuralTimerPeriod != this.structuralTimerPeriod) {
            this.structuralTimerPeriod = structuralTimerPeriod;
            if (structuralTimerStarted) {
                stopStructuralUpdates();
                startStructuralUpdates();
            }
        }
    }

    public synchronized void addStructuralNotificationListener(NotificationListener listener, Object handback) {
        timer.addNotificationListener(listener, new NotificationFilter() {
            @Override
            public boolean isNotificationEnabled(Notification notification) {
                return "structTimer".equals(notification.getType());
            }
        }, handback);
        structuralTimerListeners++;
        manageTimer();
    }

    public synchronized void removeStructuralNotificationListener(NotificationListener listener) {
        try {
            timer.removeNotificationListener(listener);
            structuralTimerListeners--;
            manageTimer();
        } catch (ListenerNotFoundException ex) {
            ex.printStackTrace();
        }
    }

    private void killTimerOnExit() {
        // unfortunately, there's no way to make the timer thread a daemon,
        // wo kill timer thread if it's the last non-daemon thread.
        timer.addNotification("isLastThreadTest", null, null, new Date(System.currentTimeMillis()), 1500);
        timer.addNotificationListener(new NotificationListener() {
            @Override
            public void handleNotification(Notification notification, Object handback) {
                final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
                int tCount = mbean.getThreadCount();
                int dCount = mbean.getDaemonThreadCount();

                if (tCount - dCount <= 2) {
                    boolean stop = true;
                    Thread[] ts;

                    for (;;) {
                        ts = new Thread[mbean.getThreadCount() + 3];
                        if (Thread.enumerate(ts) < ts.length)
                            break;
                    }
                    for (Thread t : ts) {
                        if(t == null)
                            break;
                        if (t.isDaemon() || t == Thread.currentThread())
                            continue;
                        if (!t.getName().equals("DestroyJavaVM"))
                            stop = false;
                    }

                    if (stop)
                        timer.stop();
                }
            }
        }, new NotificationFilter() {
            @Override
            public boolean isNotificationEnabled(Notification notification) {
                return "isLastThreadTest".equals(notification.getType());
            }
        }, null);
    }
}
TOP

Related Classes of co.paralleluniverse.common.monitoring.MonitoringServices

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.