Files
paho.mqtt-sn.embedded-c/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.cpp
2020-03-05 18:05:46 +09:00

321 lines
5.9 KiB
C++

/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNGWAggregateTopicTable.h"
#include "MQTTSNGWClient.h"
/*=====================================
Class ClientTopicElement
=====================================*/
ClientTopicElement::ClientTopicElement(Client* client)
{
_client = client;
}
ClientTopicElement::~ClientTopicElement()
{
}
Client* ClientTopicElement::getClient(void)
{
return _client;
}
ClientTopicElement* ClientTopicElement::getNextClientElement(void)
{
return _next;
}
/*=====================================
Class AggregateTopicElement
=====================================*/
AggregateTopicElement::AggregateTopicElement(void)
{
}
AggregateTopicElement::AggregateTopicElement(Topic* topic, Client* client)
{
_topic = topic;
ClientTopicElement* elm = new ClientTopicElement(client);
if ( elm != nullptr )
{
_head = elm;
_tail = elm;
}
}
AggregateTopicElement::~AggregateTopicElement(void)
{
_mutex.lock();
if ( _head != nullptr )
{
ClientTopicElement* p = _tail;
while ( p )
{
ClientTopicElement* pPrev = p;
delete p;
p = pPrev->_prev;
}
_head = _tail = nullptr;
}
_mutex.unlock();
}
ClientTopicElement* AggregateTopicElement::add(Client* client)
{
ClientTopicElement* elm = new ClientTopicElement(client);
if ( elm == nullptr )
{
return nullptr;
}
_mutex.lock();
if ( _head == nullptr )
{
_head = elm;
_tail = elm;
}
else
{
ClientTopicElement* p = find(client);
if ( p == nullptr )
{
p = _tail;
_tail = elm;
elm->_prev = p;
p->_next = elm;
}
else
{
delete elm;
elm = p;
}
}
_mutex.unlock();
return elm;
}
ClientTopicElement* AggregateTopicElement::find(Client* client)
{
ClientTopicElement* p = _head;
while ( p != nullptr )
{
if ( p->_client == client)
{
break;
}
p = p->_next;
}
return p;
}
ClientTopicElement* AggregateTopicElement::getFirstClientTopicElement(void)
{
return _head;
}
ClientTopicElement* AggregateTopicElement::getNextClientTopicElement(ClientTopicElement* elmClient)
{
return elmClient->_next;
}
void AggregateTopicElement::eraseClient(Client* client)
{
_mutex.lock();
ClientTopicElement* p = find(client);
if ( p != nullptr )
{
if ( p->_prev == nullptr ) // head element
{
_head = p->_next;
if ( p->_next == nullptr ) // head & only one
{
_tail = nullptr;
}
else
{
p->_next->_prev = nullptr; // head & midle
}
}
else if ( p->_next != nullptr ) // middle
{
p->_prev->_next = p->_next;
}
else // tail
{
p->_prev->_next = nullptr;
_tail = p->_prev;
}
delete p;
}
_mutex.unlock();
}
/*=====================================
Class AggregateTopicTable
======================================*/
AggregateTopicTable::AggregateTopicTable()
{
}
AggregateTopicTable::~AggregateTopicTable()
{
}
AggregateTopicElement* AggregateTopicTable::add(Topic* topic, Client* client)
{
AggregateTopicElement* elm = nullptr;
_mutex.lock();
elm = getAggregateTopicElement(topic);
if ( elm != nullptr )
{
if ( elm->find(client) == nullptr )
{
elm->add(client);
}
}
else
{
Topic* newTopic = topic->duplicate();
elm = new AggregateTopicElement(newTopic, client);
if ( _head == nullptr )
{
_head = elm;
_tail = elm;
}
else
{
elm->_prev = _tail;
_tail->_next = elm;
_tail = elm;
}
}
_mutex.unlock();
return elm;
}
void AggregateTopicTable::erase(Topic* topic, Client* client)
{
AggregateTopicElement* elm = nullptr;
_mutex.lock();
elm = getAggregateTopicElement(topic);
if ( elm != nullptr )
{
elm->eraseClient(client);
}
if ( elm->_head == nullptr )
{
erase(elm);
}
_mutex.unlock();
return;
}
void AggregateTopicTable::erase(AggregateTopicElement* elmTopic)
{
if ( elmTopic != nullptr )
{
if ( elmTopic->_prev == nullptr ) // head element
{
_head = elmTopic->_next;
if ( elmTopic->_next == nullptr ) // head & only one
{
_tail = nullptr;
}
else
{
elmTopic->_next->_prev = nullptr; // head & midle
}
}
else if ( elmTopic->_next != nullptr ) // middle
{
elmTopic->_prev->_next = elmTopic->_next;
}
else // tail
{
elmTopic->_prev->_next = nullptr;
_tail = elmTopic->_prev;
}
delete elmTopic;
}
}
AggregateTopicElement* AggregateTopicTable::getAggregateTopicElement(Topic* topic)
{
AggregateTopicElement* elm = _head;
while( elm != nullptr )
{
if ( elm->_topic->isMatch(topic->_topicName) )
{
break;
}
elm = elm->_next;
}
return elm;
}
ClientTopicElement* AggregateTopicTable::getClientElement(Topic* topic)
{
AggregateTopicElement* elm = getAggregateTopicElement(topic);
if ( elm != nullptr )
{
return elm->_head;
}
else
{
return nullptr;
}
}
void AggregateTopicTable::print(void)
{
AggregateTopicElement* elm = _head;
printf("Beginning of AggregateTopicTable\n");
while( elm != nullptr )
{
printf("%s\n", elm->_topic->getTopicName()->c_str());
ClientTopicElement* clElm = elm->getFirstClientTopicElement();
Client* client = clElm->getClient();
while ( client != nullptr )
{
printf(" %s\n", client->getClientId());
clElm = clElm->getNextClientElement();
if ( clElm != nullptr )
{
client = clElm->getClient();
}
else
{
client = nullptr;
}
}
elm = elm->_next;
}
printf("End of AggregateTopicTable\n");
}