View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.regionserver;
20  
21  import java.lang.management.ManagementFactory;
22  import java.lang.management.MemoryUsage;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.hbase.classification.InterfaceAudience;
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.Chore;
29  import org.apache.hadoop.hbase.HConstants;
30  import org.apache.hadoop.hbase.Server;
31  import org.apache.hadoop.hbase.util.Threads;
32  
33  import com.google.common.annotations.VisibleForTesting;
34  
35  /**
36   * Manages heap memory related tasks.
37   */
38  @InterfaceAudience.Private
39  public class HeapMemoryManager {
40    private static final Log LOG = LogFactory.getLog(HeapMemoryManager.class);
41  
42    // keep the same period tunable as branch-1 and higher for compatibility
43    public static final String HBASE_RS_HEAP_MEMORY_TUNER_PERIOD = 
44        "hbase.regionserver.heapmemory.tuner.period";
45    public static final int HBASE_RS_HEAP_MEMORY_TUNER_DEFAULT_PERIOD = 60 * 1000;
46  
47    private float heapOccupancyPercent;
48  
49    private Server server;
50    private HeapMemoryChore heapMemChore = null;
51    private final int defaultChorePeriod;
52    private final float heapOccupancyLowWatermark;
53  
54    public static HeapMemoryManager create(Server server) {
55      return new HeapMemoryManager(server);
56    }
57  
58    @VisibleForTesting
59    HeapMemoryManager(Server server) {
60      Configuration conf = server.getConfiguration();
61      this.server = server;
62      this.defaultChorePeriod = conf.getInt(HBASE_RS_HEAP_MEMORY_TUNER_PERIOD,
63        HBASE_RS_HEAP_MEMORY_TUNER_DEFAULT_PERIOD);
64      this.heapOccupancyLowWatermark = conf.getFloat(HConstants.HEAP_OCCUPANCY_LOW_WATERMARK_KEY,
65        HConstants.DEFAULT_HEAP_OCCUPANCY_LOW_WATERMARK);
66    }
67  
68    public void start() {
69      this.heapMemChore = new HeapMemoryChore();
70      Threads.setDaemonThreadRunning(heapMemChore.getThread());
71    }
72  
73    public void stop() {
74      // The thread is Daemon. Just interrupting the ongoing process.
75      this.heapMemChore.interrupt();
76    }
77  
78    /**
79     * @return heap occupancy percentage, 0 <= n <= 1
80     */
81    public float getHeapOccupancyPercent() {
82      return this.heapOccupancyPercent;
83    }
84  
85    private class HeapMemoryChore extends Chore {
86      private boolean alarming = false;
87  
88      public HeapMemoryChore() {
89        super(server.getServerName() + "-HeapMemoryChore", defaultChorePeriod, server);
90      }
91  
92      @Override
93      protected void sleep() {
94        if (!alarming) {
95          super.sleep();
96        } else {
97          // we are in the alarm state, so sleep only for a short fixed period
98          try {
99            Thread.sleep(1000);
100         } catch (InterruptedException e) {
101           // Interrupted, propagate
102           Thread.currentThread().interrupt();
103         }
104       }
105     }
106 
107     @Override
108     protected void chore() {
109       // Sample heap occupancy
110       MemoryUsage memUsage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
111       heapOccupancyPercent = (float)memUsage.getUsed() / (float)memUsage.getCommitted();
112       // If we are above the heap occupancy alarm low watermark, sound the alarm
113       if (heapOccupancyPercent >= heapOccupancyLowWatermark) {
114         if (!alarming) {
115           LOG.warn("heapOccupancyPercent " + heapOccupancyPercent +
116             " is above heap occupancy alarm watermark (" + heapOccupancyLowWatermark + ")");
117           alarming = true;
118         }
119       } else {
120         if (alarming) {
121           LOG.info("heapOccupancyPercent " + heapOccupancyPercent +
122             " is now below the heap occupancy alarm watermark (" +
123             heapOccupancyLowWatermark + ")");
124           alarming = false;
125         }
126       }
127     }
128   }
129 }