package com.linkedin.databus.bootstrap.common; /* * * Copyright 2013 LinkedIn Corp. All rights reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ import java.util.HashMap; import java.util.Hashtable; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import javax.management.MBeanServer; import javax.management.ObjectName; import org.apache.log4j.Logger; import com.linkedin.databus.bootstrap.monitoring.server.mbean.DbusBootstrapHttpStats; import com.linkedin.databus.bootstrap.monitoring.server.mbean.DbusBootstrapHttpStatsMBean; import com.linkedin.databus.core.Checkpoint; import com.linkedin.databus.core.monitoring.mbean.AbstractMonitoringMBean; import com.linkedin.databus.core.util.ReadWriteSyncedObject; public class BootstrapHttpStatsCollector extends ReadWriteSyncedObject implements BootstrapHttpStatsCollectorMBean { private final static String NO_PEER = "NONE"; public static final String MODULE = BootstrapHttpStatsCollector.class.getName(); public static final Logger LOG = Logger.getLogger(MODULE); private final DbusBootstrapHttpStats _totalStats; private final HashMap<String, DbusBootstrapHttpStats> _perClientStats; private final MBeanServer _mbeanServer; private final ObjectName _collectorObjName; private final int _id; private final String _name; private final String _perPeerPrefix; private final String _curPeer; private final AtomicBoolean _enabled; public BootstrapHttpStatsCollector(int id, String name, boolean enabled, boolean threadSafe, MBeanServer mbeanServer) { this(id, name, enabled, threadSafe, NO_PEER, mbeanServer); } public BootstrapHttpStatsCollector( int id, String name, boolean enabled, boolean threadSafe, String peer, MBeanServer mbeanServer) { super(threadSafe); _mbeanServer = mbeanServer; _curPeer = peer; _enabled = new AtomicBoolean(enabled); _id = id; _name = name; _perPeerPrefix = _name + ".peer."; _totalStats = new DbusBootstrapHttpStats(_id, _name + ".total", enabled, threadSafe, null); _perClientStats = new HashMap<String, DbusBootstrapHttpStats>(1000); ObjectName jmxName = null; try { Hashtable<String, String> mbeanProps = new Hashtable<String, String>(5); mbeanProps.put("name", _name); mbeanProps.put("type", BootstrapHttpStatsCollector.class.getSimpleName()); mbeanProps.put("bootstrap", Integer.toString(id)); jmxName = new ObjectName(AbstractMonitoringMBean.JMX_DOMAIN, mbeanProps); } catch (Exception e) { LOG.error("Error creating JMX object name", e); } _collectorObjName = jmxName; registerAsMBeans(); } private DbusBootstrapHttpStats getOrAddPerPeerCollector(String client, Lock writeLock) { Lock myWriteLock = null; if (null == writeLock) myWriteLock = acquireWriteLock(); try { DbusBootstrapHttpStats clientStats = _perClientStats.get(client); if (null == clientStats) { clientStats = new DbusBootstrapHttpStats(_id, _perPeerPrefix + client, true, isThreadSafe(), null); _perClientStats.put(client, clientStats); if (null != _mbeanServer) { clientStats.registerAsMbean(_mbeanServer); } } return clientStats; } finally { releaseLock(myWriteLock); } } public void merge(BootstrapHttpStatsCollector other) { _totalStats.mergeStats(other._totalStats); Lock otherReadLock = other.acquireReadLock(); Lock writeLock = acquireWriteLock(otherReadLock); try { for (String peerName: other._perClientStats.keySet()) { DbusBootstrapHttpStats bean = other._perClientStats.get(peerName); mergePerPeer(peerName, bean, writeLock); } } finally { releaseLock(writeLock); releaseLock(otherReadLock); } } private void mergePerPeer(String peer, DbusBootstrapHttpStats other, Lock writeLock) { DbusBootstrapHttpStats curBean = getOrAddPerPeerCollector(peer, writeLock); curBean.mergeStats(other); } protected void registerAsMBeans() { if (null != _mbeanServer && null != _collectorObjName) { try { if (_mbeanServer.isRegistered(_collectorObjName)) { LOG.warn("unregistering stale mbean: " + _collectorObjName); _mbeanServer.unregisterMBean(_collectorObjName); } _totalStats.registerAsMbean(_mbeanServer); _mbeanServer.registerMBean(this, _collectorObjName); LOG.info("MBean registered " + _collectorObjName); } catch (Exception e) { LOG.error("JMX registration failed", e); } } } public void unregisterMBeans() { if (null != _mbeanServer && null != _collectorObjName) { try { _mbeanServer.unregisterMBean(_collectorObjName); _totalStats.unregisterMbean(_mbeanServer); for (String clientName: _perClientStats.keySet()) { _perClientStats.get(clientName).unregisterMbean(_mbeanServer); } LOG.info("MBean unregistered " + _collectorObjName); } catch (Exception e) { LOG.error("JMX deregistration failed", e); } } } @Override public void reset() { _totalStats.reset(); Lock readLock = acquireReadLock(); try { for (String peer: _perClientStats.keySet()) { _perClientStats.get(peer).reset(); } } finally { releaseLock(readLock); } } @Override public boolean isEnabled() { return _enabled.get(); } @Override public void setEnabled(boolean enabled) { _enabled.set(enabled); } @Override public DbusBootstrapHttpStatsMBean getTotalStats() { return _totalStats; } @Override public DbusBootstrapHttpStatsMBean getPeerStats(String peer) { Lock readLock = acquireReadLock(); try { DbusBootstrapHttpStats result = _perClientStats.get(peer); return result; } finally { releaseLock(readLock); } } @Override public void registerBootStrapReq(Checkpoint cp, long latency, long size) { _totalStats.registerBootStrapReq(cp, latency, size); //TODO: client views; /* Lock writeLock = acquireWriteLock(); try { if (NO_PEER != _curPeer) { DbusBootstrapHttpStats clientStats = getOrAddPerPeerCollector(_curPeer, writeLock); clientStats.registerBootStrapReq(cp,latency,size); } } finally { releaseLock(writeLock); } */ } @Override public void registerStartSCNReq(long latency) { //TODO: client views; _totalStats.registerStartSCNReq(latency); } @Override public void registerTargetSCNReq(long latency) { //TODO: client views; _totalStats.registerTargetSCNReq(latency); } @Override public void registerErrBootstrap() { //TODO: client views; _totalStats.registerErrBootstrap(); } @Override public void registerErrStartSCN() { //TODO: client views; _totalStats.registerErrStartSCN(); } @Override public void registerErrTargetSCN() { //TODO: client views; _totalStats.registerErrTargetSCN(); } @Override public void registerErrSqlException() { //TODO: client views; _totalStats.registerErrSqlException(); } @Override public void registerErrDatabaseTooOld() { //TODO: client views; _totalStats.registerErrDatabaseTooOld(); } }