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.function.Function; 022import org.apache.hadoop.hbase.TableName; 023import org.apache.hadoop.hbase.chaos.actions.Action; 024import org.slf4j.Logger; 025import org.slf4j.LoggerFactory; 026 027public class ConfigurableSlowDeterministicMonkeyFactory extends SlowDeterministicMonkeyFactory { 028 029 private static final Logger LOG = 030 LoggerFactory.getLogger(ConfigurableSlowDeterministicMonkeyFactory.class); 031 032 final static String HEAVY_ACTIONS = "heavy.actions"; 033 final static String TABLE_PARAM = "\\$table_name"; 034 035 public enum SupportedTypes { 036 FLOAT(p -> Float.parseFloat(p)), 037 LONG(p -> Long.parseLong(p)), 038 INT(p -> Integer.parseInt(p)), 039 TABLENAME(p -> TableName.valueOf(p)); 040 041 final Function<String, Object> converter; 042 043 SupportedTypes(Function<String, Object> converter) { 044 this.converter = converter; 045 } 046 047 Object convert(String param) { 048 return converter.apply(param); 049 } 050 } 051 052 @Override 053 protected Action[] getHeavyWeightedActions() { 054 String actions = this.properties.getProperty(HEAVY_ACTIONS); 055 if (actions == null || actions.isEmpty()) { 056 return super.getHeavyWeightedActions(); 057 } else { 058 try { 059 String[] actionClasses = actions.split(";"); 060 Action[] heavyActions = new Action[actionClasses.length]; 061 for (int i = 0; i < actionClasses.length; i++) { 062 heavyActions[i] = instantiateAction(actionClasses[i]); 063 } 064 LOG.info("Created actions {}", heavyActions); 065 return heavyActions; 066 } catch (Exception e) { 067 LOG.error("Error trying to instantiate heavy actions. Returning null array.", e); 068 } 069 return null; 070 } 071 } 072 073 private Action instantiateAction(String actionString) throws Exception { 074 final String packageName = "org.apache.hadoop.hbase.chaos.actions"; 075 String[] classAndParams = actionString.split("\\)")[0].split("\\("); 076 String className = packageName + "." + classAndParams[0]; 077 String[] params = 078 classAndParams[1].replaceAll(TABLE_PARAM, tableName.getNameAsString()).split(","); 079 LOG.info("About to instantiate action class: {}; With constructor params: {}", className, 080 params); 081 Class<? extends Action> actionClass = (Class<? extends Action>) Class.forName(className); 082 Constructor<? extends Action>[] constructors = 083 (Constructor<? extends Action>[]) actionClass.getDeclaredConstructors(); 084 for (Constructor<? extends Action> c : constructors) { 085 if (c.getParameterCount() != params.length) { 086 continue; 087 } 088 Class[] paramTypes = c.getParameterTypes(); 089 Object[] constructorParams = new Object[paramTypes.length]; 090 for (int i = 0; i < paramTypes.length; i++) { 091 constructorParams[i] = 092 SupportedTypes.valueOf(paramTypes[i].getSimpleName().toUpperCase()).convert(params[i]); 093 } 094 return c.newInstance(constructorParams); 095 } 096 throw new IllegalArgumentException( 097 "Couldn't find any matching constructor for: " + actionString); 098 } 099}