Add ClientPool

Clients are created and kept in the pool at first.
ClientList gets a free client from the pool.

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
This commit is contained in:
tomoaki
2021-05-25 11:50:58 +09:00
parent 740faeb09f
commit 982e6d4884
4 changed files with 125 additions and 26 deletions

View File

@@ -32,14 +32,15 @@ char* currentDateTime(void);
Class Client Class Client
=====================================*/ =====================================*/
static const char* theClientStatus[] = static const char* theClientStatus[] =
{ "Disconnected", "TryConnecting", "Connecting", "Active", "Asleep", "Awake", { "InPool", "Disconnected", "TryConnecting", "Connecting", "Active", "Asleep",
"Awake",
"Lost" }; "Lost" };
Client::Client(bool secure) Client::Client(bool secure)
{ {
_packetId = 0; _packetId = 0;
_snMsgId = 0; _snMsgId = 0;
_status = Cstat_Disconnected; _status = Cstat_Free;
_keepAliveMsec = 0; _keepAliveMsec = 0;
_topics = new Topics(); _topics = new Topics();
_clientId = nullptr; _clientId = nullptr;

View File

@@ -152,7 +152,8 @@ private:
=====================================*/ =====================================*/
typedef enum typedef enum
{ {
Cstat_Disconnected = 0, Cstat_Free = 0,
Cstat_Disconnected,
Cstat_TryConnecting, Cstat_TryConnecting,
Cstat_Connecting, Cstat_Connecting,
Cstat_Active, Cstat_Active,
@@ -176,6 +177,7 @@ class Forwarder;
class Client class Client
{ {
friend class ClientList; friend class ClientList;
friend class ClientsPool;
public: public:
Client(bool secure = false); Client(bool secure = false);
Client(uint8_t maxInflightMessages, bool secure); Client(uint8_t maxInflightMessages, bool secure);

View File

@@ -20,18 +20,20 @@
#include <string> #include <string>
using namespace MQTTSNGW; using namespace MQTTSNGW;
extern Gateway* theGateway; char* currentDateTime(void);
/*===================================== /*=====================================
Class ClientList Class ClientList
=====================================*/ =====================================*/
const char* common_topic = "*"; const char* common_topic = "*";
ClientList::ClientList() ClientList::ClientList(Gateway* gw)
{ {
_clientCnt = 0; _clientCnt = 0;
_authorize = false; _authorize = false;
_firstClient = nullptr; _firstClient = nullptr;
_endClient = nullptr; _endClient = nullptr;
_clientsPool = new ClientsPool();
_gateway = gw;
} }
ClientList::~ClientList() ClientList::~ClientList()
@@ -46,12 +48,19 @@ ClientList::~ClientList()
delete cl; delete cl;
cl = ncl; cl = ncl;
}; };
if (_clientsPool)
{
delete _clientsPool;
}
_mutex.unlock(); _mutex.unlock();
} }
void ClientList::initialize(bool aggregate) void ClientList::initialize(bool aggregate)
{ {
if (theGateway->getGWParams()->clientAuthentication) _clientsPool->allocate(_gateway->getGWParams()->maxClients);
if (_gateway->getGWParams()->clientAuthentication)
{ {
int type = TRANSPEARENT_TYPE; int type = TRANSPEARENT_TYPE;
if (aggregate) if (aggregate)
@@ -62,7 +71,7 @@ void ClientList::initialize(bool aggregate)
_authorize = true; _authorize = true;
} }
if (theGateway->getGWParams()->predefinedTopic) if (_gateway->getGWParams()->predefinedTopic)
{ {
setPredefinedTopics(aggregate); setPredefinedTopics(aggregate);
} }
@@ -70,20 +79,21 @@ void ClientList::initialize(bool aggregate)
void ClientList::setClientList(int type) void ClientList::setClientList(int type)
{ {
if (!createList(theGateway->getGWParams()->clientListName, type)) if (!createList(_gateway->getGWParams()->clientListName, type))
{ {
throw EXCEPTION( throw EXCEPTION(
"ClientList::setClientList No client list defined by config file.", 0); "ClientList::setClientList Client list not found!", 0);
} }
} }
void ClientList::setPredefinedTopics(bool aggrecate) void ClientList::setPredefinedTopics(bool aggrecate)
{ {
if (!readPredefinedList(theGateway->getGWParams()->predefinedTopicFileName, if (!readPredefinedList(_gateway->getGWParams()->predefinedTopicFileName,
aggrecate)) aggrecate))
{ {
throw EXCEPTION( 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) else if (forwarder && type == FORWARDER_TYPE)
{ {
theGateway->getAdapterManager()->getForwarderList()->addForwarder( _gateway->getAdapterManager()->getForwarderList()->addForwarder(
&netAddr, &clientId); &netAddr, &clientId);
} }
else if (type == TRANSPEARENT_TYPE) else if (type == TRANSPEARENT_TYPE)
@@ -338,22 +348,23 @@ Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId,
Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId,
bool unstableLine, bool secure, int type) bool unstableLine, bool secure, int type)
{ {
Client* client = nullptr; Client* client = getClient(addr);
/* anonimous clients */
if (_clientCnt > MAX_CLIENTS)
{
return 0; // full of clients
}
client = getClient(addr);
if (client) if (client)
{ {
return client; return client;
} }
/* creat a new client */ /* acquire a free client */
client = new Client(secure); client = _clientsPool->getClient();
if (!client)
{
WRITELOG("%s%sMax number of Clients%s\n", currentDateTime(),
ERRMSG_HEADER, ERRMSG_FOOTER);
return nullptr;
}
client->disconnected();
if (addr) if (addr)
{ {
client->setClientAddress(addr); client->setClientAddress(addr);
@@ -411,7 +422,7 @@ Client* ClientList::createPredefinedTopic(MQTTSNString* clientId,
if (strcmp(clientId->cstring, common_topic) == 0) 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; return nullptr;
} }
else else
@@ -473,3 +484,69 @@ bool ClientList::isAuthorized()
return _authorize; 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++;
}
}

View File

@@ -30,13 +30,31 @@ namespace MQTTSNGW
class Client; 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
=====================================*/ =====================================*/
class ClientList class ClientList
{ {
public: public:
ClientList(); ClientList(Gateway* gw);
~ClientList(); ~ClientList();
void initialize(bool aggregate); void initialize(bool aggregate);
@@ -57,7 +75,8 @@ public:
private: private:
bool readPredefinedList(const char* fileName, bool _aggregate); bool readPredefinedList(const char* fileName, bool _aggregate);
Gateway* _gateway { nullptr }; ClientsPool* _clientsPool;
Gateway* _gateway;
Client* createPredefinedTopic(MQTTSNString* clientId, string topicName, Client* createPredefinedTopic(MQTTSNString* clientId, string topicName,
uint16_t toipcId, bool _aggregate); uint16_t toipcId, bool _aggregate);
Client* _firstClient; Client* _firstClient;