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

org.bdware.doip.cluster.client.DoaClusterClient Maven / Gradle / Ivy

The newest version!
package org.bdware.doip.cluster.client;

import com.google.gson.JsonObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.doip.audit.EndpointConfig;
import org.bdware.doip.audit.writer.AuditConfig;
import org.bdware.doip.cluster.entity.*;
import org.bdware.doip.cluster.flowcontrol.FlowControl;
import org.bdware.doip.cluster.flowcontrol.core.RateThresholdFlowControl;
import org.bdware.doip.cluster.util.DOResolutionUtil;
import org.bdware.doip.cluster.util.DoipClientCacheUtil;
import org.bdware.doip.codec.doipMessage.DoipMessage;
import org.bdware.doip.codec.doipMessage.DoipMessageFactory;
import org.bdware.doip.codec.doipMessage.DoipMessageSigner;
import org.bdware.doip.codec.doipMessage.DoipResponseCode;
import org.bdware.doip.endpoint.client.DoipClientImpl;
import org.bdware.doip.endpoint.client.DoipMessageCallback;
import org.bdware.irp.client.IrpClient;
import org.bdware.irp.exception.IrpClientException;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

public class DoaClusterClient extends DoipClientImpl {
    public final DoipMessageSigner doipMessageSigner;
    // router config -> provide to DoipClusterClient
    public final DOAConfig doaConfig;
    // irsClient -> connect to router to resolve doid
    private final IrpClient irsClient;
    // DDOID -> Contract Method -> RouteInfo
    private final Map doCache = new ConcurrentHashMap<>();
    private static final Logger LOGGER = LogManager.getLogger(DoaClusterClient.class);
    private final FlowControl flowControl;
    private final DoipClientCacheUtil doipClientCache;

    // todo optimize thread pool
    private AuditConfig auditConfig;

    public DoaClusterClient(DOAConfig config) {
        this.doipClientCache = new DoipClientCacheUtil();
        this.doaConfig = config;
        this.irsClient = config.getIrpClient();
        doipMessageSigner = config.getSigner();
        int threshold = 1000;
        if (config.getExtraConfig() != null && config.getExtraConfig().has("rateThresholdFlowControl"))
            threshold = config.getExtraConfig().get("rateThresholdFlowControl").getAsInt();
        flowControl = new RateThresholdFlowControl(threshold);
        LOGGER.info("The SmartClusterClient has been initialized:" + threshold);
        this.auditConfig = config.getAuditConfig();
    }

    public AuditConfig getAuditConfig() {
        return auditConfig;
    }

    @Override
    public void sendMessage(DoipMessage doipMessage, DoipMessageCallback cb) {
        sendMessage(doipMessage, cb, true);
    }


    public void sendMessage(DoipMessage doipMessage, DoipMessageCallback cb, boolean needFlowControl) {
        try {
            sendMessage(doipMessage.header.parameters.id, doipMessage, cb, needFlowControl);
        } catch (Exception e) {
            e.printStackTrace();
            DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
            builder.createResponse(DoipResponseCode.UnKnownError, doipMessage);
            cb.onResult(builder.create());
        }
    }

    public void sendMessage(String targetDO, DoipMessage doipMessage, DoipMessageCallback cb, boolean needFlowControl) {
        try {
            parseDORecursive(targetDO, doipMessage, cb, needFlowControl);
        } catch (Exception e) {
            e.printStackTrace();
            DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
            builder.createResponse(DoipResponseCode.UnKnownError, doipMessage);
            cb.onResult(builder.create());
        }
    }

    public DoipMessage sendMessageSync(DoipMessage doipMessage, long timeout, boolean needFlowControl) {
        CompletableFuture result = new CompletableFuture<>();
        sendMessage(doipMessage, result::complete, needFlowControl);
        try {
            return result.get(timeout, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
            builder.createResponse(DoipResponseCode.MoreThanOneErrors, doipMessage);
            builder.setBody("timeout".getBytes());
            return builder.create();
        }
    }

    public DoipMessage sendMessageSync(DoipMessage doipMessage, long timeout) {
        return sendMessageSync(doipMessage, timeout, true);
    }

    // 返回当前doid对应的所有的BDRepo
    public void parseDORecursive(String doid, DoipMessage doipMessage, DoipMessageCallback cb, boolean needFlowControl) throws IrpClientException {
        DOEntity cachedDO = doCache.get(doid);
        if (cachedDO == null) {
            JsonObject doInfo = DOResolutionUtil.getDOInfo(irsClient, doid);
            BDWType doType = DOResolutionUtil.getDOType(doInfo);
            if (doType == BDWType.DDO) {
                DOResolutionUtil.verifyDDOInfo(doInfo);
                cachedDO = ddoInfo2DDOEntity(doid, doInfo);
            } else {
                DOResolutionUtil.verifyBDOInfo(doInfo);
                cachedDO = bdoInfo2BDOEntity(doid, doInfo);
            }
        }
        DoipMessageCallback flowControlCallback = cb;
        if (needFlowControl)
            flowControlCallback = msg -> {
                cb.onResult(msg);
                flowControl.maintainFlowControl();
            };
        SendMsgReqPack sendMsgReqPack = new SendMsgReqPack(this, cachedDO, doipMessage, flowControlCallback, needFlowControl);
        executeTask(sendMsgReqPack);
    }

    public DDOEntity ddoInfo2DDOEntity(String ddoID, JsonObject ddoInfo) {
        DOEntity ddoEntity = doCache.get(ddoID);
        if (ddoEntity != null) return (DDOEntity) ddoEntity;
        doCache.putIfAbsent(ddoID, new DDOEntity(ddoInfo, this));
        return (DDOEntity) doCache.get(ddoID);
    }

    public BDOEntity bdoInfo2BDOEntity(String bdoID, JsonObject bdoInfo) {
        DOEntity bdoEntity = doCache.get(bdoID);
        if (bdoEntity != null) return (BDOEntity) bdoEntity;
        String address = bdoInfo.get("address").getAsString();
        String version = bdoInfo.get("version").getAsString();
        doCache.putIfAbsent(bdoID, new BDOEntity(address, version, doipClientCache));
        return (BDOEntity) doCache.get(bdoID);
    }

    private void executeTask(SendMsgReqPack pack) {
        if (pack.needFlowControl())
            for (int i = 0; i < 10 && !flowControl.enableRequestPass(); i++) {
                try {
//                    LOGGER.info("rate is too fast");
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        pack.execute();
    }

    public void signMessage(DoipMessage message) {
        if (doipMessageSigner != null)
            doipMessageSigner.signMessage(message);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy