/* | |
* ContextFactory.java | |
* | |
* 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.hadoop.metrics; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.Map; | |
import java.util.Properties; | |
import org.apache.hadoop.classification.InterfaceAudience; | |
import org.apache.hadoop.classification.InterfaceStability; | |
import org.apache.hadoop.metrics.spi.AbstractMetricsContext; | |
import org.apache.hadoop.metrics.spi.NullContext; | |
/** | |
* Factory class for creating MetricsContext objects. To obtain an instance | |
* of this class, use the static <code>getFactory()</code> method. | |
*/ | |
@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"}) | |
@InterfaceStability.Evolving | |
public class ContextFactory { | |
private static final String PROPERTIES_FILE = | |
"/hadoop-metrics.properties"; | |
private static final String CONTEXT_CLASS_SUFFIX = | |
".class"; | |
private static final String DEFAULT_CONTEXT_CLASSNAME = | |
"org.apache.hadoop.metrics.spi.NullContext"; | |
private static ContextFactory theFactory = null; | |
private Map<String,Object> attributeMap = new HashMap<String,Object>(); | |
private Map<String,MetricsContext> contextMap = | |
new HashMap<String,MetricsContext>(); | |
// Used only when contexts, or the ContextFactory itself, cannot be | |
// created. | |
private static Map<String,MetricsContext> nullContextMap = | |
new HashMap<String,MetricsContext>(); | |
/** Creates a new instance of ContextFactory */ | |
protected ContextFactory() { | |
} | |
/** | |
* Returns the value of the named attribute, or null if there is no | |
* attribute of that name. | |
* | |
* @param attributeName the attribute name | |
* @return the attribute value | |
*/ | |
public Object getAttribute(String attributeName) { | |
return attributeMap.get(attributeName); | |
} | |
/** | |
* Returns the names of all the factory's attributes. | |
* | |
* @return the attribute names | |
*/ | |
public String[] getAttributeNames() { | |
String[] result = new String[attributeMap.size()]; | |
int i = 0; | |
// for (String attributeName : attributeMap.keySet()) { | |
Iterator it = attributeMap.keySet().iterator(); | |
while (it.hasNext()) { | |
result[i++] = (String) it.next(); | |
} | |
return result; | |
} | |
/** | |
* Sets the named factory attribute to the specified value, creating it | |
* if it did not already exist. If the value is null, this is the same as | |
* calling removeAttribute. | |
* | |
* @param attributeName the attribute name | |
* @param value the new attribute value | |
*/ | |
public void setAttribute(String attributeName, Object value) { | |
attributeMap.put(attributeName, value); | |
} | |
/** | |
* Removes the named attribute if it exists. | |
* | |
* @param attributeName the attribute name | |
*/ | |
public void removeAttribute(String attributeName) { | |
attributeMap.remove(attributeName); | |
} | |
/** | |
* Returns the named MetricsContext instance, constructing it if necessary | |
* using the factory's current configuration attributes. <p/> | |
* | |
* When constructing the instance, if the factory property | |
* <i>contextName</i>.class</code> exists, | |
* its value is taken to be the name of the class to instantiate. Otherwise, | |
* the default is to create an instance of | |
* <code>org.apache.hadoop.metrics.spi.NullContext</code>, which is a | |
* dummy "no-op" context which will cause all metric data to be discarded. | |
* | |
* @param contextName the name of the context | |
* @return the named MetricsContext | |
*/ | |
public synchronized MetricsContext getContext(String refName, String contextName) | |
throws IOException, ClassNotFoundException, | |
InstantiationException, IllegalAccessException { | |
MetricsContext metricsContext = contextMap.get(refName); | |
if (metricsContext == null) { | |
String classNameAttribute = refName + CONTEXT_CLASS_SUFFIX; | |
String className = (String) getAttribute(classNameAttribute); | |
if (className == null) { | |
className = DEFAULT_CONTEXT_CLASSNAME; | |
} | |
Class contextClass = Class.forName(className); | |
metricsContext = (MetricsContext) contextClass.newInstance(); | |
metricsContext.init(contextName, this); | |
contextMap.put(contextName, metricsContext); | |
} | |
return metricsContext; | |
} | |
public synchronized MetricsContext getContext(String contextName) | |
throws IOException, ClassNotFoundException, InstantiationException, | |
IllegalAccessException { | |
return getContext(contextName, contextName); | |
} | |
/** | |
* Returns all MetricsContexts built by this factory. | |
*/ | |
public synchronized Collection<MetricsContext> getAllContexts() { | |
// Make a copy to avoid race conditions with creating new contexts. | |
return new ArrayList<MetricsContext>(contextMap.values()); | |
} | |
/** | |
* Returns a "null" context - one which does nothing. | |
*/ | |
public static synchronized MetricsContext getNullContext(String contextName) { | |
MetricsContext nullContext = nullContextMap.get(contextName); | |
if (nullContext == null) { | |
nullContext = new NullContext(); | |
nullContextMap.put(contextName, nullContext); | |
} | |
return nullContext; | |
} | |
/** | |
* Returns the singleton ContextFactory instance, constructing it if | |
* necessary. <p/> | |
* | |
* When the instance is constructed, this method checks if the file | |
* <code>hadoop-metrics.properties</code> exists on the class path. If it | |
* exists, it must be in the format defined by java.util.Properties, and all | |
* the properties in the file are set as attributes on the newly created | |
* ContextFactory instance. | |
* | |
* @return the singleton ContextFactory instance | |
*/ | |
public static synchronized ContextFactory getFactory() throws IOException { | |
if (theFactory == null) { | |
theFactory = new ContextFactory(); | |
theFactory.setAttributes(); | |
} | |
return theFactory; | |
} | |
private void setAttributes() throws IOException { | |
InputStream is = getClass().getResourceAsStream(PROPERTIES_FILE); | |
if (is != null) { | |
try { | |
Properties properties = new Properties(); | |
properties.load(is); | |
//for (Object propertyNameObj : properties.keySet()) { | |
Iterator it = properties.keySet().iterator(); | |
while (it.hasNext()) { | |
String propertyName = (String) it.next(); | |
String propertyValue = properties.getProperty(propertyName); | |
setAttribute(propertyName, propertyValue); | |
} | |
} finally { | |
is.close(); | |
} | |
} | |
} | |
} |