View Javadoc
1   /*
2    * Copyright 2014 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.handler.traffic;
17  
18  import io.netty.handler.traffic.GlobalChannelTrafficShapingHandler.PerChannel;
19  
20  import java.util.concurrent.ScheduledExecutorService;
21  import java.util.concurrent.TimeUnit;
22  
23  /**
24   * Version for {@link GlobalChannelTrafficShapingHandler}.
25   * This TrafficCounter is the Global one, and its special property is to directly handle
26   * other channel's TrafficCounters. In particular, there are no scheduler for those
27   * channel's TrafficCounters because it is managed by this one.
28   */
29  public class GlobalChannelTrafficCounter extends TrafficCounter {
30      /**
31       * @param trafficShapingHandler the associated {@link GlobalChannelTrafficShapingHandler}.
32       * @param executor the underlying executor service for scheduling checks (both Global and per Channel).
33       * @param name the name given to this monitor.
34       * @param checkInterval the checkInterval in millisecond between two computations.
35       */
36      public GlobalChannelTrafficCounter(GlobalChannelTrafficShapingHandler trafficShapingHandler,
37              ScheduledExecutorService executor, String name, long checkInterval) {
38          super(trafficShapingHandler, executor, name, checkInterval);
39          if (executor == null) {
40              throw new IllegalArgumentException("Executor must not be null");
41          }
42      }
43  
44      /**
45       * Class to implement monitoring at fix delay.
46       * This version is Mixed in the way it mixes Global and Channel counters.
47       */
48      private static class MixedTrafficMonitoringTask implements Runnable {
49          /**
50           * The associated TrafficShapingHandler
51           */
52          private final GlobalChannelTrafficShapingHandler trafficShapingHandler1;
53  
54          /**
55           * The associated TrafficCounter
56           */
57          private final TrafficCounter counter;
58  
59          /**
60           * @param trafficShapingHandler The parent handler to which this task needs to callback to for accounting.
61           * @param counter The parent TrafficCounter that we need to reset the statistics for.
62           */
63          MixedTrafficMonitoringTask(
64                  GlobalChannelTrafficShapingHandler trafficShapingHandler,
65                  TrafficCounter counter) {
66              trafficShapingHandler1 = trafficShapingHandler;
67              this.counter = counter;
68          }
69  
70          @Override
71          public void run() {
72              if (!counter.monitorActive) {
73                  return;
74              }
75              long newLastTime = milliSecondFromNano();
76              counter.resetAccounting(newLastTime);
77              for (PerChannel perChannel : trafficShapingHandler1.channelQueues.values()) {
78                  perChannel.channelTrafficCounter.resetAccounting(newLastTime);
79              }
80              trafficShapingHandler1.doAccounting(counter);
81              counter.scheduledFuture = counter.executor.schedule(this, counter.checkInterval.get(),
82                                                                  TimeUnit.MILLISECONDS);
83          }
84      }
85  
86      /**
87       * Start the monitoring process.
88       */
89      @Override
90      public synchronized void start() {
91          if (monitorActive) {
92              return;
93          }
94          lastTime.set(milliSecondFromNano());
95          long localCheckInterval = checkInterval.get();
96          if (localCheckInterval > 0) {
97              monitorActive = true;
98              monitor = new MixedTrafficMonitoringTask((GlobalChannelTrafficShapingHandler) trafficShapingHandler, this);
99              scheduledFuture =
100                 executor.schedule(monitor, localCheckInterval, TimeUnit.MILLISECONDS);
101         }
102     }
103 
104     /**
105      * Stop the monitoring process.
106      */
107     @Override
108     public synchronized void stop() {
109         if (!monitorActive) {
110             return;
111         }
112         monitorActive = false;
113         resetAccounting(milliSecondFromNano());
114         trafficShapingHandler.doAccounting(this);
115         if (scheduledFuture != null) {
116             scheduledFuture.cancel(true);
117         }
118     }
119 
120     @Override
121     public void resetCumulativeTime() {
122         for (PerChannel perChannel :
123             ((GlobalChannelTrafficShapingHandler) trafficShapingHandler).channelQueues.values()) {
124             perChannel.channelTrafficCounter.resetCumulativeTime();
125         }
126         super.resetCumulativeTime();
127     }
128 
129 }