fdbus client实现之增加重连机制

1、应用前景

一般的,fdbus的client端的实现是继承CBaseClient,override接口。由于使用CBaseClient的connect去连接Service时,失败不会有通知只有成功才会有onOnline的通知,这就需要我们引入重连技术。另外假如Service端crash了,Client端会收到onOffline状态通知,收到onOffline也需要触发重连,直到Service进程启动后才会重连成功。
FDBUS Client重连Service依赖于onOnline和onOffline这两个状态,但似乎CBaseClient中没有相应的方法来获取这两个状态值,因此我这边引入了一个父类FdbusClientBase,由它来继承FDBUS的CBaseClient,FdbusClientBase主要增加setOnline和isOnline两个方法,我们的Client只需要继承父类FdbusClientBase,不需要继承CBaseClient。

2、FdbusCluetBase实现

FdbusClientBase有如下几个方法:

class FdbusClientBase : public CBaseClient, public android::RefBase {
    public:
        FdbusClientBase(const std::string& url, const std::string& name, CBaseWorker *worker)
        : CBaseClient(name.c_str(), worker),
          mOnline(false),
          mUrl(url) {
        }

        virtual ~FdbusClientBase() {
        }

        virtual bool isOnline() {
            MuxGuard g(mLock);
            return mOnline;
        }

        virtual void setOnline(bool online) {
            MuxGuard g(mLock);
            mOnline = online;
        }

        virtual std::string getUrl() {
            return mUrl;
        }

    protected:
        bool mOnline;
        std::string mUrl;
        using MuxGuard = std::lock_guard<std::mutex>;
        mutable std::mutex mLock;
    };

子类继承它的例子:
.h文件

class CANFdbusClient : public FdbusClientBase {
public:
    CANFdbusClient(const string& url, const string& name, CBaseWorker *worker, MessageTransceiver* transceiver);
    ~CANFdbusClient();
    ProxyStatusCode sendMessage(IPC_MODULE_GROUP groupId, const uint8_t * data, int32_t length);
    void onReceiveMsg(IPC_MODULE_GROUP groupId, const VehicleMessage& vehicleMsg);
    virtual void onOffline(FdbSessionId_t sid, bool is_last) override;
    virtual void onOnline(FdbSessionId_t sid, bool is_first) override;
    virtual void onBroadcast(CBaseJob::Ptr &msg_ref) override;
    virtual void onStatus(CBaseJob::Ptr &msg_ref, int error_code,
    const char *description) override;
    virtual void onReply(CBaseJob::Ptr &msg_ref);

private:
    MessageTransceiver *mTransceiver;
    bool mFdbusOnline;
};

重要实现:
保存online和offline状态值:
在onOnline中调用setOnline保存状态值
在onOffline中保存状态值

3、Timer实现类

多个client的情况:

class FdbusConnectionTimer : public android::RefBase{
    public:
        FdbusConnectionTimer() {
        }

        virtual ~FdbusConnectionTimer() {
            mIsActive = false;
        }

        void addFdbusClient(android::sp<FdbusClientBase> client) {
            std::lock_guard<std::mutex> g(mLock);
            mClientList.push_back(client);
        }

        void startTimer() {
            mIsActive = true;
            mTimerThread = std::thread(&FdbusConnectionTimer::loop, this);
        }

        void stopTimer() {
            mIsActive = false;
            mStopRequested = true;
            mCond.notify_one();
            if (mTimerThread.joinable()) {
                mTimerThread.join();
            }
        }

        bool isDeactive() {
            return !mIsActive;
        }

    private:
        void loop() {
            int32_t retryCount = 0;
            while (!mStopRequested) {
                if(mClientList.size() > 0) {
                    for(android::sp<FdbusClientBase> client : mClientList) {
                        if(client != nullptr && !client->isOnline()) {
                            ALOGD("%s retry to connect to %s", __func__, client->getUrl().c_str());
                            client->connect(client->getUrl().c_str());
                            retryCount++;
                        } else if(client != nullptr && client->isOnline()) {
                            ALOGD("%s client connect to %s successfully", __func__, client->getUrl().c_str());
                            for(std::vector<android::sp<FdbusClientBase>>::iterator iter = mClientList.begin(); iter != mClientList.end(); iter++){
                                if(*iter == client){
                                    MuxGuard g(mLock);
                                    mClientList.erase(iter);
                                    break;
                                }
                            }
                        }
                    }
                    std::unique_lock<std::mutex> g(mLock);
                    mCond.wait_for(g, std::chrono::seconds(1));  // wait 1 second
                } else {
                    // All client are online,so stop loop
                    mIsActive = false;
                    break;
                }
            }
            ALOGD("%s total retryCount: %d", __func__, retryCount);
        }

    private:
        using MuxGuard = std::lock_guard<std::mutex>;
        mutable std::mutex mLock;
        std::thread mTimerThread;
        std::condition_variable mCond;
        std::atomic_bool mStopRequested { false };
        std::atomic_bool mIsActive { false };
        std::vector<android::sp<FdbusClientBase>> mClientList;
    };

单个client的情况:

/*************************************************************************
 * Copyright (C) 2020 GWM Automotive Inc.
 *
 * The copyright notice above does not evidence any actual
 * or intended publication of such source code.
 * The code contains GWM Confidential Proprietary Information.
 *************************************************************************/
/**************************************************************************
 * @file FdbusConnectionTimer.h
 * FdbusConnectionTimer
 *
 * @project     v3.5
 * @subsystem
 * @version     0.1
 * @author
 * @date        2020-7-30

 Module-History:
 Date(dd.mm.year)| Author            | Reason
 The latest entry at the head of the history list.
 8/4/2020         Fugen Peng           Init version

***************************************************************************/
#ifndef vendor_noch_hardware_automotive_vehicle_V1_0_impl_FdbusConnectionTimer_H_
#define vendor_noch_hardware_automotive_vehicle_V1_0_impl_FdbusConnectionTimer_H_

#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <common_base/fdbus.h>
#include "FdbusClientBase.h"
#include <log/log.h>
#include <utils/RefBase.h>

#undef LOG_TAG
#define LOG_TAG "FdbusConnectionTimer"

namespace vendor {
namespace noch {
namespace hardware {
namespace automotive {
namespace vehicle {
namespace V1_0 {


    class FdbusConnectionTimer : public android::RefBase{
    public:
        FdbusConnectionTimer() {
        }

        virtual ~FdbusConnectionTimer() {
            mIsActive = false;
        }

        void addFdbusClient(android::sp<FdbusClientBase> client) {
            std::lock_guard<std::mutex> g(mLock);
            mClient = client;
        }

        void startTimer() {
            mIsActive = true;
            mTimerThread = std::thread(&FdbusConnectionTimer::loop, this);
        }

        void stopTimer() {
            mIsActive = false;
            mStopRequested = true;
            mCond.notify_one();
            if (mTimerThread.joinable()) {
                mTimerThread.join();
            }
        }

        bool isDeactive() {
            return !mIsActive;
        }

    private:
        void loop() {
            int32_t retryCount = 0;
            while (!mStopRequested) {
                if ((mClient != nullptr) && !mClient->isOnline()) {
                    ALOGD("%s retry to connect to %s", __func__, mClient->getUrl().c_str());
                    mClient->connect(mClient->getUrl().c_str());
                    retryCount++;
                }
                else {
                    mIsActive = false;
                    ALOGD("%s client connect to %s successfully", __func__, mClient->getUrl().c_str());
                    break;
                }
                std::unique_lock<std::mutex> g(mLock);
                mCond.wait_for(g, std::chrono::seconds(1));  // wait 1 second
            }
            ALOGD("%s total retryCount: %d", __func__, retryCount);
        }

    private:
        using MuxGuard = std::lock_guard<std::mutex>;
        mutable std::mutex mLock;
        std::thread mTimerThread;
        std::condition_variable mCond;
        std::atomic_bool mStopRequested { false };
        std::atomic_bool mIsActive { false };
        sp<FdbusClientBase> mClient;
    };
}
}
}
}
}
}
#endif

触发Timer

开机触发Timer

void MessageTransceiver::fdbus_init() {
/* start fdbus context thread */
FDB_CONTEXT->start();

/* start worker thread */
CBaseWorker *worker_ptr = &main_worker;
worker_ptr->start();

/* create client to connect mcuipc server */
std::string mcuipcsrv_name = "fdbus_mcu_ipc";
std::string mcuipcsrv_url(FDB_URL_SVC);
mcuipcsrv_url += mcuipcsrv_name;

mCANFdbusClient = new CANFdbusClient(mcuipcsrv_url, mcuipcsrv_name, worker_ptr, this);
assert(mCANFdbusClient != nullptr);

mCANFdbusClient->enableReconnect(true);
mCANFdbusClient->connect(mcuipcsrv_url.c_str());

/* create client to connect display server */
std::string backlightsrv_name = "fdbus_backlight";
std::string backlightsrv_url(FDB_URL_SVC);
backlightsrv_url += backlightsrv_name;

mDisplayFdbusClient = new DisplayFdbusClient(backlightsrv_url, backlightsrv_name, worker_ptr, this);
assert(mDisplayFdbusClient != nullptr);

mDisplayFdbusClient->enableReconnect(true);
mDisplayFdbusClient->connect(backlightsrv_url.c_str());
mConTimer = new FdbusConnectionTimer();
assert(mConTimer != nullptr);
mConTimer->addFdbusClient(mCANFdbusClient);
// display server is not ready
// mConTimer->addFdbusClient(mDisplayFdbusClient);
if(mConTimer->isDeactive()) {
mConTimer->startTimer();
}
}

onOffline时触发

void MessageTransceiver::notifyFdbusOffline(sp<FdbusClientBase> client) {
    mConTimer->addFdbusClient(client); 
    if(mConTimer->isDeactive()) {
       mConTimer->startTimer();
    }
}

void CANFdbusClient::onOffline(FdbSessionId_t sid, bool is_last) {
        ALOGD("%s client session offline: %d", __func__, sid);
        setOnline(false);
        if(mTransceiver != nullptr) {
            mTransceiver->notifyFdbusOffline(this);
        }
}
  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值