Commit f319fda7 authored by Pavel Vainerman's avatar Pavel Vainerman

(UNetUDP): added 'channel switch counter'

parent a05c4bf3
...@@ -212,7 +212,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const ...@@ -212,7 +212,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( resp_id == uniset::DefaultObjectId ) if( resp_id == uniset::DefaultObjectId )
{ {
ostringstream err; ostringstream err;
err << myname << ": Unknown RespondID.. Not found id for '" << s_resp_id << "'" << endl; err << myname << ": " << n_it.getProp("name") << " : Unknown RespondID.. Not found id for '" << s_resp_id << "'" << endl;
unetcrit << myname << "(init): " << err.str() << endl; unetcrit << myname << "(init): " << err.str() << endl;
throw SystemError(err.str()); throw SystemError(err.str());
} }
...@@ -228,7 +228,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const ...@@ -228,7 +228,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( resp2_id == uniset::DefaultObjectId ) if( resp2_id == uniset::DefaultObjectId )
{ {
ostringstream err; ostringstream err;
err << myname << ": Unknown RespondID(2).. Not found id for '" << s_resp2_id << "'" << endl; err << myname << ": " << n_it.getProp("name") << " : Unknown RespondID(2).. Not found id for '" << s_resp2_id << "'" << endl;
unetcrit << myname << "(init): " << err.str() << endl; unetcrit << myname << "(init): " << err.str() << endl;
throw SystemError(err.str()); throw SystemError(err.str());
} }
...@@ -244,7 +244,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const ...@@ -244,7 +244,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( lp_id == uniset::DefaultObjectId ) if( lp_id == uniset::DefaultObjectId )
{ {
ostringstream err; ostringstream err;
err << myname << ": Unknown LostPacketsID.. Not found id for '" << s_lp_id << "'" << endl; err << myname << ": " << n_it.getProp("name") << " : Unknown LostPacketsID.. Not found id for '" << s_lp_id << "'" << endl;
unetcrit << myname << "(init): " << err.str() << endl; unetcrit << myname << "(init): " << err.str() << endl;
throw SystemError(err.str()); throw SystemError(err.str());
} }
...@@ -260,7 +260,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const ...@@ -260,7 +260,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( lp2_id == uniset::DefaultObjectId ) if( lp2_id == uniset::DefaultObjectId )
{ {
ostringstream err; ostringstream err;
err << myname << ": Unknown LostPacketsID(2).. Not found id for '" << s_lp2_id << "'" << endl; err << myname << ": " << n_it.getProp("name") << " : Unknown LostPacketsID(2).. Not found id for '" << s_lp2_id << "'" << endl;
unetcrit << myname << "(init): " << err.str() << endl; unetcrit << myname << "(init): " << err.str() << endl;
throw SystemError(err.str()); throw SystemError(err.str());
} }
...@@ -276,7 +276,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const ...@@ -276,7 +276,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( lp_comm_id == uniset::DefaultObjectId ) if( lp_comm_id == uniset::DefaultObjectId )
{ {
ostringstream err; ostringstream err;
err << myname << ": Unknown LostPacketsID(comm).. Not found id for '" << s_lp_comm_id << "'" << endl; err << myname << ": " << n_it.getProp("name") << " : Unknown LostPacketsID(comm).. Not found id for '" << s_lp_comm_id << "'" << endl;
unetcrit << myname << "(init): " << err.str() << endl; unetcrit << myname << "(init): " << err.str() << endl;
throw SystemError(err.str()); throw SystemError(err.str());
} }
...@@ -292,7 +292,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const ...@@ -292,7 +292,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( resp_comm_id == uniset::DefaultObjectId ) if( resp_comm_id == uniset::DefaultObjectId )
{ {
ostringstream err; ostringstream err;
err << myname << ": Unknown RespondID(comm).. Not found id for '" << s_resp_comm_id << "'" << endl; err << myname << ": " << n_it.getProp("name") << " : Unknown RespondID(comm).. Not found id for '" << s_resp_comm_id << "'" << endl;
unetcrit << myname << "(init): " << err.str() << endl; unetcrit << myname << "(init): " << err.str() << endl;
throw SystemError(err.str()); throw SystemError(err.str());
} }
...@@ -308,7 +308,23 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const ...@@ -308,7 +308,23 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( numchannel_id == uniset::DefaultObjectId ) if( numchannel_id == uniset::DefaultObjectId )
{ {
ostringstream err; ostringstream err;
err << myname << ": Unknown NumChannelID.. Not found id for '" << s_numchannel_id << "'" << endl; err << myname << ": " << n_it.getProp("name") << " : Unknown NumChannelID.. Not found id for '" << s_numchannel_id << "'" << endl;
unetcrit << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
}
string s_channelSwitchCount_id(n_it.getProp("unet_channelswitchcount_id"));
uniset::ObjectId channelswitchcount_id = uniset::DefaultObjectId;
if( !s_channelSwitchCount_id.empty() )
{
channelswitchcount_id = conf->getSensorID(s_channelSwitchCount_id);
if( channelswitchcount_id == uniset::DefaultObjectId )
{
ostringstream err;
err << myname << ": " << n_it.getProp("name") << " : Unknown ChannelSwitchCountID.. Not found id for '" << channelswitchcount_id << "'" << endl;
unetcrit << myname << "(init): " << err.str() << endl; unetcrit << myname << "(init): " << err.str() << endl;
throw SystemError(err.str()); throw SystemError(err.str());
} }
...@@ -393,6 +409,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const ...@@ -393,6 +409,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
ri.setRespondID(resp_comm_id, resp_invert); ri.setRespondID(resp_comm_id, resp_invert);
ri.setLostPacketsID(lp_comm_id); ri.setLostPacketsID(lp_comm_id);
ri.setChannelNumID(numchannel_id); ri.setChannelNumID(numchannel_id);
ri.setChannelSwitchCountID(channelswitchcount_id);
recvlist.emplace_back( std::move(ri) ); recvlist.emplace_back( std::move(ri) );
} }
...@@ -594,6 +611,16 @@ void UNetExchange::ReceiverInfo::step( const std::shared_ptr<SMInterface>& shm, ...@@ -594,6 +611,16 @@ void UNetExchange::ReceiverInfo::step( const std::shared_ptr<SMInterface>& shm,
{ {
unetcrit << myname << "(ReceiverInfo::step): (channelnum): " << ex.what() << std::endl; unetcrit << myname << "(ReceiverInfo::step): (channelnum): " << ex.what() << std::endl;
} }
try
{
if( sidChannelSwitchCount != DefaultObjectId )
shm->localSetValue(itChannelSwitchCount, sidChannelSwitchCount, channelSwitchCount, shm->ID());
}
catch( const std::exception& ex )
{
unetcrit << myname << "(ReceiverInfo::step): (channelSwitchCount): " << ex.what() << std::endl;
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetExchange::sysCommand( const uniset::SystemMessage* sm ) void UNetExchange::sysCommand( const uniset::SystemMessage* sm )
...@@ -901,6 +928,7 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive ...@@ -901,6 +928,7 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive
// переключаемся на второй // переключаемся на второй
it.r1->setLockUpdate(true); it.r1->setLockUpdate(true);
it.r2->setLockUpdate(false); it.r2->setLockUpdate(false);
it.channelSwitchCount++;
dlog8 << myname << "(event): " << r->getName() dlog8 << myname << "(event): " << r->getName()
<< ": timeout for channel1.. select channel 2" << endl; << ": timeout for channel1.. select channel 2" << endl;
...@@ -917,6 +945,13 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive ...@@ -917,6 +945,13 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive
if( it.r2 ) if( it.r2 )
it.r2->setLockUpdate(true); it.r2->setLockUpdate(true);
// если какой-то канал уже работал
// то увеличиваем счётчик переключений
// а если ещё не работал, значит это просто первое включение канала
// а не переключение
if( it.channelSwitchCount > 0 )
it.channelSwitchCount++;
dlog8 << myname << "(event): " << r->getName() dlog8 << myname << "(event): " << r->getName()
<< ": link failed for channel2.. select again channel1.." << endl; << ": link failed for channel2.. select again channel1.." << endl;
} }
...@@ -938,6 +973,7 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive ...@@ -938,6 +973,7 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive
// переключаемся на первый // переключаемся на первый
it.r1->setLockUpdate(false); it.r1->setLockUpdate(false);
it.r2->setLockUpdate(true); it.r2->setLockUpdate(true);
it.channelSwitchCount++;
dlog8 << myname << "(event): " << r->getName() dlog8 << myname << "(event): " << r->getName()
<< ": timeout for channel2.. select channel 1" << endl; << ": timeout for channel2.. select channel 1" << endl;
...@@ -954,6 +990,13 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive ...@@ -954,6 +990,13 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive
it.r2->setLockUpdate(false); it.r2->setLockUpdate(false);
// если какой-то канал уже работал
// то увеличиваем счётчик переключений
// а если ещё не работал, значит это просто первое включение канала
// а не переключение
if( it.channelSwitchCount > 0 )
it.channelSwitchCount++;
dlog8 << myname << "(event): " << r->getName() dlog8 << myname << "(event): " << r->getName()
<< ": link failed for channel1.. select again channel2.." << endl; << ": link failed for channel1.. select again channel2.." << endl;
} }
......
...@@ -49,6 +49,7 @@ namespace uniset ...@@ -49,6 +49,7 @@ namespace uniset
- \ref pgUNetUDP_Conf - \ref pgUNetUDP_Conf
- \ref pgUNetUDP_Reserv - \ref pgUNetUDP_Reserv
- \ref pgUNetUDP_SendFactor - \ref pgUNetUDP_SendFactor
- \ref pgUNetUDP_Stat
\section pgUNetUDP_Common Общее описание \section pgUNetUDP_Common Общее описание
Обмен построен на основе протокола UDP. Обмен построен на основе протокола UDP.
...@@ -57,6 +58,7 @@ namespace uniset ...@@ -57,6 +58,7 @@ namespace uniset
пар [id,value]. Другие узлы принимают их. Помимо этого данный процесс запускает пар [id,value]. Другие узлы принимают их. Помимо этого данный процесс запускает
"получателей" по одному на каждый (другой) узел и ловит пакеты от них, сохраняя данные в SM. "получателей" по одному на каждый (другой) узел и ловит пакеты от них, сохраняя данные в SM.
При этом "получатели" работают на одном(!) потоке с использованием событий libev (см. UNetReceiver). При этом "получатели" работают на одном(!) потоке с использованием событий libev (см. UNetReceiver).
или каждый на своём потоке. Это определяется параметром \b unet_update_strategy.
\par \par
При своём старте процесс считывает из секции \<nodes> список узлов которые необходимо "слушать", При своём старте процесс считывает из секции \<nodes> список узлов которые необходимо "слушать",
...@@ -120,6 +122,19 @@ namespace uniset ...@@ -120,6 +122,19 @@ namespace uniset
При загрузке все датчики (относщиеся к данному процессу) разбиваются на группы пакетов согласно своей частоте посылки. При загрузке все датчики (относщиеся к данному процессу) разбиваются на группы пакетов согласно своей частоте посылки.
При этом внутри одной группы датчики разбиваются по пакетам согласно заданному максимальному размеру пакета При этом внутри одной группы датчики разбиваются по пакетам согласно заданному максимальному размеру пакета
(см. конструктор класса UNetSender()). (см. конструктор класса UNetSender()).
\section pgUNetUDP_Stat Статистика работы канала
Для возможности мониторинга работы имеются счётчики, которые можно привязать к датчикам,
задав их для соответствующего узла в секции '<nodes>' конфигурационного файла.
- unet_lostpackets_id="" - общее количество потерянных пакетов с данным узлом (суммарно по обоим каналам)
- unet_lostpackets1_id="" - количество потерянных пакетов с данным узлом по первому каналу
- unet_lostpackets2_id="" - количество потерянных пакетов с данным узлом по второму каналу
- unet_respond_id="" - наличие связи хотя бы по одному каналу
- unet_respond1_id - наличие связи по первому каналу
- unet_respond2_id - наличие связи по второму каналу
- unet_numchannel_id="" - номер текущего активного канала
- unet_channelswitchcount_id="" - количество переключений с канала на канал
*/ */
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
class UNetExchange: class UNetExchange:
...@@ -233,16 +248,23 @@ namespace uniset ...@@ -233,16 +248,23 @@ namespace uniset
sidChannelNum = id; sidChannelNum = id;
} }
inline void setChannelSwitchCountID( uniset::ObjectId id ) noexcept
{
sidChannelSwitchCount = id;
}
inline void initIterators( const std::shared_ptr<SMInterface>& shm ) noexcept inline void initIterators( const std::shared_ptr<SMInterface>& shm ) noexcept
{ {
shm->initIterator(itLostPackets); shm->initIterator(itLostPackets);
shm->initIterator(itRespond); shm->initIterator(itRespond);
shm->initIterator(itChannelNum); shm->initIterator(itChannelNum);
shm->initIterator(itChannelSwitchCount);
} }
// Сводная информация по двум каналам // Сводная информация по двум каналам
// сумма потерянных пакетов и наличие связи // сумма потерянных пакетов и наличие связи
// хотя бы по одному каналу, номер рабочего канала // хотя бы по одному каналу, номер рабочего канала
// количество переключений с канала на канал
// ( реализацию см. ReceiverInfo::step() ) // ( реализацию см. ReceiverInfo::step() )
uniset::ObjectId sidRespond; uniset::ObjectId sidRespond;
IOController::IOStateList::iterator itRespond; IOController::IOStateList::iterator itRespond;
...@@ -251,6 +273,10 @@ namespace uniset ...@@ -251,6 +273,10 @@ namespace uniset
IOController::IOStateList::iterator itLostPackets; IOController::IOStateList::iterator itLostPackets;
uniset::ObjectId sidChannelNum; uniset::ObjectId sidChannelNum;
IOController::IOStateList::iterator itChannelNum; IOController::IOStateList::iterator itChannelNum;
long channelSwitchCount = { 0 }; /*!< счётчик переключений с канала на канал */
uniset::ObjectId sidChannelSwitchCount = { uniset::DefaultObjectId };
IOController::IOStateList::iterator itChannelSwitchCount;
}; };
typedef std::deque<ReceiverInfo> ReceiverList; typedef std::deque<ReceiverInfo> ReceiverList;
......
...@@ -242,7 +242,7 @@ namespace uniset ...@@ -242,7 +242,7 @@ namespace uniset
UNetReceiver(); UNetReceiver();
timeout_t recvpause = { 10 }; /*!< пауза меджду приёмами пакетов, [мсек] */ timeout_t recvpause = { 10 }; /*!< пауза меджду приёмами пакетов, [мсек] */
timeout_t updatepause = { 100 }; /*!< переодичность обновления данных в SM, [мсек] */ timeout_t updatepause = { 100 }; /*!< переодичность обновления данных в SM, [мсек] */
std::unique_ptr<UDPReceiveU> udp; std::unique_ptr<UDPReceiveU> udp;
std::string addr; std::string addr;
......
...@@ -29,6 +29,7 @@ static ObjectId node2_lostpackets_as = 13; ...@@ -29,6 +29,7 @@ static ObjectId node2_lostpackets_as = 13;
static int maxDifferense = 5; // см. unetudp-test-configure.xml --unet-maxdifferense static int maxDifferense = 5; // см. unetudp-test-configure.xml --unet-maxdifferense
static int recvTimeout = 1000; // --unet-recv-timeout static int recvTimeout = 1000; // --unet-recv-timeout
static ObjectId node1_numchannel_as = 14; static ObjectId node1_numchannel_as = 14;
static ObjectId node1_channelSwitchCount_as = 15;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void InitTest() void InitTest()
{ {
...@@ -462,6 +463,9 @@ TEST_CASE("[UNetUDP]: switching channels", "[unetudp][chswitch]") ...@@ -462,6 +463,9 @@ TEST_CASE("[UNetUDP]: switching channels", "[unetudp][chswitch]")
msleep(120); msleep(120);
REQUIRE( ui->getValue(8) == 70 ); REQUIRE( ui->getValue(8) == 70 );
// и счётчик переключений каналов в нуле
REQUIRE( ui->getValue(node1_channelSwitchCount_as) == 0 );
// К сожалению в текущей реализации тестов // К сожалению в текущей реализации тестов
// обмена по второму каналу нет // обмена по второму каналу нет
// поэтому проверить переключение нет возможности // поэтому проверить переключение нет возможности
...@@ -469,6 +473,9 @@ TEST_CASE("[UNetUDP]: switching channels", "[unetudp][chswitch]") ...@@ -469,6 +473,9 @@ TEST_CASE("[UNetUDP]: switching channels", "[unetudp][chswitch]")
// т.к. на втором нет связи и мы не должны на него переключаться // т.к. на втором нет связи и мы не должны на него переключаться
msleep(recvTimeout * 2); msleep(recvTimeout * 2);
REQUIRE( ui->getValue(node1_numchannel_as) == 1 ); REQUIRE( ui->getValue(node1_numchannel_as) == 1 );
// и счётчик переключений каналов остался в нуле
REQUIRE( ui->getValue(node1_channelSwitchCount_as) == 0 );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_CASE("[UNetUDP]: check undefined value", "[unetudp][sender]") TEST_CASE("[UNetUDP]: check undefined value", "[unetudp][sender]")
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
<nodes port="2809" unet_broadcast_ip="127.255.255.255" unet_broadcast_ip2="badip"> <nodes port="2809" unet_broadcast_ip="127.255.255.255" unet_broadcast_ip2="badip">
<item id="3000" ip="127.0.0.1" name="localhost" textname="Локальный узел" unet_ignore="0" unet_port="3000"/> <item id="3000" ip="127.0.0.1" name="localhost" textname="Локальный узел" unet_ignore="0" unet_port="3000"/>
<item id="3001" ip="127.0.0.1" name="localhost1" textname="Локальный узел" unet_ignore="1" unet_port="3001"/> <item id="3001" ip="127.0.0.1" name="localhost1" textname="Локальный узел" unet_ignore="1" unet_port="3001"/>
<item id="3002" ip="192.168.56.10" name="Node1" textname="Node1" unet_ignore="0" unet_respond_id="Node1_Not_Respond_S" unet_respond_invert="1"/> <item id="3002" ip="192.168.56.10" name="Node1" textname="Node1" unet_ignore="0" unet_respond_id="Node1_Not_Respond_S" unet_respond_invert="1" unet_channelswitchcount_id="Node1_ChannelSwitchCount_AS"/>
<item id="3003" ip="192.168.56.11" name="Node2" textname="Node2" unet_ignore="0" unet_respond_id="Node2_Respond_S" unet_lostpackets_id="Node2_LostPackets_AS" unet_numchannel_id="Node2_NumChannel_AS"/> <item id="3003" ip="192.168.56.11" name="Node2" textname="Node2" unet_ignore="0" unet_respond_id="Node2_Respond_S" unet_lostpackets_id="Node2_LostPackets_AS" unet_numchannel_id="Node2_NumChannel_AS"/>
</nodes> </nodes>
<!-- ************************ Датчики ********************** --> <!-- ************************ Датчики ********************** -->
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
<item id="12" iotype="DI" name="Node2_Respond_S" textname="Node2 respond"/> <item id="12" iotype="DI" name="Node2_Respond_S" textname="Node2 respond"/>
<item id="13" iotype="AI" name="Node2_LostPackets_AS" textname="Node2 lost packets"/> <item id="13" iotype="AI" name="Node2_LostPackets_AS" textname="Node2 lost packets"/>
<item id="14" iotype="AI" name="Node2_NumChannel_AS" textname="Node2 num channel"/> <item id="14" iotype="AI" name="Node2_NumChannel_AS" textname="Node2 num channel"/>
<item id="15" iotype="AI" name="Node1_ChannelSwitchCount_AS" textname="Node1 channel switch count"/>
</sensors> </sensors>
<thresholds name="thresholds"/> <thresholds name="thresholds"/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment