From 982e6d488448f53780c988f7ec928401485157a9 Mon Sep 17 00:00:00 2001 From: tomoaki Date: Tue, 25 May 2021 11:50:58 +0900 Subject: [PATCH] Add ClientPool Clients are created and kept in the pool at first. ClientList gets a free client from the pool. Signed-off-by: tomoaki --- MQTTSNGateway/src/MQTTSNGWClient.cpp | 5 +- MQTTSNGateway/src/MQTTSNGWClient.h | 4 +- MQTTSNGateway/src/MQTTSNGWClientList.cpp | 119 +++++++++++++++++++---- MQTTSNGateway/src/MQTTSNGWClientList.h | 23 ++++- 4 files changed, 125 insertions(+), 26 deletions(-) diff --git a/MQTTSNGateway/src/MQTTSNGWClient.cpp b/MQTTSNGateway/src/MQTTSNGWClient.cpp index 11ecc71..ddd4adc 100644 --- a/MQTTSNGateway/src/MQTTSNGWClient.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClient.cpp @@ -32,14 +32,15 @@ char* currentDateTime(void); Class Client =====================================*/ static const char* theClientStatus[] = -{ "Disconnected", "TryConnecting", "Connecting", "Active", "Asleep", "Awake", +{ "InPool", "Disconnected", "TryConnecting", "Connecting", "Active", "Asleep", + "Awake", "Lost" }; Client::Client(bool secure) { _packetId = 0; _snMsgId = 0; - _status = Cstat_Disconnected; + _status = Cstat_Free; _keepAliveMsec = 0; _topics = new Topics(); _clientId = nullptr; diff --git a/MQTTSNGateway/src/MQTTSNGWClient.h b/MQTTSNGateway/src/MQTTSNGWClient.h index 6d063f9..7b7db4e 100644 --- a/MQTTSNGateway/src/MQTTSNGWClient.h +++ b/MQTTSNGateway/src/MQTTSNGWClient.h @@ -152,7 +152,8 @@ private: =====================================*/ typedef enum { - Cstat_Disconnected = 0, + Cstat_Free = 0, + Cstat_Disconnected, Cstat_TryConnecting, Cstat_Connecting, Cstat_Active, @@ -176,6 +177,7 @@ class Forwarder; class Client { friend class ClientList; + friend class ClientsPool; public: Client(bool secure = false); Client(uint8_t maxInflightMessages, bool secure); diff --git a/MQTTSNGateway/src/MQTTSNGWClientList.cpp b/MQTTSNGateway/src/MQTTSNGWClientList.cpp index d40c0fc..0d1ad0d 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientList.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientList.cpp @@ -20,18 +20,20 @@ #include using namespace MQTTSNGW; -extern Gateway* theGateway; +char* currentDateTime(void); /*===================================== Class ClientList =====================================*/ const char* common_topic = "*"; -ClientList::ClientList() +ClientList::ClientList(Gateway* gw) { _clientCnt = 0; _authorize = false; _firstClient = nullptr; _endClient = nullptr; + _clientsPool = new ClientsPool(); + _gateway = gw; } ClientList::~ClientList() @@ -46,12 +48,19 @@ ClientList::~ClientList() delete cl; cl = ncl; }; + + if (_clientsPool) + { + delete _clientsPool; + } _mutex.unlock(); } void ClientList::initialize(bool aggregate) { - if (theGateway->getGWParams()->clientAuthentication) + _clientsPool->allocate(_gateway->getGWParams()->maxClients); + + if (_gateway->getGWParams()->clientAuthentication) { int type = TRANSPEARENT_TYPE; if (aggregate) @@ -62,7 +71,7 @@ void ClientList::initialize(bool aggregate) _authorize = true; } - if (theGateway->getGWParams()->predefinedTopic) + if (_gateway->getGWParams()->predefinedTopic) { setPredefinedTopics(aggregate); } @@ -70,20 +79,21 @@ void ClientList::initialize(bool aggregate) void ClientList::setClientList(int type) { - if (!createList(theGateway->getGWParams()->clientListName, type)) + if (!createList(_gateway->getGWParams()->clientListName, type)) { throw EXCEPTION( - "ClientList::setClientList No client list defined by config file.", 0); + "ClientList::setClientList Client list not found!", 0); } } void ClientList::setPredefinedTopics(bool aggrecate) { - if (!readPredefinedList(theGateway->getGWParams()->predefinedTopicFileName, + if (!readPredefinedList(_gateway->getGWParams()->predefinedTopicFileName, aggrecate)) { throw EXCEPTION( - "ClientList::setPredefinedTopics No predefindTopi list defined by config file.",0); + "ClientList::setPredefinedTopics PredefindTopic list not found!", + 0); } } @@ -158,7 +168,7 @@ bool ClientList::createList(const char* fileName, int type) } else if (forwarder && type == FORWARDER_TYPE) { - theGateway->getAdapterManager()->getForwarderList()->addForwarder( + _gateway->getAdapterManager()->getForwarderList()->addForwarder( &netAddr, &clientId); } else if (type == TRANSPEARENT_TYPE) @@ -338,22 +348,23 @@ Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure, int type) { - Client* client = nullptr; - - /* anonimous clients */ - if (_clientCnt > MAX_CLIENTS) - { - return 0; // full of clients - } - - client = getClient(addr); + Client* client = getClient(addr); if (client) { return client; } - /* creat a new client */ - client = new Client(secure); + /* acquire a free client */ + client = _clientsPool->getClient(); + + if (!client) + { + WRITELOG("%s%sMax number of Clients%s\n", currentDateTime(), + ERRMSG_HEADER, ERRMSG_FOOTER); + return nullptr; + } + + client->disconnected(); if (addr) { client->setClientAddress(addr); @@ -411,7 +422,7 @@ Client* ClientList::createPredefinedTopic(MQTTSNString* clientId, if (strcmp(clientId->cstring, common_topic) == 0) { - theGateway->getTopics()->add((const char*) topicName.c_str(), topicId); + _gateway->getTopics()->add((const char*) topicName.c_str(), topicId); return nullptr; } else @@ -473,3 +484,69 @@ bool ClientList::isAuthorized() return _authorize; } +/****************************** + * Class ClientsPool + ******************************/ + +ClientsPool::ClientsPool() +{ + _clientCnt = 0; + _firstClient = nullptr; + _endClient = nullptr; +} + +ClientsPool::~ClientsPool() +{ + Client* cl = _firstClient; + Client* ncl; + + while (cl != nullptr) + { + ncl = cl->_nextClient; + delete cl; + cl = ncl; + }; +} + +void ClientsPool::allocate(int maxClients) +{ + Client* cl = nullptr; + + _firstClient = new Client(); + + for (int i = 0; i < maxClients; i++) + { + if ((cl = new Client()) == nullptr) + { + throw Exception( + "ClientsPool::Can't allocate max number of clients\n", 0); + } + cl->_nextClient = _firstClient; + _firstClient = cl; + _clientCnt++; + } + +} + +Client* ClientsPool::getClient(void) +{ + while (_firstClient != nullptr) + { + Client* cl = _firstClient; + _firstClient = cl->_nextClient; + cl->_nextClient = nullptr; + _clientCnt--; + return cl; + } + return nullptr; +} + +void ClientsPool::setClient(Client* client) +{ + if (client) + { + client->_nextClient = _firstClient; + _firstClient = client; + _clientCnt++; + } +} diff --git a/MQTTSNGateway/src/MQTTSNGWClientList.h b/MQTTSNGateway/src/MQTTSNGWClientList.h index e3542bb..33424be 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientList.h +++ b/MQTTSNGateway/src/MQTTSNGWClientList.h @@ -30,13 +30,31 @@ namespace MQTTSNGW class Client; +/*===================================== + Class ClientsPool + =====================================*/ +class ClientsPool +{ +public: + ClientsPool(); + ~ClientsPool(); + void allocate(int maxClients); + Client* getClient(void); + void setClient(Client* client); + +private: + Client* _firstClient; + Client* _endClient; + int _clientCnt; +}; + /*===================================== Class ClientList =====================================*/ class ClientList { public: - ClientList(); + ClientList(Gateway* gw); ~ClientList(); void initialize(bool aggregate); @@ -57,7 +75,8 @@ public: private: bool readPredefinedList(const char* fileName, bool _aggregate); - Gateway* _gateway { nullptr }; + ClientsPool* _clientsPool; + Gateway* _gateway; Client* createPredefinedTopic(MQTTSNString* clientId, string topicName, uint16_t toipcId, bool _aggregate); Client* _firstClient;