View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.management.stats;
8   
9   import org.mule.api.MuleContext;
10  import org.mule.api.MuleException;
11  import org.mule.api.context.MuleContextAware;
12  import org.mule.util.concurrent.ThreadNameHelper;
13  
14  import java.lang.ref.ReferenceQueue;
15  import java.lang.ref.WeakReference;
16  import java.util.Map;
17  import java.util.concurrent.ConcurrentHashMap;
18  import java.util.concurrent.atomic.AtomicLong;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  
23  public class DefaultProcessingTimeWatcher implements ProcessingTimeWatcher, MuleContextAware
24  {
25  
26      private static final Log logger = LogFactory.getLog(DefaultProcessingTimeWatcher.class);
27  
28      private final ReferenceQueue<ProcessingTime> queue = new ReferenceQueue<ProcessingTime>();
29      private final Map<ProcessingTimeReference, Object> refs = new ConcurrentHashMap<ProcessingTimeReference, Object>();
30      private Thread watcherThread;
31      private MuleContext muleContext;
32  
33      public void addProcessingTime(ProcessingTime processingTime)
34      {
35          refs.put(new ProcessingTimeReference(processingTime, queue), refs);
36      }
37  
38      public void start() throws MuleException
39      {
40          String threadName = String.format("%sprocessing.time.monitor", ThreadNameHelper.getPrefix(muleContext));
41          watcherThread = new Thread(new ProcessingTimeChecker(), threadName);
42          watcherThread.setDaemon(true);
43          watcherThread.start();
44      }
45  
46      public void stop() throws MuleException
47      {
48          if (watcherThread != null)
49          {
50              watcherThread.interrupt();
51          }
52          refs.clear();
53      }
54  
55      public void setMuleContext(MuleContext muleContext)
56      {
57          this.muleContext = muleContext;
58      }
59  
60      private class ProcessingTimeChecker implements Runnable
61      {
62  
63          /**
64           * As weak references to completed ProcessingTimes are delivered, record them
65           */
66          public void run()
67          {
68              while (true)
69              {
70                  try
71                  {
72                      // The next two lines look silly, but ref = (ProcessingTimeReference) queue.poll();
73                      // fails on the IBM 1.5 compiler
74                      Object temp = queue.remove();
75                      ProcessingTimeReference ref = (ProcessingTimeReference) temp;
76                      refs.remove(ref);
77  
78                      FlowConstructStatistics stats = ref.getStatistics();
79                      if (stats.isEnabled())
80                      {
81                          stats.addCompleteFlowExecutionTime(ref.getAccumulator().longValue());
82                      }
83                  }
84                  catch (InterruptedException ex)
85                  {
86                      Thread.currentThread().interrupt();
87                      break;
88                  }
89                  catch (Exception ex)
90                  {
91                      // Don't let exception escape -- it kills the thread
92                      logger.error(this, ex);
93                  }
94              }
95          }
96      }
97  
98      /**
99       * Weak reference that includes flow statistics to be updated
100      */
101     static class ProcessingTimeReference extends WeakReference<ProcessingTime>
102     {
103 
104         private FlowConstructStatistics statistics;
105         private AtomicLong accumulator;
106 
107         ProcessingTimeReference(ProcessingTime time, ReferenceQueue<ProcessingTime> queue)
108         {
109             super(time, queue);
110             this.statistics = time.getStatistics();
111             this.accumulator = time.getAccumulator();
112         }
113 
114         public AtomicLong getAccumulator()
115         {
116             return accumulator;
117         }
118 
119         public FlowConstructStatistics getStatistics()
120         {
121             return statistics;
122         }
123     }
124 }