org.bdware.doip.cluster.util.ResultMergerUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of doip-audit-tool Show documentation
Show all versions of doip-audit-tool Show documentation
doip audit tool developed by bdware
package org.bdware.doip.cluster.util;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.doip.codec.doipMessage.DoipMessage;
import org.bdware.doip.endpoint.client.DoipMessageCallback;
import org.bdware.sc.ContractResult;
import org.bdware.sc.bean.JoinInfo;
import org.bdware.sc.util.JsonUtil;
import wrp.jdk.nashorn.api.scripting.NashornScriptEngineUtil;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
public class ResultMergerUtil implements DoipMessageCallback {
CompositeDoipResult compositeDoipResult;
AtomicInteger order;
int totalCount; // 记录有多少个节点
DoipMessageCallback originalCallback;
JoinInfo joinInfo;
static Logger Logger = LogManager.getLogger(ResultMergerUtil.class);
int THRESHOLD; // >=的结果可返回
NashornScriptEngineUtil engineUtil;
public ResultMergerUtil(DoipMessageCallback originalCb, int totalCount, final JoinInfo joinInfo, NashornScriptEngineUtil nashornScriptEngineUtil) {
originalCallback = originalCb;
this.totalCount = totalCount;
compositeDoipResult = new CompositeDoipResult(totalCount);
order = new AtomicInteger(0);
this.joinInfo = joinInfo;
this.engineUtil = nashornScriptEngineUtil;
}
public String getInfo() {
return " 收到第 " + order.get() + " 个节点回复 : ";
}
@Override
public void onResult(DoipMessage doipMessage) {
// TODO 必须在这里聚合。
// 返回值
try {
Logger.info(getInfo() + doipMessage);
//LOGGER.info("contractID=" + contractID + " 收到第 " + order + " 个节点回复 : " + str + " order=" + order + " count=" + count);
final int curCount = order.incrementAndGet();
compositeDoipResult.addDoipResult(curCount, doipMessage);
// 收集到所有结果
if (curCount == totalCount) {
// todo merge后的结果很奇怪,ContractResult是可以的,但是DOIPMessage不知道怎么merge合适啊。。。
ContractResult finalResult = compositeDoipResult.mergeFinalResult();
if (joinInfo != null) {
handleJoinInfo(finalResult, joinInfo);
}
// new return result
DoipMessage doipMsgResult = new DoipMessage("", "");
doipMsgResult.body.encodedData = finalResult.result.toString().getBytes(StandardCharsets.UTF_8);
originalCallback.onResult(doipMsgResult);
// old return result
// originalCallback.onResult(JsonUtil.fromJson(finalResult.result.getAsJsonObject(), DoipMessage.class));
// recover,其中无状态合约CP出错无需恢复
Set problemResults = compositeDoipResult.getProblemNodes();
for (String problemResult : problemResults) {
Logger.warn(problemResult);
}
}
} catch (Exception e) {
e.printStackTrace();
Logger.info("本次执行最终结果为有异常");
}
}
private void handleJoinInfo(ContractResult finalResult, JoinInfo joinInfo) {
JsonObject jo = finalResult.result.getAsJsonObject();
try {
if (joinInfo != null) {
if (joinInfo.useDefault == null) {
if (joinInfo.joinFuncName != null) {
finalResult.result = engineUtil.invokeFunction(joinInfo.joinFuncName, JsonElement.class, jo);
}
return;
}
switch (joinInfo.useDefault) {
case add:
double val = 0;
for (String key : jo.keySet()) {
val += jo.get(key).getAsDouble();
}
finalResult.result = new JsonPrimitive(val);
break;
case multiply:
val = 1;
for (String key : jo.keySet()) {
val *= jo.get(key).getAsDouble();
}
finalResult.result = new JsonPrimitive(val);
break;
default:
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class CompositeDoipResult {
private static final Logger LOGGER = LogManager.getLogger(CompositeDoipResult.class);
Map successResultMap = new HashMap<>(); // 只有状态是Success的返回结果会存在这个map中
Set problemResult = new HashSet<>();
int THRESHOLD; // >=的结果可返回
public CompositeDoipResult(int totalCount) {
THRESHOLD = (int) Math.ceil((double) totalCount / 2);
}
public synchronized void addDoipResult(final int count, DoipMessage doipMessage) {
successResultMap.put(Integer.valueOf(count).toString(), doipMessage);
}
public Set getProblemNodes() {
return problemResult;
}
public ContractResult mergeFinalResult() {
LOGGER.info("mergeFinalResult");
// JsonParser
JsonObject finalResult = new JsonObject();
ContractResult finalContractResult = new ContractResult(ContractResult.Status.Success, finalResult);
for (String count : successResultMap.keySet()) {
// 取出
DoipMessage singleResult = successResultMap.get(count); // 取出结果
if (singleResult != null) {
finalResult.add(count, JsonUtil.fromJson(JsonUtil.toJson(singleResult), JsonObject.class));
}
}
return finalContractResult;
}
}