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       }
144     }
145   }
146 
147   @Override
148   public String getTableName() {
149     return tableName.getNameAsString();
150   }
151 
152   @Override
153   public int hashCode() {
154     return hashCode;
155   }
156 
157   @Override
158   public boolean equals(Object o) {
159     if (this == o) return true;
160     if (o == null || getClass() != o.getClass()) return false;
161     return (o instanceof MetricsTableSourceImpl && compareTo((MetricsTableSourceImpl) o) == 0);
162   }
163 
164   public MetricsTableWrapperAggregate getTableWrapper() {
165     return tableWrapperAgg;
166   }
167 
168   public String getTableNamePrefix() {
169     return tableNamePrefix;
170   }
171 }