001    package org.shiftone.jrat.provider.tree;
002    
003    
004    import org.shiftone.jrat.core.MethodKey;
005    import org.shiftone.jrat.core.spi.AbstractMethodHandlerFactory;
006    import org.shiftone.jrat.core.spi.MethodHandler;
007    import org.shiftone.jrat.core.spi.RuntimeContext;
008    import org.shiftone.jrat.provider.tree.command.DumpOutputCommandlet;
009    import org.shiftone.jrat.provider.tree.command.ResetCommandlet;
010    import org.shiftone.jrat.provider.tree.command.WriteOutputCommandlet;
011    import org.shiftone.jrat.provider.tree.ui.TraceViewBuilder;
012    import org.shiftone.jrat.util.AtomicLong;
013    import org.shiftone.jrat.util.log.Logger;
014    
015    import java.util.HashSet;
016    import java.util.Set;
017    
018    
019    /**
020     * Class TreeMethodHandlerFactory
021     *
022     * @author jeff@shiftone.org (Jeff Drost)
023     */
024    public class TreeMethodHandlerFactory extends AbstractMethodHandlerFactory implements TreeMethodHandlerFactoryMBean {
025    
026        private static final Logger LOG = Logger.getLogger(TreeMethodHandlerFactory.class);
027        private final TreeNode rootNode = new TreeNode();
028        private final Set allMethodKeys = new HashSet();
029        private final DelegateThreadLocal delegateThreadLocal = new DelegateThreadLocal(this);
030        private final AtomicLong methodHandlerCount = new AtomicLong();
031    
032        public void startup(RuntimeContext context) throws Exception {
033            super.startup(context);
034            context.registerMBean(this);
035            context.register(new ResetCommandlet(this));
036            context.register(new WriteOutputCommandlet(this));
037            context.register(new DumpOutputCommandlet(this));
038        }
039    
040    
041        public synchronized final MethodHandler createMethodHandler(MethodKey methodKey) {
042    
043    
044            methodHandlerCount.incrementAndGet();
045            allMethodKeys.add(methodKey);
046    
047            return new TreeMethodHandler(this, methodKey);
048        }
049    
050    
051        public long getMethodHandlerCount() {
052            return methodHandlerCount.get();
053        }
054    
055    
056        /**
057         * Returns the current thread's delegate instance. This delegate will
058         * operate on this factory's call tree data structure when events are
059         * processed.
060         */
061        public final Delegate getDelegate() {
062            return (Delegate) delegateThreadLocal.get();
063        }
064    
065    
066        public final TreeNode getRootNode() {
067            return rootNode;
068        }
069    
070    
071        public synchronized void writeOutputFile() {
072            writeOutputFile(getOutputFile());
073        }
074    
075        public synchronized void reset() {
076            rootNode.reset();
077        }
078    
079        public synchronized void writeOutputFile(String fileName) {
080    
081            LOG.info("writeOutputFile...");
082    
083            getContext().writeSerializable(fileName,
084                    new TraceViewBuilder(
085                            rootNode,
086                            new HashSet(allMethodKeys), // copy to avoid sync issues
087                            getContext().getStartTimeMs(),
088                            System.currentTimeMillis(),
089                            getContext().getSystemPropertiesAtStartup(),
090                            getContext().getHostName(),
091                            getContext().getHostAddress()
092                    )
093            );
094    
095        }
096    
097    
098        public synchronized void shutdown() {
099    
100            LOG.info("shutdown...");
101            writeOutputFile();
102            LOG.info("shutdown complete");
103        }
104    
105    
106        public String toString() {
107            return "Tree Handler Factory";
108        }
109    }