View Javadoc

1   /*
2    * Copyright The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements. See the NOTICE file distributed with this
6    * work for additional information regarding copyright ownership. The ASF
7    * licenses this file to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance with the License.
9    * 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, WITHOUT
15   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16   * License for the specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.hadoop.hbase.regionserver.metrics;
21  
22  import java.util.Map;
23  import java.util.Map.Entry;
24  import java.util.concurrent.ConcurrentHashMap;
25  import java.util.concurrent.ConcurrentMap;
26  import java.util.concurrent.atomic.AtomicInteger;
27  import java.util.concurrent.atomic.AtomicLong;
28  
29  import org.apache.hadoop.hbase.util.Pair;
30  
31  /**
32   * This class if for maintaining the maps used to power metrics for hfiles,
33   * regions, and regionservers. It has methods to mutate and get state of metrics
34   * numbers. These numbers are exposed to Hadoop metrics through
35   * RegionServerDynamicMetrics.
36   */
37  public class RegionMetricsStorage {
38  
39    // for simple numeric metrics (# of blocks read from block cache)
40    private static final ConcurrentMap<String, AtomicLong> numericMetrics =
41        new ConcurrentHashMap<String, AtomicLong>();
42  
43    // for simple numeric metrics (current block cache size)
44    // These ones are not reset to zero when queried, unlike the previous.
45    private static final ConcurrentMap<String, AtomicLong> numericPersistentMetrics =
46        new ConcurrentHashMap<String, AtomicLong>();
47  
48    /**
49     * Used for metrics where we want track a metrics (such as latency) over a
50     * number of operations.
51     */
52    private static final ConcurrentMap<String, Pair<AtomicLong, AtomicInteger>> timeVaryingMetrics =
53        new ConcurrentHashMap<String, Pair<AtomicLong, AtomicInteger>>();
54  
55    public static Map<String, AtomicLong> getNumericMetrics() {
56      return numericMetrics;
57    }
58  
59    public static Map<String, AtomicLong> getNumericPersistentMetrics() {
60      return numericPersistentMetrics;
61    }
62  
63    public static Map<String, Pair<AtomicLong, AtomicInteger>> getTimeVaryingMetrics() {
64      return timeVaryingMetrics;
65    }
66  
67    public static void incrNumericMetric(String key, long amount) {
68      AtomicLong oldVal = numericMetrics.get(key);
69      if (oldVal == null) {
70        oldVal = numericMetrics.putIfAbsent(key, new AtomicLong(amount));
71        if (oldVal == null)
72          return;
73      }
74      oldVal.addAndGet(amount);
75    }
76  
77    public static void incrTimeVaryingMetric(String key, long amount) {
78      Pair<AtomicLong, AtomicInteger> oldVal = timeVaryingMetrics.get(key);
79      if (oldVal == null) {
80        oldVal =
81            timeVaryingMetrics.putIfAbsent(key, 
82                new Pair<AtomicLong, AtomicInteger>(
83                    new AtomicLong(amount), 
84                    new AtomicInteger(1)));
85        if (oldVal == null)
86          return;
87      }
88      oldVal.getFirst().addAndGet(amount); // total time
89      oldVal.getSecond().incrementAndGet(); // increment ops by 1
90    }
91  
92    public static void setNumericPersistentMetric(String key, long amount) {
93      numericPersistentMetrics.put(key, new AtomicLong(amount));
94    }
95    public static void incrNumericPersistentMetric(String key, long amount) {
96      AtomicLong oldVal = numericPersistentMetrics.get(key);
97      if (oldVal == null) {
98        oldVal = numericPersistentMetrics.putIfAbsent(key, new AtomicLong(amount));
99        if (oldVal == null)
100         return;
101     }
102     oldVal.addAndGet(amount);
103   }
104 
105   public static void setNumericMetric(String key, long amount) {
106     numericMetrics.put(key, new AtomicLong(amount));
107   }
108 
109   public static long getNumericMetric(String key) {
110     AtomicLong m = numericMetrics.get(key);
111     if (m == null)
112       return 0;
113     return m.get();
114   }
115 
116   public static Pair<Long, Integer> getTimeVaryingMetric(String key) {
117     Pair<AtomicLong, AtomicInteger> pair = timeVaryingMetrics.get(key);
118     if (pair == null) {
119       return new Pair<Long, Integer>(0L, 0);
120     }
121 
122     return new Pair<Long, Integer>(pair.getFirst().get(), pair.getSecond().get());
123   }
124 
125   public static long getNumericPersistentMetric(String key) {
126     AtomicLong m = numericPersistentMetrics.get(key);
127     if (m == null)
128       return 0;
129     return m.get();
130   }
131 
132   /**
133    * Clear the timevarying and numeric metrics for all regions in this region server
134    * Clear the numericPersistentMerics for only the region being closed.
135    */
136   public static void clear(String regionEncodedName) {
137     timeVaryingMetrics.clear();
138     numericMetrics.clear();
139     for (Entry<String, AtomicLong> entry : RegionMetricsStorage.getNumericPersistentMetrics().entrySet()) {
140      if (entry.getKey().contains(regionEncodedName))
141      {
142        String keyName = entry.getKey();
143        numericPersistentMetrics.remove(keyName);
144      }
145     }
146   }
147 }