1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.hadoop.hbase.util;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.hadoop.hbase.classification.InterfaceAudience;
24  import org.apache.hadoop.hbase.Stoppable;
25  
26  
27  
28  
29  
30  
31  
32  @InterfaceAudience.Private
33  public class Sleeper {
34    private static final Log LOG = LogFactory.getLog(Sleeper.class);
35    private final int period;
36    private final Stoppable stopper;
37    private static final long MINIMAL_DELTA_FOR_LOGGING = 10000;
38  
39    private final Object sleepLock = new Object();
40    private boolean triggerWake = false;
41  
42    
43  
44  
45  
46  
47    public Sleeper(final int sleep, final Stoppable stopper) {
48      this.period = sleep;
49      this.stopper = stopper;
50    }
51  
52    
53  
54  
55    public void sleep() {
56      sleep(System.currentTimeMillis());
57    }
58  
59    
60  
61  
62  
63    public void skipSleepCycle() {
64      synchronized (sleepLock) {
65        triggerWake = true;
66        sleepLock.notifyAll();
67      }
68    }
69  
70    
71  
72  
73  
74  
75    public void sleep(final long startTime) {
76      if (this.stopper.isStopped()) {
77        return;
78      }
79      long now = System.currentTimeMillis();
80      long waitTime = this.period - (now - startTime);
81      if (waitTime > this.period) {
82        LOG.warn("Calculated wait time > " + this.period +
83          "; setting to this.period: " + System.currentTimeMillis() + ", " +
84          startTime);
85        waitTime = this.period;
86      }
87      while (waitTime > 0) {
88        long woke = -1;
89        try {
90          synchronized (sleepLock) {
91            if (triggerWake) break;
92            sleepLock.wait(waitTime);
93          }
94          woke = System.currentTimeMillis();
95          long slept = woke - now;
96          if (slept - this.period > MINIMAL_DELTA_FOR_LOGGING) {
97            LOG.warn("We slept " + slept + "ms instead of " + this.period +
98                "ms, this is likely due to a long " +
99                "garbage collecting pause and it's usually bad, see " +
100               "http://hbase.apache.org/book.html#trouble.rs.runtime.zkexpired");
101         }
102       } catch(InterruptedException iex) {
103         
104         
105         if (this.stopper.isStopped()) {
106           return;
107         }
108       }
109       
110       woke = (woke == -1)? System.currentTimeMillis(): woke;
111       waitTime = this.period - (woke - startTime);
112     }
113     synchronized(sleepLock) {
114       triggerWake = false;
115     }
116   }
117   
118   
119 
120 
121   public final int getPeriod() {
122     return period;
123   }
124 }