blob: a402f741085c0f323c30c2a52281a72ca51071a4 [file] [log] [blame]
/*
* 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.mapreduce.counters;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.mapreduce.Counter;
import org.apache.hadoop.mapreduce.FileSystemCounter;
import org.apache.hadoop.mapreduce.JobCounter;
import org.apache.hadoop.mapreduce.TaskCounter;
import org.apache.hadoop.mapreduce.util.ResourceBundles;
/**
* An abstract class to provide common implementation of the
* group factory in both mapred and mapreduce packages.
*
* @param <C> type of the counter
* @param <G> type of the group
*/
@InterfaceAudience.Private
public abstract class CounterGroupFactory<C extends Counter,
G extends CounterGroupBase<C>> {
public interface FrameworkGroupFactory<F> {
F newGroup(String name);
}
// Integer mapping (for serialization) for framework groups
private static final Map<String, Integer> s2i = Maps.newHashMap();
private static final List<String> i2s = Lists.newArrayList();
private static final int VERSION = 1;
private static final String FS_GROUP_NAME = FileSystemCounter.class.getName();
private final Map<String, FrameworkGroupFactory<G>> fmap = Maps.newHashMap();
{
// Add builtin counter class here and the version when changed.
addFrameworkGroup(TaskCounter.class);
addFrameworkGroup(JobCounter.class);
}
// Initialize the framework counter group mapping
private synchronized <T extends Enum<T>>
void addFrameworkGroup(final Class<T> cls) {
updateFrameworkGroupMapping(cls);
fmap.put(cls.getName(), newFrameworkGroupFactory(cls));
}
// Update static mappings (c2i, i2s) of framework groups
private static synchronized void updateFrameworkGroupMapping(Class<?> cls) {
String name = cls.getName();
Integer i = s2i.get(name);
if (i != null) return;
i2s.add(name);
s2i.put(name, i2s.size() - 1);
}
/**
* Required override to return a new framework group factory
* @param <T> type of the counter enum class
* @param cls the counter enum class
* @return a new framework group factory
*/
protected abstract <T extends Enum<T>>
FrameworkGroupFactory<G> newFrameworkGroupFactory(Class<T> cls);
/**
* Create a new counter group
* @param name of the group
* @param limits the counters limits policy object
* @return a new counter group
*/
public G newGroup(String name, Limits limits) {
return newGroup(name, ResourceBundles.getCounterGroupName(name, name),
limits);
}
/**
* Create a new counter group
* @param name of the group
* @param displayName of the group
* @param limits the counters limits policy object
* @return a new counter group
*/
public G newGroup(String name, String displayName, Limits limits) {
FrameworkGroupFactory<G> gf = fmap.get(name);
if (gf != null) return gf.newGroup(name);
if (name.equals(FS_GROUP_NAME)) {
return newFileSystemGroup();
}
return newGenericGroup(name, displayName, limits);
}
/**
* Create a new framework group
* @param id of the group
* @return a new framework group
*/
public G newFrameworkGroup(int id) {
String name;
synchronized(CounterGroupFactory.class) {
if (id < 0 || id >= i2s.size()) throwBadFrameGroupIdException(id);
name = i2s.get(id); // should not throw here.
}
FrameworkGroupFactory<G> gf = fmap.get(name);
if (gf == null) throwBadFrameGroupIdException(id);
return gf.newGroup(name);
}
/**
* Get the id of a framework group
* @param name of the group
* @return the framework group id
*/
public static synchronized int getFrameworkGroupId(String name) {
Integer i = s2i.get(name);
if (i == null) throwBadFrameworkGroupNameException(name);
return i;
}
/**
* @return the counter factory version
*/
public int version() {
return VERSION;
}
/**
* Check whether a group name is a name of a framework group (including
* the filesystem group).
*
* @param name to check
* @return true for framework group names
*/
public static synchronized boolean isFrameworkGroup(String name) {
return s2i.get(name) != null || name.equals(FS_GROUP_NAME);
}
private static void throwBadFrameGroupIdException(int id) {
throw new IllegalArgumentException("bad framework group id: "+ id);
}
private static void throwBadFrameworkGroupNameException(String name) {
throw new IllegalArgumentException("bad framework group name: "+ name);
}
/**
* Abstract factory method to create a generic (vs framework) counter group
* @param name of the group
* @param displayName of the group
* @param limits limits of the counters
* @return a new generic counter group
*/
protected abstract G newGenericGroup(String name, String displayName,
Limits limits);
/**
* Abstract factory method to create a file system counter group
* @return a new file system counter group
*/
protected abstract G newFileSystemGroup();
}