1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.hadoop.mapreduce.counters; 20 21 import java.util.List; 22 import java.util.Map; 23 24 import com.google.common.collect.Lists; 25 import com.google.common.collect.Maps; 26 27 import org.apache.hadoop.classification.InterfaceAudience; 28 import org.apache.hadoop.mapreduce.Counter; 29 import org.apache.hadoop.mapreduce.FileSystemCounter; 30 import org.apache.hadoop.mapreduce.JobCounter; 31 import org.apache.hadoop.mapreduce.TaskCounter; 32 import org.apache.hadoop.mapreduce.util.ResourceBundles; 33 34 /** 35 * An abstract class to provide common implementation of the 36 * group factory in both mapred and mapreduce packages. 37 * 38 * @param <C> type of the counter 39 * @param <G> type of the group 40 */ 41 @InterfaceAudience.Private 42 public abstract class CounterGroupFactory<C extends Counter, 43 G extends CounterGroupBase<C>> { 44 45 public interface FrameworkGroupFactory<F> { newGroup(String name)46 F newGroup(String name); 47 } 48 49 // Integer mapping (for serialization) for framework groups 50 private static final Map<String, Integer> s2i = Maps.newHashMap(); 51 private static final List<String> i2s = Lists.newArrayList(); 52 private static final int VERSION = 1; 53 private static final String FS_GROUP_NAME = FileSystemCounter.class.getName(); 54 55 private final Map<String, FrameworkGroupFactory<G>> fmap = Maps.newHashMap(); 56 { 57 // Add builtin counter class here and the version when changed. 58 addFrameworkGroup(TaskCounter.class); 59 addFrameworkGroup(JobCounter.class); 60 } 61 62 // Initialize the framework counter group mapping 63 private synchronized <T extends Enum<T>> addFrameworkGroup(final Class<T> cls)64 void addFrameworkGroup(final Class<T> cls) { 65 updateFrameworkGroupMapping(cls); 66 fmap.put(cls.getName(), newFrameworkGroupFactory(cls)); 67 } 68 69 // Update static mappings (c2i, i2s) of framework groups updateFrameworkGroupMapping(Class<?> cls)70 private static synchronized void updateFrameworkGroupMapping(Class<?> cls) { 71 String name = cls.getName(); 72 Integer i = s2i.get(name); 73 if (i != null) return; 74 i2s.add(name); 75 s2i.put(name, i2s.size() - 1); 76 } 77 78 /** 79 * Required override to return a new framework group factory 80 * @param <T> type of the counter enum class 81 * @param cls the counter enum class 82 * @return a new framework group factory 83 */ 84 protected abstract <T extends Enum<T>> newFrameworkGroupFactory(Class<T> cls)85 FrameworkGroupFactory<G> newFrameworkGroupFactory(Class<T> cls); 86 87 /** 88 * Create a new counter group 89 * @param name of the group 90 * @param limits the counters limits policy object 91 * @return a new counter group 92 */ newGroup(String name, Limits limits)93 public G newGroup(String name, Limits limits) { 94 return newGroup(name, ResourceBundles.getCounterGroupName(name, name), 95 limits); 96 } 97 98 /** 99 * Create a new counter group 100 * @param name of the group 101 * @param displayName of the group 102 * @param limits the counters limits policy object 103 * @return a new counter group 104 */ newGroup(String name, String displayName, Limits limits)105 public G newGroup(String name, String displayName, Limits limits) { 106 FrameworkGroupFactory<G> gf = fmap.get(name); 107 if (gf != null) return gf.newGroup(name); 108 if (name.equals(FS_GROUP_NAME)) { 109 return newFileSystemGroup(); 110 } else if (s2i.get(name) != null) { 111 return newFrameworkGroup(s2i.get(name)); 112 } 113 return newGenericGroup(name, displayName, limits); 114 } 115 116 /** 117 * Create a new framework group 118 * @param id of the group 119 * @return a new framework group 120 */ newFrameworkGroup(int id)121 public G newFrameworkGroup(int id) { 122 String name; 123 synchronized(CounterGroupFactory.class) { 124 if (id < 0 || id >= i2s.size()) throwBadFrameGroupIdException(id); 125 name = i2s.get(id); // should not throw here. 126 } 127 FrameworkGroupFactory<G> gf = fmap.get(name); 128 if (gf == null) throwBadFrameGroupIdException(id); 129 return gf.newGroup(name); 130 } 131 132 /** 133 * Get the id of a framework group 134 * @param name of the group 135 * @return the framework group id 136 */ getFrameworkGroupId(String name)137 public static synchronized int getFrameworkGroupId(String name) { 138 Integer i = s2i.get(name); 139 if (i == null) throwBadFrameworkGroupNameException(name); 140 return i; 141 } 142 143 /** 144 * @return the counter factory version 145 */ version()146 public int version() { 147 return VERSION; 148 } 149 150 /** 151 * Check whether a group name is a name of a framework group (including 152 * the filesystem group). 153 * 154 * @param name to check 155 * @return true for framework group names 156 */ isFrameworkGroup(String name)157 public static synchronized boolean isFrameworkGroup(String name) { 158 return s2i.get(name) != null || name.equals(FS_GROUP_NAME); 159 } 160 throwBadFrameGroupIdException(int id)161 private static void throwBadFrameGroupIdException(int id) { 162 throw new IllegalArgumentException("bad framework group id: "+ id); 163 } 164 throwBadFrameworkGroupNameException(String name)165 private static void throwBadFrameworkGroupNameException(String name) { 166 throw new IllegalArgumentException("bad framework group name: "+ name); 167 } 168 169 /** 170 * Abstract factory method to create a generic (vs framework) counter group 171 * @param name of the group 172 * @param displayName of the group 173 * @param limits limits of the counters 174 * @return a new generic counter group 175 */ newGenericGroup(String name, String displayName, Limits limits)176 protected abstract G newGenericGroup(String name, String displayName, 177 Limits limits); 178 179 /** 180 * Abstract factory method to create a file system counter group 181 * @return a new file system counter group 182 */ newFileSystemGroup()183 protected abstract G newFileSystemGroup(); 184 } 185