001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.hbase.regionserver; 020 021import java.util.concurrent.atomic.AtomicBoolean; 022 023import org.apache.hadoop.hbase.TableName; 024import org.apache.hadoop.hbase.metrics.Interns; 025import org.apache.hadoop.metrics2.MetricsRecordBuilder; 026import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry; 027import org.apache.yetus.audience.InterfaceAudience; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031@InterfaceAudience.Private 032public class MetricsTableSourceImpl implements MetricsTableSource { 033 034 private static final Logger LOG = LoggerFactory.getLogger(MetricsTableSourceImpl.class); 035 036 private AtomicBoolean closed = new AtomicBoolean(false); 037 038 // Non-final so that we can null out the wrapper 039 // This is just paranoia. We really really don't want to 040 // leak a whole table by way of keeping the 041 // tableWrapper around too long. 042 private MetricsTableWrapperAggregate tableWrapperAgg; 043 private final MetricsTableAggregateSourceImpl agg; 044 private final DynamicMetricsRegistry registry; 045 private final String tableNamePrefix; 046 private final TableName tableName; 047 private final int hashCode; 048 049 public MetricsTableSourceImpl(String tblName, 050 MetricsTableAggregateSourceImpl aggregate, MetricsTableWrapperAggregate tblWrapperAgg) { 051 LOG.debug("Creating new MetricsTableSourceImpl for table "); 052 this.tableName = TableName.valueOf(tblName); 053 this.agg = aggregate; 054 agg.register(tblName, this); 055 this.tableWrapperAgg = tblWrapperAgg; 056 this.registry = agg.getMetricsRegistry(); 057 this.tableNamePrefix = "Namespace_" + this.tableName.getNamespaceAsString() + 058 "_table_" + this.tableName.getQualifierAsString() + "_metric_"; 059 this.hashCode = this.tableName.hashCode(); 060 } 061 062 @Override 063 public void close() { 064 boolean wasClosed = closed.getAndSet(true); 065 066 // Has someone else already closed this for us? 067 if (wasClosed) { 068 return; 069 } 070 071 // Before removing the metrics remove this table from the aggregate table bean. 072 // This should mean that it's unlikely that snapshot and close happen at the same time. 073 agg.deregister(tableName.getNameAsString()); 074 075 // While it's un-likely that snapshot and close happen at the same time it's still possible. 076 // So grab the lock to ensure that all calls to snapshot are done before we remove the metrics 077 synchronized (this) { 078 if (LOG.isTraceEnabled()) { 079 LOG.trace("Removing table Metrics for table "); 080 } 081 tableWrapperAgg = null; 082 } 083 } 084 @Override 085 public MetricsTableAggregateSource getAggregateSource() { 086 return agg; 087 } 088 089 @Override 090 public int compareTo(MetricsTableSource source) { 091 if (!(source instanceof MetricsTableSourceImpl)) { 092 return -1; 093 } 094 095 MetricsTableSourceImpl impl = (MetricsTableSourceImpl) source; 096 if (impl == null) { 097 return -1; 098 } 099 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) { 160 return true; 161 } 162 163 if (o == null || getClass() != o.getClass()) { 164 return false; 165 } 166 167 return (compareTo((MetricsTableSourceImpl) o) == 0); 168 } 169 170 public MetricsTableWrapperAggregate getTableWrapper() { 171 return tableWrapperAgg; 172 } 173 174 public String getTableNamePrefix() { 175 return tableNamePrefix; 176 } 177}