View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.regionserver;
20  
21  import java.util.concurrent.atomic.AtomicBoolean;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.hbase.TableName;
26  import org.apache.hadoop.hbase.classification.InterfaceAudience;
27  import org.apache.hadoop.hbase.metrics.Interns;
28  import org.apache.hadoop.metrics2.MetricsRecordBuilder;
29  import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry;
30  
31  @InterfaceAudience.Private
32  public class MetricsTableSourceImpl implements MetricsTableSource {
33  
34    private static final Log LOG = LogFactory.getLog(MetricsTableSourceImpl.class);
35  
36    private AtomicBoolean closed = new AtomicBoolean(false);
37  
38    // Non-final so that we can null out the wrapper
39    // This is just paranoia. We really really don't want to
40    // leak a whole table by way of keeping the
41    // tableWrapper around too long.
42    private MetricsTableWrapperAggregate tableWrapperAgg;
43    private final MetricsTableAggregateSourceImpl agg;
44    private final DynamicMetricsRegistry registry;
45    private final String tableNamePrefix;
46    private final TableName tableName;
47    private final int hashCode;
48  
49    public MetricsTableSourceImpl(String tblName,
50        MetricsTableAggregateSourceImpl aggregate, MetricsTableWrapperAggregate tblWrapperAgg) {
51      LOG.debug("Creating new MetricsTableSourceImpl for table ");
52      this.tableName = TableName.valueOf(tblName);
53      this.agg = aggregate;
54      agg.register(tblName, this);
55      this.tableWrapperAgg = tblWrapperAgg;
56      this.registry = agg.getMetricsRegistry();
57      this.tableNamePrefix = "Namespace_" + this.tableName.getNamespaceAsString() +
58          "_table_" + this.tableName.getQualifierAsString() + "_metric_";
59      this.hashCode = this.tableName.hashCode();
60    }
61  
62    @Override
63    public void close() {
64      boolean wasClosed = closed.getAndSet(true);
65  
66      // Has someone else already closed this for us?
67      if (wasClosed) {
68        return;
69      }
70  
71      // Before removing the metrics remove this table from the aggregate table bean.
72      // This should mean that it's unlikely that snapshot and close happen at the same time.
73      agg.deregister(tableName.getNameAsString());
74  
75      // While it's un-likely that snapshot and close happen at the same time it's still possible.
76      // So grab the lock to ensure that all calls to snapshot are done before we remove the metrics
77      synchronized (this) {
78        if (LOG.isTraceEnabled()) {
79          LOG.trace("Removing table Metrics for table ");
80        }
81        tableWrapperAgg = null;
82      }
83    }
84    @Override
85    public MetricsTableAggregateSource getAggregateSource() {
86      return agg;
87    }
88  
89    @Override
90    public int compareTo(MetricsTableSource source) {
91      if (!(source instanceof MetricsTableSourceImpl)) {
92        return -1;
93      }
94  
95      MetricsTableSourceImpl impl = (MetricsTableSourceImpl) source;
96      if (impl == null) {
97        return -1;
98      }
99  
100     return Long.compare(hashCode, impl.hashCode);
101   }
102 
103   void snapshot(MetricsRecordBuilder mrb, boolean ignored) {
104 
105     // If there is a close that started be double extra sure
106     // that we're not getting any locks and not putting data
107     // into the metrics that should be removed. So early out
108     // before even getting the lock.
109     if (closed.get()) {
110       return;
111     }
112 
113     // Grab the read
114     // This ensures that removes of the metrics
115     // can't happen while we are putting them back in.
116     synchronized (this) {
117 
118       // It's possible that a close happened between checking
119       // the closed variable and getting the lock.
120       if (closed.get()) {
121         return;
122       }
123 
124       if (this.tableWrapperAgg != null) {
125         mrb.addCounter(Interns.info(tableNamePrefix + MetricsTableSource.READ_REQUEST_COUNT,
126           MetricsTableSource.READ_REQUEST_COUNT_DESC),
127           tableWrapperAgg.getReadRequestsCount(tableName.getNameAsString()));
128         mrb.addCounter(Interns.info(tableNamePrefix + MetricsTableSource.WRITE_REQUEST_COUNT,
129           MetricsTableSource.WRITE_REQUEST_COUNT_DESC),
130           tableWrapperAgg.getWriteRequestsCount(tableName.getNameAsString()));
131         mrb.addCounter(Interns.info(tableNamePrefix + MetricsTableSource.TOTAL_REQUEST_COUNT,
132           MetricsTableSource.TOTAL_REQUEST_COUNT_DESC),
133           tableWrapperAgg.getTotalRequestsCount(tableName.getNameAsString()));
134         mrb.addGauge(Interns.info(tableNamePrefix + MetricsTableSource.MEMSTORE_SIZE,
135           MetricsTableSource.MEMSTORE_SIZE_DESC),
136           tableWrapperAgg.getMemstoresSize(tableName.getNameAsString()));
137         mrb.addGauge(Interns.info(tableNamePrefix + MetricsTableSource.STORE_FILE_SIZE,
138           MetricsTableSource.STORE_FILE_SIZE_DESC),
139           tableWrapperAgg.getStoreFilesSize(tableName.getNameAsString()));
140         mrb.addGauge(Interns.info(tableNamePrefix + MetricsTableSource.TABLE_SIZE,
141           MetricsTableSource.TABLE_SIZE_DESC),
142           tableWrapperAgg.getTableSize(tableName.getNameAsString()));
143         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.AVERAGE_REGION_SIZE,
144           MetricsRegionServerSource.AVERAGE_REGION_SIZE_DESC),
145           tableWrapperAgg.getAvgRegionSize(tableName.getNameAsString()));
146         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.REGION_COUNT,
147           MetricsRegionServerSource.REGION_COUNT_DESC),
148           tableWrapperAgg.getNumRegions(tableName.getNameAsString()));
149       }
150     }
151   }
152 
153   @Override
154   public String getTableName() {
155     return tableName.getNameAsString();
156   }
157 
158   @Override
159   public int hashCode() {
160     return hashCode;
161   }
162 
163   @Override
164   public boolean equals(Object o) {
165     if (this == o) return true;
166     if (o == null || getClass() != o.getClass()) return false;
167     return (o instanceof MetricsTableSourceImpl && compareTo((MetricsTableSourceImpl) o) == 0);
168   }
169 
170   public MetricsTableWrapperAggregate getTableWrapper() {
171     return tableWrapperAgg;
172   }
173 
174   public String getTableNamePrefix() {
175     return tableNamePrefix;
176   }
177 }