Add Countable interface for result model

pull/1203/head
gongdewei 5 years ago
parent 17e268dde0
commit 5498891252

@ -0,0 +1,15 @@
package com.taobao.arthas.core.command.model;
/**
* Item countable for ResultModel
* @author gongdewei 2020/6/8
*/
public interface Countable {
/**
* Get item size of this result model, the value of size is greater than or equal to 1
* @return item size of this result model
*/
int size();
}

@ -1,6 +1,7 @@
package com.taobao.arthas.core.distribution;
import com.alibaba.fastjson.JSON;
import com.taobao.arthas.core.command.model.Countable;
import com.taobao.arthas.core.command.model.ResultModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -14,49 +15,56 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
*
*
* @author gongdewei 2020/5/18
*/
public class ResultConsumerHelper {
private static final Logger logger = LoggerFactory.getLogger(ResultConsumerHelper.class);
private static Map<String, List<Field>> modelFieldMap = new ConcurrentHashMap<String, List<Field>>();
private static ConcurrentHashMap<String, List<Field>> modelFieldMap = new ConcurrentHashMap<String, List<Field>>();
/**
* item
*
* itemConsumer
*
*
* @param model
* @return
*/
public static int getItemCount(ResultModel model) {
int count = processSpecialCommand(model);
if (count > 0) {
return count;
//如果实现Countable接口则认为model自己统计元素数量
if (model instanceof Countable) {
return ((Countable) model).size();
}
//TODO 抽取ItemSet/ItemGroup接口解决ClassSetVO/mbean等分组的情况
//对于普通的Model通过类反射统计容器类字段统计元素数量
//缓存Field对象避免产生内存碎片
Class modelClass = model.getClass();
List<Field> fields = modelFieldMap.get(modelClass.getName());
if (fields == null) {
fields = new ArrayList<Field>();
modelFieldMap.put(modelClass.getName(), fields);
Field[] declaredFields = modelClass.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) {
Field field = declaredFields[i];
Class<?> fieldClass = field.getType();
//如果是List/Map/Array/Countable类型的字段则缓存起来后面统计数量
if (Collection.class.isAssignableFrom(fieldClass)
|| Map.class.isAssignableFrom(fieldClass)
|| fieldClass.isArray()
/* || fieldClass == ClassSetVO.class*/) {
|| Countable.class.isAssignableFrom(fieldClass)
|| fieldClass.isArray()) {
field.setAccessible(true);
fields.add(field);
}
}
List<Field> old_fields = modelFieldMap.putIfAbsent(modelClass.getName(), fields);
if (old_fields != null) {
fields = old_fields;
}
}
//获取item数量
//统计Model对象的item数量
int count = 0;
try {
for (int i = 0; i < fields.size(); i++) {
Field field = fields.get(i);
@ -66,13 +74,13 @@ public class ResultConsumerHelper {
Object value = field.get(model);
if (value != null) {
if (value instanceof Collection) {
return ((Collection) value).size();
count += ((Collection) value).size();
} else if (value.getClass().isArray()) {
return Array.getLength(value);
count += Array.getLength(value);
} else if (value instanceof Map) {
return ((Map) value).size();
// } else if (value.getClass() == ClassSetVO.class) {
// return ((ClassSetVO) value).getClasses().size();
count += ((Map) value).size();
} else if (value instanceof Countable) {
count += ((Countable) value).size();
}
}
}
@ -80,18 +88,7 @@ public class ResultConsumerHelper {
logger.error("get item count of result model failed, model: {}", JSON.toJSONString(model), e);
}
return 1;
}
private static int processSpecialCommand(ResultModel model) {
// if (model instanceof CatModel) {
// //特殊处理cat
// return ((CatModel) model).getContent().length()/100 + 1 ;
// } else if (model instanceof TraceModel) {
// //特殊处理trace
// return ((TraceModel) model).getNodeCount();
// }
return 0;
return count > 0 ? count : 1;
}
}

Loading…
Cancel
Save