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

org.bdware.doip.cluster.util.ResultMergerUtil 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 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;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy