co.paralleluniverse.common.monitoring.PeriodicMonitor.java Source code

Java tutorial

Introduction

Here is the source code for co.paralleluniverse.common.monitoring.PeriodicMonitor.java

Source

/*
 * Copyright (c) 2012-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 java.lang.management.ManagementFactory;
import java.lang.ref.WeakReference;
import java.util.Date;
import javax.management.AttributeChangeNotification;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.StandardEmitterMBean;
import javax.management.timer.Timer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

/**
 *
 * @author pron
 */
public abstract class PeriodicMonitor extends StandardEmitterMBean
        implements NotificationListener, NotificationEmitter, InitializingBean, DisposableBean {
    private static final Logger LOG = LoggerFactory.getLogger(PeriodicMonitor.class);
    private final String name;
    private boolean registered;
    private long lastCollectTime;
    private int notificationSequenceNumber;
    private WeakReference<Object> monitored;
    private boolean timerStarted;
    private int timerPeriod = 5000;
    private final Timer timer = new Timer();

    public PeriodicMonitor(Class mbeanInterface, String name) {
        super(mbeanInterface, true, new NotificationBroadcasterSupport());
        this.name = name;
        this.lastCollectTime = System.currentTimeMillis();
        this.monitored = null;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        collectAndResetCounters1();
        registerMBean();
    }

    @Override
    public void destroy() throws Exception {
        unregisterMBean();
    }

    public void setMonitoredObject(Object obj) {
        this.monitored = new WeakReference<Object>(obj);
    }

    private boolean isMonitoredObjectAlive() {
        return monitored == null || monitored.get() != null;
    }

    private void registerMBean() {
        try {
            LOG.info("Registering MBean {}", name);
            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
            ObjectName mxbeanName = new ObjectName(name);
            mbs.registerMBean(this, mxbeanName);

            timer.addNotificationListener(this, new NotificationFilter() {
                @Override
                public boolean isNotificationEnabled(Notification notification) {
                    return "tickTimer".equals(notification.getType());
                }
            }, null);
            this.registered = true;
        } catch (InstanceAlreadyExistsException ex) {
            throw new RuntimeException(ex);
        } catch (MBeanRegistrationException ex) {
            throw new RuntimeException(ex);
        } catch (NotCompliantMBeanException ex) {
            throw new AssertionError(ex);
        } catch (MalformedObjectNameException ex) {
            throw new AssertionError(ex);
        }
    }

    public void unregisterMBean() {
        try {
            if (registered) {
                LOG.info("Unregistering MBean {}", name);
                ManagementFactory.getPlatformMBeanServer().unregisterMBean(new ObjectName(name));
                timer.stop();
            }
            this.registered = false;
        } catch (Exception e) {
            LOG.warn("Exception:", e);
        }
    }

    @Override
    public MBeanNotificationInfo[] getNotificationInfo() {
        String[] types = new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE };
        String _name = AttributeChangeNotification.class.getName();
        String description = "An attribute of this MBean has changed";
        MBeanNotificationInfo info = new MBeanNotificationInfo(types, _name, description);
        return new MBeanNotificationInfo[] { info };
    }

    @Override
    public void handleNotification(Notification notification, Object handback) {
        if ("tickTimer".equals(notification.getType())) {
            //assert Objects.equal(handback, name);
            refresh();
        }
    }

    public void refresh() {
        collectAndResetCounters1();
        //Notification n = new AttributeChangeNotification(this, notificationSequenceNumber++, System.currentTimeMillis(), "CacheInfo changed", "PerfInfo", newValue.getClass().getName(), null, newValue);
        Notification n = new AttributeChangeNotification(this, notificationSequenceNumber++,
                System.currentTimeMillis(), "Info changed", "", null, null, null);
        sendNotification(n);
    }

    protected long getMillisSinceLastCollect() {
        return System.currentTimeMillis() - lastCollectTime;
    }

    public synchronized int getTimerPeriod() {
        return timerPeriod;
    }

    public synchronized void setTimerPeriod(int timerPeriod) {
        if (timerPeriod != this.timerPeriod) {
            this.timerPeriod = timerPeriod;
            if (timerStarted) {
                stopUpdates();
                startUpdates();
            }
        }
    }

    public synchronized boolean isUpdates() {
        return timerStarted;
    }

    public synchronized void setUpdates(boolean value) {
        if (value == timerStarted)
            return;
        if (!timerStarted)
            startUpdates();
        else
            stopUpdates();
    }

    public synchronized void startUpdates() {
        if (!timerStarted) {
            timer.addNotification("tickTimer", null, null, new Date(System.currentTimeMillis()), timerPeriod);
            this.timerStarted = true;
            timer.start();
        }
    }

    public synchronized void stopUpdates() {
        if (timerStarted) {
            try {
                timer.removeNotifications("tickTimer");
                this.timerStarted = false;
            } catch (InstanceNotFoundException ex) {
            }
            timer.stop();
        }
    }

    private void collectAndResetCounters1() {
        if (registered) {
            if (!isMonitoredObjectAlive())
                unregisterMBean();
            else {
                collectAndResetCounters();
                lastCollectTime = System.currentTimeMillis();
                return;
            }
        }
        resetCounters();
        lastCollectTime = System.currentTimeMillis();
    }

    protected void initCounters() {
    }

    protected abstract void collectAndResetCounters();

    protected abstract void resetCounters();
}