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
if( resp_id == uniset::DefaultObjectId )
{
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;
throw SystemError(err.str());
}
......@@ -228,7 +228,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( resp2_id == uniset::DefaultObjectId )
{
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;
throw SystemError(err.str());
}
......@@ -244,7 +244,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( lp_id == uniset::DefaultObjectId )
{
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;
throw SystemError(err.str());
}
......@@ -260,7 +260,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( lp2_id == uniset::DefaultObjectId )
{
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;
throw SystemError(err.str());
}
......@@ -276,7 +276,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( lp_comm_id == uniset::DefaultObjectId )
{
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;
throw SystemError(err.str());
}
......@@ -292,7 +292,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( resp_comm_id == uniset::DefaultObjectId )
{
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;
throw SystemError(err.str());
}
......@@ -308,7 +308,23 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
if( numchannel_id == uniset::DefaultObjectId )
{
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;
throw SystemError(err.str());
}
......@@ -393,6 +409,7 @@ UNetExchange::UNetExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const
ri.setRespondID(resp_comm_id, resp_invert);
ri.setLostPacketsID(lp_comm_id);
ri.setChannelNumID(numchannel_id);
ri.setChannelSwitchCountID(channelswitchcount_id);
recvlist.emplace_back( std::move(ri) );
}
......@@ -594,6 +611,16 @@ void UNetExchange::ReceiverInfo::step( const std::shared_ptr<SMInterface>& shm,
{
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 )
......@@ -901,6 +928,7 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive
// переключаемся на второй
it.r1->setLockUpdate(true);
it.r2->setLockUpdate(false);
it.channelSwitchCount++;
dlog8 << myname << "(event): " << r->getName()
<< ": timeout for channel1.. select channel 2" << endl;
......@@ -917,6 +945,13 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive
if( it.r2 )
it.r2->setLockUpdate(true);
// если какой-то канал уже работал
// то увеличиваем счётчик переключений
// а если ещё не работал, значит это просто первое включение канала
// а не переключение
if( it.channelSwitchCount > 0 )
it.channelSwitchCount++;
dlog8 << myname << "(event): " << r->getName()
<< ": link failed for channel2.. select again channel1.." << endl;
}
......@@ -938,6 +973,7 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive
// переключаемся на первый
it.r1->setLockUpdate(false);
it.r2->setLockUpdate(true);
it.channelSwitchCount++;
dlog8 << myname << "(event): " << r->getName()
<< ": timeout for channel2.. select channel 1" << endl;
......@@ -954,6 +990,13 @@ void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceive
it.r2->setLockUpdate(false);
// если какой-то канал уже работал
// то увеличиваем счётчик переключений
// а если ещё не работал, значит это просто первое включение канала
// а не переключение
if( it.channelSwitchCount > 0 )
it.channelSwitchCount++;
dlog8 << myname << "(event): " << r->getName()
<< ": link failed for channel1.. select again channel2.." << endl;
}
......
......@@ -49,6 +49,7 @@ namespace uniset
- \ref pgUNetUDP_Conf
- \ref pgUNetUDP_Reserv
- \ref pgUNetUDP_SendFactor
- \ref pgUNetUDP_Stat
\section pgUNetUDP_Common Общее описание
Обмен построен на основе протокола UDP.
......@@ -57,6 +58,7 @@ namespace uniset
пар [id,value]. Другие узлы принимают их. Помимо этого данный процесс запускает
"получателей" по одному на каждый (другой) узел и ловит пакеты от них, сохраняя данные в SM.
При этом "получатели" работают на одном(!) потоке с использованием событий libev (см. UNetReceiver).
или каждый на своём потоке. Это определяется параметром \b unet_update_strategy.
\par
При своём старте процесс считывает из секции \<nodes> список узлов которые необходимо "слушать",
......@@ -120,6 +122,19 @@ namespace uniset
При загрузке все датчики (относщиеся к данному процессу) разбиваются на группы пакетов согласно своей частоте посылки.
При этом внутри одной группы датчики разбиваются по пакетам согласно заданному максимальному размеру пакета
(см. конструктор класса 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:
......@@ -233,16 +248,23 @@ namespace uniset
sidChannelNum = id;
}
inline void setChannelSwitchCountID( uniset::ObjectId id ) noexcept
{
sidChannelSwitchCount = id;
}
inline void initIterators( const std::shared_ptr<SMInterface>& shm ) noexcept
{
shm->initIterator(itLostPackets);
shm->initIterator(itRespond);
shm->initIterator(itChannelNum);
shm->initIterator(itChannelSwitchCount);
}
// Сводная информация по двум каналам
// сумма потерянных пакетов и наличие связи
// хотя бы по одному каналу, номер рабочего канала
// количество переключений с канала на канал
// ( реализацию см. ReceiverInfo::step() )
uniset::ObjectId sidRespond;
IOController::IOStateList::iterator itRespond;
......@@ -251,6 +273,10 @@ namespace uniset
IOController::IOStateList::iterator itLostPackets;
uniset::ObjectId sidChannelNum;
IOController::IOStateList::iterator itChannelNum;
long channelSwitchCount = { 0 }; /*!< счётчик переключений с канала на канал */
uniset::ObjectId sidChannelSwitchCount = { uniset::DefaultObjectId };
IOController::IOStateList::iterator itChannelSwitchCount;
};
typedef std::deque<ReceiverInfo> ReceiverList;
......
......@@ -242,7 +242,7 @@ namespace uniset
UNetReceiver();
timeout_t recvpause = { 10 }; /*!< пауза меджду приёмами пакетов, [мсек] */
timeout_t updatepause = { 100 }; /*!< переодичность обновления данных в SM, [мсек] */
timeout_t updatepause = { 100 }; /*!< переодичность обновления данных в SM, [мсек] */
std::unique_ptr<UDPReceiveU> udp;
std::string addr;
......
......@@ -29,6 +29,7 @@ static ObjectId node2_lostpackets_as = 13;
static int maxDifferense = 5; // см. unetudp-test-configure.xml --unet-maxdifferense
static int recvTimeout = 1000; // --unet-recv-timeout
static ObjectId node1_numchannel_as = 14;
static ObjectId node1_channelSwitchCount_as = 15;
// -----------------------------------------------------------------------------
void InitTest()
{
......@@ -462,6 +463,9 @@ TEST_CASE("[UNetUDP]: switching channels", "[unetudp][chswitch]")
msleep(120);
REQUIRE( ui->getValue(8) == 70 );
// и счётчик переключений каналов в нуле
REQUIRE( ui->getValue(node1_channelSwitchCount_as) == 0 );
// К сожалению в текущей реализации тестов
// обмена по второму каналу нет
// поэтому проверить переключение нет возможности
......@@ -469,6 +473,9 @@ TEST_CASE("[UNetUDP]: switching channels", "[unetudp][chswitch]")
// т.к. на втором нет связи и мы не должны на него переключаться
msleep(recvTimeout * 2);
REQUIRE( ui->getValue(node1_numchannel_as) == 1 );
// и счётчик переключений каналов остался в нуле
REQUIRE( ui->getValue(node1_channelSwitchCount_as) == 0 );
}
// -----------------------------------------------------------------------------
TEST_CASE("[UNetUDP]: check undefined value", "[unetudp][sender]")
......
......@@ -35,7 +35,7 @@
<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="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"/>
</nodes>
<!-- ************************ Датчики ********************** -->
......@@ -56,6 +56,7 @@
<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="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>
<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