001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.chaos.factories; 019 020import java.lang.reflect.Constructor; 021import java.util.List; 022import java.util.function.Function; 023import org.apache.hadoop.hbase.TableName; 024import org.apache.hadoop.hbase.chaos.actions.Action; 025import org.slf4j.Logger; 026import org.slf4j.LoggerFactory; 027 028import org.apache.hbase.thirdparty.com.google.common.base.Splitter; 029import org.apache.hbase.thirdparty.com.google.common.collect.Iterables; 030 031public class ConfigurableSlowDeterministicMonkeyFactory extends SlowDeterministicMonkeyFactory { 032 033 private static final Logger LOG = 034 LoggerFactory.getLogger(ConfigurableSlowDeterministicMonkeyFactory.class); 035 036 final static String HEAVY_ACTIONS = "heavy.actions"; 037 final static String TABLE_PARAM = "\\$table_name"; 038 039 @SuppressWarnings("ImmutableEnumChecker") 040 public enum SupportedTypes { 041 FLOAT(p -> Float.parseFloat(p)), 042 LONG(p -> Long.parseLong(p)), 043 INT(p -> Integer.parseInt(p)), 044 TABLENAME(p -> TableName.valueOf(p)); 045 046 final Function<String, Object> converter; 047 048 SupportedTypes(Function<String, Object> converter) { 049 this.converter = converter; 050 } 051 052 Object convert(String param) { 053 return converter.apply(param); 054 } 055 } 056 057 @Override 058 protected Action[] getHeavyWeightedActions() { 059 String actions = this.properties.getProperty(HEAVY_ACTIONS); 060 if (actions == null || actions.isEmpty()) { 061 return super.getHeavyWeightedActions(); 062 } else { 063 try { 064 List<String> actionClasses = Splitter.on(';').splitToList(actions); 065 Action[] heavyActions = new Action[actionClasses.size()]; 066 int i = 0; 067 for (String action : actionClasses) { 068 heavyActions[i++] = instantiateAction(action); 069 } 070 LOG.info("Created actions {}", (Object[]) heavyActions); // non-varargs call to LOG#info 071 return heavyActions; 072 } catch (Exception e) { 073 LOG.error("Error trying to instantiate heavy actions. Returning null array.", e); 074 } 075 return null; 076 } 077 } 078 079 private Action instantiateAction(String actionString) throws Exception { 080 final String packageName = "org.apache.hadoop.hbase.chaos.actions"; 081 Iterable<String> classAndParams = 082 Splitter.on('(').split(Iterables.get(Splitter.on(')').split(actionString), 0)); 083 String className = packageName + "." + Iterables.get(classAndParams, 0); 084 String[] params = Splitter.on(',') 085 .splitToStream( 086 Iterables.get(classAndParams, 1).replaceAll(TABLE_PARAM, tableName.getNameAsString())) 087 .toArray(String[]::new); 088 LOG.info("About to instantiate action class: {}; With constructor params: {}", className, 089 params); 090 Class<? extends Action> actionClass = (Class<? extends Action>) Class.forName(className); 091 Constructor<? extends Action>[] constructors = 092 (Constructor<? extends Action>[]) actionClass.getDeclaredConstructors(); 093 for (Constructor<? extends Action> c : constructors) { 094 if (c.getParameterCount() != params.length) { 095 continue; 096 } 097 Class[] paramTypes = c.getParameterTypes(); 098 Object[] constructorParams = new Object[paramTypes.length]; 099 for (int i = 0; i < paramTypes.length; i++) { 100 constructorParams[i] = 101 SupportedTypes.valueOf(paramTypes[i].getSimpleName().toUpperCase()).convert(params[i]); 102 } 103 return c.newInstance(constructorParams); 104 } 105 throw new IllegalArgumentException( 106 "Couldn't find any matching constructor for: " + actionString); 107 } 108}