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

org.bdware.doip.endpoint.client.ResponseWait Maven / Gradle / Ivy

There is a newer version: 1.5.7
Show newest version
/*
 *    Copyright (c) [2021] [Peking University]
 *    [BDWare DOIP SDK] is licensed under Mulan PSL v2.
 *    You can use this software according to the terms and conditions of the Mulan PSL v2.
 *    You may obtain a copy of Mulan PSL v2 at:
 *             http://license.coscl.org.cn/MulanPSL2
 *    THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 *    See the Mulan PSL v2 for more details.
 */

package org.bdware.doip.endpoint.client;

import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.doip.codec.doipMessage.DoipMessage;
import org.bdware.doip.codec.doipMessage.DoipMessageFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;


public class ResponseWait {
    static Logger LOGGER = LogManager.getLogger(ResponseWait.class);
    public final static HashedWheelTimer HASHED_WHEEL_TIMER = new HashedWheelTimer(new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = Executors.defaultThreadFactory().newThread(r);
            t.setDaemon(true);
            return t;
        }
    }, 5, TimeUnit.MILLISECONDS, 2);
    // RecvCounter counter = new RecvCounter("(ResponseWait.java:84)");

    public ResponseWait() {
        //   counter.start();
    }

    // use static map to ensure requestid is !UNIC!
    // in a client(With multiple connection)
    final static Map> waitObj = new ConcurrentHashMap<>();

    static class Pair {
        final T first;
        final U second;

        Pair(T t, U u) {
            this.first = t;
            this.second = u;
        }
    }

    public void wakeUpAndRemove(int requestID, DoipMessage result) {
        Pair ob = getAndRemove(requestID);
        wakeup(requestID, ob, result);
    }

    //DO NOT use synchronized like "private synchronized ..."
    //Because the waitObj is static
    private Pair getAndRemove(int requestID) {
        synchronized (waitObj) {
            Pair ob = waitObj.get(requestID);
            waitObj.remove(requestID);
            if (ob != null && ob.second != null) {
                ob.second.cancel();
                return ob;
            }
            return null;
        }
    }

    public boolean waitResponseFor5Secs(final int requestID, DoipMessageCallback cb) {
        return waitResponse(requestID, cb, 5);
    }

    public boolean waitResponse(int requestID, DoipMessageCallback cb, int seconds) {
        //TODO speed control in client is here!
        //In case of out-of-memory exception!
        if (waitObj.size() > 2000) {
            // counter.inc();
            return false;
        }
        synchronized (waitObj) {
            if (!waitObj.containsKey(requestID)) {
                TimerTask tt = new TimerTask() {
                    @Override
                    public void run(Timeout timeout) throws Exception {
                        DoipMessage timeOutMessage = DoipMessageFactory.createTimeoutResponse(requestID);
                        wakeUpAndRemove(requestID, timeOutMessage);
                        // TODO bug here
                        // may remove unhandled callback if the requestID is duplicated
                    }
                };
                Timeout timeout = HASHED_WHEEL_TIMER.newTimeout(tt, seconds, TimeUnit.SECONDS);
                waitObj.put(requestID, new Pair<>(cb, timeout));
                return true;
            }
            LOGGER.debug("Return false, try again!");
            return false;
        }
    }


    //TODO just support for stream??
    // schedule timeout cleaner?
    public void wakeup(int requestID, DoipMessage result) {
        Pair ob = waitObj.get(requestID);
        wakeup(requestID, ob, result);
    }

    public void wakeup(int requestID, Pair ob, DoipMessage result) {
        if (ob == null) {
            // LOGGER.info("cancel the timeout task!!" + requestID + ", please Check server status??");
            // @TODO fix previous bug by stopping the timeout runner.
        }
        if (ob != null) {
            ob.first.onResult(result);
            ob.second.cancel();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy