Package co.paralleluniverse.actors

Source Code of co.paralleluniverse.actors.JMXActorsMonitor

/*
* Quasar: lightweight threads and actors for the JVM.
* Copyright (c) 2013-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.actors;

import co.paralleluniverse.common.monitoring.Counter;
import co.paralleluniverse.common.monitoring.MonitoringServices;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import jsr166e.LongAdder;
import org.cliffc.high_scale_lib.NonBlockingHashMapLong;
import org.cliffc.high_scale_lib.NonBlockingHashMapLong.IteratorLong;

/**
*
* @author pron
*/
class JMXActorsMonitor implements NotificationListener, ActorsMXBean {
    private static final JMXActorsMonitor instance = new JMXActorsMonitor();

    public static JMXActorsMonitor getInstance() {
        return instance;
    }
    private final String mbeanName;
    private boolean registered;
    private final NonBlockingHashMapLong<ActorRef<?>> actors = new NonBlockingHashMapLong<ActorRef<?>>();
    private final NonBlockingHashMapLong<SmallActorMonitor> watchedActors = new NonBlockingHashMapLong<SmallActorMonitor>();
    private long lastCollectTime;
    private final LongAdder activeCount = new LongAdder();

    private JMXActorsMonitor() {
        this.mbeanName = "co.paralleluniverse:type=Actors";
        registerMBean();
        lastCollectTime = nanoTime();
    }

    @SuppressWarnings({"CallToPrintStackTrace", "CallToThreadDumpStack"})
    private void registerMBean() {
        try {
            final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
            final ObjectName mxbeanName = new ObjectName(mbeanName);
            mbs.registerMBean(this, mxbeanName);
            this.registered = true;
        } 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);
        }
        MonitoringServices.getInstance().addPerfNotificationListener(this, mbeanName);
    }

    @SuppressWarnings({"CallToPrintStackTrace", "CallToThreadDumpStack"})
    private void unregister() {
        try {
            if (registered) {
                MonitoringServices.getInstance().removePerfNotificationListener(this);
                ManagementFactory.getPlatformMBeanServer().unregisterMBean(new ObjectName(mbeanName));
            }
            this.registered = false;
        } catch (InstanceNotFoundException ex) {
            ex.printStackTrace();
        } catch (MBeanRegistrationException ex) {
            ex.printStackTrace();
        } catch (MalformedObjectNameException ex) {
            throw new AssertionError(ex);
        }
    }

    @Override
    public void handleNotification(Notification notification, Object handback) {
        if ("perfTimer".equals(notification.getType()))
            refresh();
    }

    @Override
    public void refresh() {
        collectAndResetCounters();
    }

    public boolean isRegistered() {
        return registered;
    }

    private void collectAndResetCounters() {
        if (isRegistered()) {
            collectAndResetCounters(nanoTime() - lastCollectTime);
        }
    }

    protected void collectAndResetCounters(long intervalNanos) {

        lastCollectTime = nanoTime();
    }

    private long nanoTime() {
        return System.nanoTime();
    }

    void actorStarted(ActorRef<?> actor) {
        activeCount.increment();
        actors.put(LocalActor.getStrand(actor).getId(), actor);
    }

    void actorTerminated(ActorRef<?> actor) {
        activeCount.decrement();
        actors.remove(LocalActor.getStrand(actor).getId());
    }

    @Override
    public int getNumActiveActors() {
        return activeCount.intValue();
    }

    @Override
    public long[] getAllActorIds() {
        int size = actors.size();
        IteratorLong it = (IteratorLong) actors.keys();
        long[] ids = new long[size];
        int i = 0;
        while (it.hasNext() && i < size) {
            ids[i] = it.nextLong();
            i++;
        }
        if (i < size)
            return Arrays.copyOf(ids, i);
        else
            return ids; // might not include all nw fibers
    }

    @Override
    public String getStackTrace(long actorId) {
        ActorRef actor = actors.get(actorId);
        if (actor == null)
            return null;

        return getStackTrace(actor);
    }

    private String getStackTrace(ActorRef actor) {
        final StackTraceElement[] stackTrace = LocalActor.getStackTrace(actor);
        final StringBuilder sb = new StringBuilder();
        for (StackTraceElement ste : stackTrace)
            sb.append(ste).append('\n');
        return sb.toString();
    }
   
    @Override
    public String[] getMailbox(long actorId) {
        ActorRef actor = actors.get(actorId);
        if (actor == null)
            return null;

        return getMailbox(actor);
    }

    private String[] getMailbox(ActorRef actor) {
        List<Object> list = LocalActor.getMailboxSnapshot(actor);
        String[] ms = new String[list.size()];
        int i = 0;
        for (Object m : list)
            ms[i++] = m.toString();
        return ms;
    }
   
    @Override
    public void addWatch(long actorId) {
        ActorRef actor = actors.get(actorId);
        if (actor == null)
            throw new IllegalArgumentException("No actor with id " + actorId + " found.");
        SmallActorMonitor mon = new SmallActorMonitor(actorId);
        LocalActor.setMonitor(actor, mon);
        watchedActors.put(actorId, mon);
    }

    @Override
    public void removeWatch(long actorId) {
        SmallActorMonitor mon = watchedActors.get(actorId);
        if (mon == null)
            return;
        LocalActor.stopMonitor(mon.actor);
    }

    @Override
    public List<ActorInfo> getWatchedActorsInfo() {
        List<ActorInfo> list = new ArrayList<>(watchedActors.size());
        for (SmallActorMonitor mon : watchedActors.values()) {
            ActorInfo ai = getActorInfo(mon);
            if (ai != null)
                list.add(ai);
        }
        Collections.sort(list, new Comparator<ActorInfo>() {
            public int compare(ActorInfo o1, ActorInfo o2) {
                return (int) (o1.getId() - o2.getId());
            }
        });
        return list;
    }

    private ActorInfo getActorInfo(SmallActorMonitor mon) {
        final ActorRef actor = mon.actor;
        if (actor == null)
            return null;
        return new ActorInfo(mon.id,
                actor.getName(),
                LocalActor.getStrand(actor).isFiber(),
                mon.messages,
                LocalActor.getQueueLength(actor),
                (int) mon.restartCounter.get(),
                mon.deathCauses.toArray(new String[0]),
                getMailbox(actor),
                getStackTrace(actor));
    }

    private class SmallActorMonitor implements ActorMonitor {
        private final long id;
        private ActorRef actor;
        private int messageCounter;
        private int skippedMessageCounter;
        private final Counter restartCounter = new Counter();
        private final Queue<String> deathCauses = new ConcurrentLinkedQueue<>();
        // These hold counter values for the previous window
        volatile long messages;
        volatile long skippedMessages;

        public SmallActorMonitor(long id) {
            this.id = id;
        }

        void refresh() {
            if (registered) {
                final ActorRef a1 = actor;
                if (a1 != null)
                    collect(nanoTime() - lastCollectTime);

                reset();
            }
        }

        protected void collect(long intervalNanos) {
            messages = messageCounter;
        }

        protected void reset() {
            messageCounter = 0;

            lastCollectTime = nanoTime();
        }

        @Override
        public void setActor(ActorRef actor) {
            this.actor = actor;
        }

        @Override
        public void addDeath(Object cause) {
            if (cause == null)
                cause = "normal";
            while (deathCauses.size() > 20)
                deathCauses.poll();
            deathCauses.add(cause.toString());
        }

        @Override
        public void addRestart() {
            restartCounter.inc();
        }

        @Override
        public void addMessage() {
            messageCounter++;
        }

        @Override
        public void skippedMessage() {
            skippedMessageCounter++;
        }

        @Override
        public void resetSkippedMessages() {
            skippedMessageCounter = 0;
        }

        @Override
        public void shutdown() {
            watchedActors.remove(id);
        }
    }
}
TOP

Related Classes of co.paralleluniverse.actors.JMXActorsMonitor

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.