org.bdware.doip.cluster.util.ResultCollector 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 ResultCollector implements DoipMessageCallback {
// joinCount记录开始Merge的上限
int joinCount;
AtomicInteger count = new AtomicInteger(0);
DoipMessageCallback originalCallback;
Logger Logger = LogManager.getLogger(ResultCollector.class);
Map successResMap = new HashMap<>();
Set problemResult = new HashSet<>();
// 记录所有收到结果列表
Set nodeIDs = new HashSet<>();
NashornScriptEngineUtil engineUtil;
JoinInfo joinInfo;
public ResultCollector(DoipMessageCallback cb, int joinCount, NashornScriptEngineUtil engineUtil, JoinInfo joinInfo) {
this.originalCallback = cb;
this.joinCount = joinCount;
this.engineUtil = engineUtil;
this.joinInfo = joinInfo;
}
@Override
public void onResult(DoipMessage msg) {
logDoipMsgInfo(msg);
// 如果nodeID不存在,或者该节点的返回值已经被处理过了,不需要再次调用onResult了
String nodeID = getNodeID(msg);
if (nodeID == null || nodeIDs.contains(nodeID)) {
// 如果当前nodeID == null, 记录到problemResult中
if(nodeID == null) {
problemResult.add(msg.toString());
}
return;
}
nodeIDs.add(nodeID);
int curCount = count.incrementAndGet();
// 小于joinCount,意味着还没达到聚合的标准,需要继续处理
if (curCount <= joinCount) {
addDoipResult(nodeID, msg);
// 达到聚合标准
if (curCount == joinCount) {
// 完成聚合 & 结果统计
DoipMessage finalResult = executeJoinFunc();
originalCallback.onResult(finalResult);
}
}
}
public DoipMessageCallback getOriginalCallback(){ return originalCallback; }
public Set getProblemNodes() {
return problemResult;
}
public void logDoipMsgInfo(DoipMessage msg) {
String nodeID = getNodeID(msg);
if(nodeID != null) {
Logger.info(" 收到第 " + nodeID + " 个节点回复 : " + msg.toString());
} else {
Logger.error(" 收到错误的节点回复 : " + "Something wrong happens in the msg received from doip server, msg is : " + msg.toString());
}
}
public synchronized void addDoipResult(String nodeID, DoipMessage msg) {
successResMap.put(nodeID, msg);
}
public ContractResult mergeFinalResult() {
Logger.info("mergeFinalResult");
// JsonParser
JsonObject finalResult = new JsonObject();
ContractResult mergedContractResult = new ContractResult(ContractResult.Status.Success, finalResult);
for (String nodeID : successResMap.keySet()) {
DoipMessage singleDoipMsg = successResMap.get(nodeID); // 取出结果
if (singleDoipMsg != null) {
finalResult.add("Node" + nodeID, JsonUtil.fromJson(JsonUtil.toJson(singleDoipMsg), JsonObject.class));
}
}
return mergedContractResult;
}
public String getNodeID(DoipMessage msg) {
String nodeID = null;
if(msg != null && msg.header != null && msg.header.parameters != null && msg.header.parameters.attributes != null) {
if (msg.header.parameters.attributes.get("nodeID") != null) {
nodeID = msg.header.parameters.attributes.get("nodeID").getAsString();
}
}
return nodeID;
}
public DoipMessage executeJoinFunc() {
ContractResult finalResult = mergeFinalResult();
if(joinInfo != null) {
handleJoinInfo(finalResult, joinInfo);
}
// new return result
DoipMessage doipMsgResult = new DoipMessage("", "");
doipMsgResult.body.encodedData = finalResult.result.toString().getBytes(StandardCharsets.UTF_8);
// recover,其中无状态合约CP出错无需恢复
Set problemResults = getProblemNodes();
for (String problemResult : problemResults) {
Logger.warn(problemResult);
}
return doipMsgResult;
}
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();
}
}
}