Coverage Report - org.mule.management.stats.ProcessingTime
 
Classes in this File Line Coverage Branch Coverage Complexity
ProcessingTime
0%
0/36
0%
0/18
0
ProcessingTime$1
0%
0/18
0%
0/4
0
ProcessingTime$Reference
0%
0/6
N/A
0
 
 1  
 /*
 2  
  * $Id: ProcessingTime.java 20593 2010-12-10 03:56:00Z mike.schilling $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.management.stats;
 12  
 
 13  
 import org.mule.api.MuleContext;
 14  
 import org.mule.api.MuleSession;
 15  
 import org.mule.api.construct.FlowConstruct;
 16  
 import org.mule.util.concurrent.ThreadNameHelper;
 17  
 
 18  
 import java.io.Serializable;
 19  
 import java.lang.ref.ReferenceQueue;
 20  
 import java.lang.ref.WeakReference;
 21  
 import java.util.Map;
 22  
 
 23  
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
 24  
 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicLong;
 25  
 import org.apache.commons.logging.Log;
 26  
 import org.apache.commons.logging.LogFactory;
 27  
 
 28  
 /**
 29  
  * Accumulates the processing time for all branches of a flow
 30  
  */
 31  0
 public class ProcessingTime implements Serializable
 32  
 {
 33  
     /**
 34  
      * Serial version
 35  
      */
 36  
     private static final long serialVersionUID = 1L;
 37  
 
 38  0
     private static final Log logger = LogFactory.getLog(ProcessingTime.class);
 39  
     private static volatile Thread referenceThread;
 40  0
     private static ReferenceQueue<ProcessingTime> queue = new ReferenceQueue<ProcessingTime>();
 41  0
     private static Map refs = new ConcurrentHashMap();
 42  
 
 43  0
     private AtomicLong accumulator = new AtomicLong();
 44  
     private FlowConstructStatistics statistics;
 45  
     private String threadName;
 46  
 
 47  
     /**
 48  
      * Create a ProcessingTime for the specified MuleSession.
 49  
      * @return ProcessingTime if the session has an enabled FlowConstructStatistics or null otherwise
 50  
      */
 51  
     public static ProcessingTime newInstance(MuleSession session, MuleContext muleContext)
 52  
     {
 53  0
         if (session != null)
 54  
         {
 55  0
             FlowConstruct fc = session.getFlowConstruct();
 56  0
             if (fc != null)
 57  
             {
 58  0
                 FlowConstructStatistics stats = fc.getStatistics();
 59  0
                 if (stats != null && fc.getStatistics().isEnabled())
 60  
                 {
 61  0
                     return new ProcessingTime(stats, muleContext);
 62  
                 }
 63  
             }
 64  
 
 65  
         }
 66  
 
 67  0
         return null;
 68  
     }
 69  
 
 70  
     /**
 71  
      * Create a Processing Time
 72  
      * @param stats never null
 73  
      * @param muleContext
 74  
      */
 75  
     private ProcessingTime(FlowConstructStatistics stats, MuleContext muleContext)
 76  0
     {
 77  0
         this.statistics = stats;
 78  0
         this.threadName = String.format("%sprocessing.time.monitor", ThreadNameHelper.getPrefix(muleContext));
 79  0
         if (referenceThread == null)
 80  
         {
 81  0
             startThread();
 82  
         }
 83  0
         refs.put(new Reference(this), refs);
 84  0
     }
 85  
 
 86  
     /**
 87  
      * Add the execution time for this branch to the flow construct's statistics
 88  
      * @param startTime  time this branch started
 89  
      */
 90  
     public void addFlowExecutionBranchTime(long startTime)
 91  
     {
 92  0
         if (statistics.isEnabled())
 93  
         {
 94  0
             long elapsedTime = getEffectiveTime(System.currentTimeMillis() - startTime);
 95  0
             statistics.addFlowExecutionBranchTime(elapsedTime, accumulator.addAndGet(elapsedTime));
 96  
         }
 97  0
     }
 98  
 
 99  
     /**
 100  
      * Convert processing time to effective processing time.  If processing took less than a tick, we consider
 101  
      * it to have been one millisecond
 102  
      */
 103  
     public static long getEffectiveTime(long time)
 104  
     {
 105  0
         return (time <= 0) ? 1L : time;
 106  
     }
 107  
 
 108  
     /**
 109  
      * Start timer that processes reference queue
 110  
      */
 111  
     public void startThread()
 112  
     {
 113  0
         synchronized (ProcessingTime.class)
 114  
         {
 115  0
             if (referenceThread == null)
 116  
             {
 117  0
                 referenceThread = new Thread(new Runnable()
 118  0
                 {
 119  
                     /**
 120  
                      * As weak references to completed ProcessingTimes are delivered, record them
 121  
                      */
 122  
                     public void run()
 123  
                     {
 124  
 
 125  
                         try
 126  
                         {
 127  
                             while (true)
 128  
                             {
 129  0
                                 if (Thread.currentThread() != referenceThread)
 130  
                                 {
 131  0
                                     break;
 132  
                                 }
 133  
                                 try
 134  
                                 {
 135  
                                     // The next two lines look silly, but
 136  
                                     //       ref = (Reference) queue.poll();
 137  
                                     // fails on the IBM 1.5 compiler
 138  0
                                     Object temp = queue.remove();
 139  0
                                     Reference ref = (Reference) temp;
 140  0
                                     refs.remove(ref);
 141  0
                                     FlowConstructStatistics stats = ref.getStatistics();
 142  0
                                     if (stats.isEnabled())
 143  
                                     {
 144  0
                                         stats.addCompleteFlowExecutionTime(ref.getAccumulator().longValue());
 145  
                                     }
 146  
                                 }
 147  0
                                 catch (InterruptedException ex )
 148  
                                 {
 149  0
                                     Thread.currentThread().interrupt();
 150  0
                                     break;
 151  
                                 }
 152  0
                                 catch (Exception ex)
 153  
                                 {
 154  
                                     // Don't let exception escape -- it kills the thread
 155  0
                                     logger.error(this, ex);
 156  0
                                 }
 157  
                             }
 158  
                         }
 159  
                         finally
 160  
                         {
 161  0
                             referenceThread = null;
 162  0
                         }
 163  0
                     }
 164  
                 }, this.threadName);
 165  0
                 referenceThread.setDaemon(true);
 166  0
                 referenceThread.start();
 167  
             }
 168  0
         }
 169  0
     }
 170  
 
 171  
     /**
 172  
      * Stop timer that processes reference queue
 173  
      */
 174  
     public synchronized static void stopTimer()
 175  
     {
 176  0
         if (referenceThread != null)
 177  
         {
 178  0
             referenceThread.interrupt();
 179  0
             referenceThread = null;
 180  
         }
 181  0
         refs.clear();
 182  0
     }
 183  
 
 184  
     /**
 185  
      * Weak reference that includes flow statistics to be updated
 186  
      */
 187  
     static class Reference extends WeakReference<ProcessingTime>
 188  
     {
 189  
         private FlowConstructStatistics statistics;
 190  
         private AtomicLong accumulator;
 191  
 
 192  
         Reference(ProcessingTime time)
 193  
         {
 194  0
             super(time, queue);
 195  0
             this.statistics = time.statistics;
 196  0
             this.accumulator = time.accumulator;
 197  0
         }
 198  
 
 199  
         public AtomicLong getAccumulator()
 200  
         {
 201  0
             return accumulator;
 202  
         }
 203  
 
 204  
         public FlowConstructStatistics getStatistics()
 205  
         {
 206  0
             return statistics;
 207  
         }
 208  
     }
 209  
 }