/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ package org.apache.accumulo.server.metrics; import java.net.URL; import org.apache.accumulo.core.util.Daemon; import org.apache.commons.configuration.AbstractFileConfiguration; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.EnvironmentConfiguration; import org.apache.commons.configuration.SystemConfiguration; import org.apache.commons.configuration.XMLConfiguration; import org.apache.commons.configuration.event.ConfigurationEvent; import org.apache.commons.configuration.event.ConfigurationListener; import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MetricsConfiguration { private static final Logger log = LoggerFactory.getLogger(MetricsConfiguration.class); private static boolean alreadyWarned = false; private boolean notFound = false; private int notFoundCount = 0; private static SystemConfiguration sysConfig = null; private static EnvironmentConfiguration envConfig = null; private XMLConfiguration xConfig = null; private Configuration config = null; private final Object lock = new Object(); private volatile boolean needsReloading = false; private long lastCheckTime = 0; private static long CONFIG_FILE_CHECK_INTERVAL = 1000 * 60 * 10; // 10 minutes private static int CONFIG_FILE_CHECK_COUNTER = 100; public final static long CONFIG_FILE_RELOAD_DELAY = 60000; private MetricsConfigWatcher watcher = null; private boolean enabled = false; private String enabledName = null; /** * Background thread that pokes the XMLConfiguration file to see if it has changed. If it has, then the Configuration Listener will get an event. * */ private class MetricsConfigWatcher extends Daemon { public MetricsConfigWatcher() {} @Override public void run() { while (this.isAlive()) { try { Thread.sleep(MetricsConfiguration.CONFIG_FILE_RELOAD_DELAY); } catch (InterruptedException ie) { // Do Nothing } xConfig.getBoolean("master.enabled"); } } } /** * ConfigurationListener that sets a flag to reload the XML config file */ private class MetricsConfigListener implements ConfigurationListener { @Override public void configurationChanged(ConfigurationEvent event) { if (event.getType() == AbstractFileConfiguration.EVENT_RELOAD) needsReloading = true; } } public MetricsConfiguration(String name) { // We are going to store the "enabled" parameter for this // name as a shortcut so that it doesn't have to be looked // up in the configuration so much. this.enabledName = name + ".enabled"; getMetricsConfiguration(); } public Configuration getEnvironmentConfiguration() { synchronized (MetricsConfiguration.class) { if (null == envConfig) envConfig = new EnvironmentConfiguration(); return envConfig; } } public Configuration getSystemConfiguration() { synchronized (MetricsConfiguration.class) { if (null == sysConfig) sysConfig = new SystemConfiguration(); return sysConfig; } } public Configuration getMetricsConfiguration() { if (notFound) { if (notFoundCount <= CONFIG_FILE_CHECK_COUNTER) { return null; } else if ((notFoundCount > CONFIG_FILE_CHECK_COUNTER) && ((System.currentTimeMillis() - lastCheckTime) > CONFIG_FILE_CHECK_INTERVAL)) { notFoundCount = 0; lastCheckTime = System.currentTimeMillis(); notFound = false; } else { notFoundCount++; } } if (null == config || needsReloading) { synchronized (lock) { if (needsReloading) { loadConfiguration(); } else if (null == config) { loadConfiguration(); } needsReloading = false; } } return config; } private void loadConfiguration() { URL metricsUrl = MetricsConfiguration.class.getClassLoader().getResource("accumulo-metrics.xml"); if (metricsUrl == null) { if (!alreadyWarned) log.warn("accumulo-metrics.xml was not found on classpath. Metrics collection will be disabled."); alreadyWarned = true; notFound = true; return; } try { xConfig = new XMLConfiguration(metricsUrl); xConfig.append(getEnvironmentConfiguration()); xConfig.addConfigurationListener(new MetricsConfigListener()); xConfig.setReloadingStrategy(new FileChangedReloadingStrategy()); // Start a background Thread that checks a property from the XMLConfiguration // every so often to force the FileChangedReloadingStrategy to fire. if (null == watcher || !watcher.isAlive()) { watcher = new MetricsConfigWatcher(); watcher.start(); } notFound = false; alreadyWarned = false; } catch (ConfigurationException ce) { log.error("Error reading accumulo-metrics.xml file."); notFound = true; return; } if (xConfig != null) { config = xConfig.interpolatedConfiguration(); // set the enabled boolean from the configuration enabled = config.getBoolean(enabledName); if (log.isDebugEnabled()) log.debug("Metrics collection enabled=" + enabled); } else { enabled = false; } } public boolean isEnabled() { // Force reload if necessary if (null == getMetricsConfiguration()) return false; return enabled; } public static void main(String[] args) throws Exception { MetricsConfiguration mc = new MetricsConfiguration("master"); while (true) { System.out.println("------------------------------------------------------------------------------------------------"); long t1 = System.currentTimeMillis(); System.out.println(mc.isEnabled() + " took: " + (System.currentTimeMillis() - t1)); Thread.sleep(1000); } } }