All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bdware.doip.cluster.util.ResultCollector Maven / Gradle / Ivy

There is a newer version: 1.5.4
Show newest version
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();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy