Commit 9d59a0d8 authored by Pavel Vainerman's avatar Pavel Vainerman

(UNetUDP): небольшая оптимизация при обработке пакетов (спасибо uzum),

дописал немного тестов, корректировка значений по умолчанию.
parent 50b9549f
...@@ -9,7 +9,7 @@ int main( int argc, char **argv ) ...@@ -9,7 +9,7 @@ int main( int argc, char **argv )
{ {
if( argc < 2 || (argc > 1 && ( !strcmp(argv[1],"--help") || !strcmp(argv[1],"-h"))) ) if( argc < 2 || (argc > 1 && ( !strcmp(argv[1],"--help") || !strcmp(argv[1],"-h"))) )
{ {
cout << "Usage: lo2gval info,warn,crit,.... " << endl; cout << "Usage: lo2gval [ info,warn,crit,level1...level9,init,repository,system,exception | any ]" << endl;
return 0; return 0;
} }
......
...@@ -411,6 +411,7 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname ...@@ -411,6 +411,7 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
%changelog %changelog
* Thu Mar 12 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt21 * Thu Mar 12 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt21
- codegen: adjustment documentation - codegen: adjustment documentation
- unetudp: add tests, minor optimization (thank`s uzum)
* Fri Mar 06 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt20 * Fri Mar 06 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt20
- (modbustcpmaster): minor fixes in error messages - (modbustcpmaster): minor fixes in error messages
......
...@@ -39,12 +39,12 @@ no_sender(false) ...@@ -39,12 +39,12 @@ no_sender(false)
int recvTimeout = conf->getArgPInt("--" + prefix + "-recv-timeout",it.getProp("recvTimeout"), 5000); int recvTimeout = conf->getArgPInt("--" + prefix + "-recv-timeout",it.getProp("recvTimeout"), 5000);
int prepareTime = conf->getArgPInt("--" + prefix + "-preapre-time",it.getProp("prepareTime"), 2000); int prepareTime = conf->getArgPInt("--" + prefix + "-preapre-time",it.getProp("prepareTime"), 2000);
int lostTimeout = conf->getArgPInt("--" + prefix + "-lost-timeout",it.getProp("lostTimeout"), recvTimeout);
int recvpause = conf->getArgPInt("--" + prefix + "-recvpause",it.getProp("recvpause"), 10); int recvpause = conf->getArgPInt("--" + prefix + "-recvpause",it.getProp("recvpause"), 10);
int sendpause = conf->getArgPInt("--" + prefix + "-sendpause",it.getProp("sendpause"), 100); int sendpause = conf->getArgPInt("--" + prefix + "-sendpause",it.getProp("sendpause"), 100);
int updatepause = conf->getArgPInt("--" + prefix + "-updatepause",it.getProp("updatepause"), 100); int updatepause = conf->getArgPInt("--" + prefix + "-updatepause",it.getProp("updatepause"), 100);
int lostTimeout = conf->getArgPInt("--" + prefix + "-lost-timeout",it.getProp("lostTimeout"), 2*updatepause);
steptime = conf->getArgPInt("--" + prefix + "-steptime",it.getProp("steptime"), 1000); steptime = conf->getArgPInt("--" + prefix + "-steptime",it.getProp("steptime"), 1000);
int maxDiff = conf->getArgPInt("--" + prefix + "-maxdifferense",it.getProp("maxDifferense"), 1000); int maxDiff = conf->getArgPInt("--" + prefix + "-maxdifferense",it.getProp("maxDifferense"), 100);
int maxProcessingCount = conf->getArgPInt("--" + prefix + "-maxprocessingcount",it.getProp("maxProcessingCount"), 100); int maxProcessingCount = conf->getArgPInt("--" + prefix + "-maxprocessingcount",it.getProp("maxProcessingCount"), 100);
no_sender = conf->getArgInt("--" + prefix + "-nosender",it.getProp("nosender")); no_sender = conf->getArgInt("--" + prefix + "-nosender",it.getProp("nosender"));
......
...@@ -25,14 +25,14 @@ recvpause(10), ...@@ -25,14 +25,14 @@ recvpause(10),
updatepause(100), updatepause(100),
recvTimeout(5000), recvTimeout(5000),
prepareTime(2000), prepareTime(2000),
lostTimeout(5000), lostTimeout(200), /* 2*updatepause */
lostPackets(0), lostPackets(0),
sidRespond(UniSetTypes::DefaultObjectId), sidRespond(UniSetTypes::DefaultObjectId),
respondInvert(false), respondInvert(false),
sidLostPackets(UniSetTypes::DefaultObjectId), sidLostPackets(UniSetTypes::DefaultObjectId),
activated(false), activated(false),
pnum(0), pnum(0),
maxDifferens(1000), maxDifferens(20),
waitClean(false), waitClean(false),
rnum(0), rnum(0),
maxProcessingCount(100), maxProcessingCount(100),
...@@ -245,10 +245,20 @@ void UNetReceiver::real_update() ...@@ -245,10 +245,20 @@ void UNetReceiver::real_update()
// чтобы констатировать потерю пакета.. // чтобы констатировать потерю пакета..
if( sub > 1 && sub < maxDifferens ) if( sub > 1 && sub < maxDifferens )
{ {
// если p.num < pnum, то это какой-то "дубль",
// т.к мы все пакеты <= pnum уже "отработали".
// а значит можно не ждать, а откидывать пакет и
// дальше работать..
if( p.num < pnum )
{
qpack.pop();
continue;
}
if( !ptLostTimeout.checkTime() ) if( !ptLostTimeout.checkTime() )
return; return;
lostPackets++; lostPackets += sub;
} }
else if( p.num == pnum ) else if( p.num == pnum )
{ {
...@@ -256,9 +266,16 @@ void UNetReceiver::real_update() ...@@ -256,9 +266,16 @@ void UNetReceiver::real_update()
* для надёжности лучше обрабатывать.. * для надёжности лучше обрабатывать..
* для "оптимизации".. лучше игнорировать * для "оптимизации".. лучше игнорировать
*/ */
qpack.pop(); // пока выбрали вариант "оптимизации" qpack.pop(); // пока выбрали вариант "оптимизации" (выкидываем из очереди и идём дальше)
continue; continue;
} }
if( sub >= maxDifferens )
{
// считаем сколько пакетов потеряли..
if( p.num > pnum )
lostPackets+=sub;
}
} }
ptLostTimeout.reset(); ptLostTimeout.reset();
......
...@@ -65,7 +65,7 @@ class UNetReceiver: ...@@ -65,7 +65,7 @@ class UNetReceiver:
inline std::string getName(){ return myname; } inline std::string getName(){ return myname; }
// блокировать сохранение данный в SM // блокировать сохранение данных в SM
void setLockUpdate( bool st ); void setLockUpdate( bool st );
void resetTimeout(); void resetTimeout();
...@@ -110,6 +110,19 @@ class UNetReceiver: ...@@ -110,6 +110,19 @@ class UNetReceiver:
void initIterators(); void initIterators();
public:
// функция определения приоритетного сообщения для обработки
struct PacketCompare:
public std::binary_function<UniSetUDP::UDPMessage, UniSetUDP::UDPMessage, bool>
{
inline bool operator()(const UniSetUDP::UDPMessage& lhs,
const UniSetUDP::UDPMessage& rhs) const
{ return lhs.num > rhs.num; }
};
typedef std::priority_queue<UniSetUDP::UDPMessage,std::vector<UniSetUDP::UDPMessage>,PacketCompare> PacketQueue;
private: private:
UNetReceiver(); UNetReceiver();
...@@ -141,15 +154,6 @@ class UNetReceiver: ...@@ -141,15 +154,6 @@ class UNetReceiver:
std::shared_ptr< ThreadCreator<UNetReceiver> > r_thr; // receive thread std::shared_ptr< ThreadCreator<UNetReceiver> > r_thr; // receive thread
std::shared_ptr< ThreadCreator<UNetReceiver> > u_thr; // update thread std::shared_ptr< ThreadCreator<UNetReceiver> > u_thr; // update thread
// функция определения приоритетного сообщения для обработки
struct PacketCompare:
public std::binary_function<UniSetUDP::UDPMessage, UniSetUDP::UDPMessage, bool>
{
inline bool operator()(const UniSetUDP::UDPMessage& lhs,
const UniSetUDP::UDPMessage& rhs) const
{ return lhs.num > rhs.num; }
};
typedef std::priority_queue<UniSetUDP::UDPMessage,std::vector<UniSetUDP::UDPMessage>,PacketCompare> PacketQueue;
PacketQueue qpack; /*!< очередь принятых пакетов (отсортированных по возрастанию номера пакета) */ PacketQueue qpack; /*!< очередь принятых пакетов (отсортированных по возрастанию номера пакета) */
UniSetUDP::UDPMessage pack; /*!< просто буфер для получения очередного сообщения */ UniSetUDP::UDPMessage pack; /*!< просто буфер для получения очередного сообщения */
UniSetUDP::UDPPacket r_buf; UniSetUDP::UDPPacket r_buf;
......
...@@ -24,6 +24,8 @@ static int s_nodeID = 3003; ...@@ -24,6 +24,8 @@ static int s_nodeID = 3003;
static int s_procID = 123; static int s_procID = 123;
static int s_numpack = 1; static int s_numpack = 1;
static ObjectId node2_respond_s = 12; static ObjectId node2_respond_s = 12;
static ObjectId node2_lostpackets_as = 13;
static int maxDifferense = 5; // см. unetudp-test-configure.xml --unet-maxdifferense
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void InitTest() void InitTest()
{ {
...@@ -47,7 +49,7 @@ void InitTest() ...@@ -47,7 +49,7 @@ void InitTest()
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// pnum - минималный номер ожидаемого пакета ( 0 - любой пришедщий ) // pnum - минималный номер ожидаемого пакета ( 0 - любой пришедщий )
// ncycle - сколько пакетов разрещено "пропустить" прежде чем дождёмся нужного.. (чтобы не ждать бесконечно) // ncycle - сколько пакетов разрешено "пропустить" прежде чем дождёмся нужного.. (чтобы не ждать бесконечно)
static UniSetUDP::UDPMessage receive( unsigned int pnum = 0, timeout_t tout = 2000, int ncycle = 10 ) static UniSetUDP::UDPMessage receive( unsigned int pnum = 0, timeout_t tout = 2000, int ncycle = 10 )
{ {
UniSetUDP::UDPMessage pack; UniSetUDP::UDPMessage pack;
...@@ -84,6 +86,44 @@ void send( UniSetUDP::UDPMessage& pack, int tout=2000 ) ...@@ -84,6 +86,44 @@ void send( UniSetUDP::UDPMessage& pack, int tout=2000 )
REQUIRE( ret == s_buf.len ); REQUIRE( ret == s_buf.len );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_CASE("[UNetUDP]: queue sort","[unetudp][packetqueue]")
{
UNetReceiver::PacketQueue q;
UniSetUDP::UDPMessage m1;
m1.num = 10;
UniSetUDP::UDPMessage m2;
m2.num = 11;
UniSetUDP::UDPMessage m3;
m3.num = 13;
UniSetUDP::UDPMessage m4;
m4.num = 100;
// специально сладываем в обратном порядке
// чтобы проверить "сортировку"
q.push(m1);
q.push(m3);
q.push(m2);
q.push(m4);
UniSetUDP::UDPMessage t = q.top();
REQUIRE( t.num == 10 );
q.pop();
t = q.top();
REQUIRE( t.num == 11 );
q.pop();
t = q.top();
REQUIRE( t.num == 13 );
q.pop();
t = q.top();
REQUIRE( t.num == 100 );
q.pop();
}
// -----------------------------------------------------------------------------
TEST_CASE("[UNetUDP]: UDPMessage","[unetudp][udpmessage]") TEST_CASE("[UNetUDP]: UDPMessage","[unetudp][udpmessage]")
{ {
SECTION("UDPMessage::isFull()") SECTION("UDPMessage::isFull()")
...@@ -260,3 +300,120 @@ TEST_CASE("[UNetUDP]: check receiver","[unetudp][receiver]") ...@@ -260,3 +300,120 @@ TEST_CASE("[UNetUDP]: check receiver","[unetudp][receiver]")
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_CASE("[UNetUDP]: check packets 'hole'","[unetudp][udphole]")
{
InitTest();
// проверяем обработку "дырок" в пакетах..
UniSetUDP::UDPMessage pack;
pack.addAData(8,15);
send(pack);
msleep(120);
REQUIRE( ui->getValue(8) == 15 );
unsigned long nlost = ui->getValue(node2_lostpackets_as);
int lastnum = s_numpack-1;
// искуственно делаем дырку в два пакета
s_numpack = lastnum+3;
UniSetUDP::UDPMessage pack_hole;
pack_hole.addAData(8,30);
send(pack_hole); // пакет с дыркой
msleep(120);
REQUIRE( ui->getValue(8) == 15 );
REQUIRE( ui->getValue(node2_lostpackets_as) == nlost );
s_numpack = lastnum+1;
UniSetUDP::UDPMessage pack1;
pack1.addAData(8,21);
send(pack1); // заполняем первую дырку..// дырка закроется.. пакет тут же обработается
msleep(120);
REQUIRE( ui->getValue(8) == 21 );
REQUIRE( ui->getValue(node2_lostpackets_as) == nlost );
s_numpack = lastnum+2;
UniSetUDP::UDPMessage pack2;
pack2.addAData(8,25);
send(pack2); // заполняем следующую дырку
msleep(120);
// тут обработка дойдёт уже до "первого" пакета..
REQUIRE( ui->getValue(8) == 30 );
REQUIRE( ui->getValue(node2_lostpackets_as) == nlost );
// возвращаем к нормальному..чтобы следующие тесты не поломались..
for( int i=0; i<10; i++ )
send(pack2);
}
// -----------------------------------------------------------------------------
TEST_CASE("[UNetUDP]: check packets 'MaxDifferens'","[unetudp][maxdifferens]")
{
InitTest();
// проверяем обработку "дырок" в пакетах..
UniSetUDP::UDPMessage pack;
pack.addAData(8,50);
send(pack);
msleep(1000);
REQUIRE( ui->getValue(8) == 50 );
unsigned long nlost = ui->getValue(node2_lostpackets_as);
int need_num = s_numpack;
// искуственно делаем дырку в два пакета
s_numpack += maxDifferense+1;
UniSetUDP::UDPMessage pack_hole;
pack_hole.addAData(8,150);
send(pack_hole); // пакет с дыркой > maxDifference (должен обработаться)
msleep(120);
REQUIRE( ui->getValue(8) == 150 );
msleep(2000);
REQUIRE( ui->getValue(node2_lostpackets_as) > nlost );
}
// -----------------------------------------------------------------------------
TEST_CASE("[UNetUDP]: bad packet number","[unetudp][badnumber]")
{
InitTest();
// посылаем нормальный пакет
UniSetUDP::UDPMessage pack;
pack.addAData(8,60);
send(pack);
msleep(120);
REQUIRE( ui->getValue(8) == 60 );
int lastpack = s_numpack-1;
// посылаем пакет с тем же номером
s_numpack = lastpack;
UniSetUDP::UDPMessage pack1;
pack1.addAData(8,150);
send(pack1); // должен быть "откинут"
msleep(120);
REQUIRE( ui->getValue(8) == 60 );
// посылаем пакет с меньшим номером
s_numpack=lastpack-2;
UniSetUDP::UDPMessage pack2;
pack2.addAData(8,155);
send(pack2); // должен быть "откинут"
msleep(120);
REQUIRE( ui->getValue(8) == 60 );
// посылаем нормальный
s_numpack=lastpack+1;
UniSetUDP::UDPMessage pack3;
pack3.addAData(8,160);
send(pack3); // должен быть "обработан"
msleep(120);
REQUIRE( ui->getValue(8) == 160 );
}
// -----------------------------------------------------------------------------
...@@ -39,7 +39,7 @@ int main(int argc, char* argv[] ) ...@@ -39,7 +39,7 @@ int main(int argc, char* argv[] )
if( !shm ) if( !shm )
return 1; return 1;
auto unet = UNetExchange::init_unetexchange(argc,argv,shm->getId(), (apart ? nullptr : shm )); auto unet = UNetExchange::init_unetexchange(argc,argv,shm->getId(), (apart ? nullptr : shm ),"unet");
if( !unet ) if( !unet )
return 1; return 1;
......
...@@ -9,5 +9,5 @@ cd ../../../Utilities/Admin/ ...@@ -9,5 +9,5 @@ cd ../../../Utilities/Admin/
cd - cd -
./uniset2-start.sh -f ./tests-with-sm $* -- --confile unetudp-test-configure.xml --e-startup-pause 10 \ ./uniset2-start.sh -f ./tests-with-sm $* -- --confile unetudp-test-configure.xml --e-startup-pause 10 \
--unet-name UNetExchange --unet-filter-field unet --unet-filter-value 1 --unet-maxdifferense 40 \ --unet-name UNetExchange --unet-filter-field unet --unet-filter-value 1 --unet-maxdifferense 5 \
--unet-recv-timeout 1000 --unet-sendpause 500 --unet-recv-timeout 1000 --unet-sendpause 500
#!/bin/sh
# '--' - нужен для отделения аргументов catch, от наших..
cd ../../../Utilities/Admin/
./uniset2-start.sh -f ./create_links.sh
./uniset2-start.sh -f ./create
./uniset2-start.sh -f ./exist | grep -q UNISET_PLC/Controllers || exit 1
cd -
./uniset2-start.sh -f ./tests-with-sm $* -- --apart --confile mbslave-test-configure.xml --e-startup-pause 10 \
--mbs-name MBSlave1 --mbs-type TCP --mbs-inet-addr 127.0.0.1 --mbs-inet-port 20048 --mbs-my-addr 0x01 \
--mbs-askcount-id SVU_AskCount_AS --mbs-respond-id RespondRTU_S --mbs-respond-invert 1 \
--mbs-filter-field mbs --mbs-filter-value 1
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
<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_ip="192.168.56.255" unet_respond_id="Node1_Respond_S" unet_respond_invert="1"/> <item id="3002" ip="192.168.56.10" name="Node1" textname="Node1" unet_ignore="0" unet_ip="192.168.56.255" unet_respond_id="Node1_Respond_S" unet_respond_invert="1"/>
<item id="3003" ip="192.168.56.11" name="Node2" textname="Node2" unet_ignore="0" unet_ip="192.168.56.255" unet_respond_id="Node2_Respond_S"/> <item id="3003" ip="192.168.56.11" name="Node2" textname="Node2" unet_ignore="0" unet_ip="192.168.56.255" unet_respond_id="Node2_Respond_S" unet_lostpackets_id="Node2_LostPackets_AS"/>
</nodes> </nodes>
<!-- ************************ Датчики ********************** --> <!-- ************************ Датчики ********************** -->
<sensors name="Sensors"> <sensors name="Sensors">
...@@ -54,6 +54,8 @@ ...@@ -54,6 +54,8 @@
<item id="10" iotype="DI" name="DI3_S" textname="DI sensor 3"/> <item id="10" iotype="DI" name="DI3_S" textname="DI sensor 3"/>
<item id="11" iotype="DI" name="DI4_S" textname="DI sensor 4"/> <item id="11" iotype="DI" name="DI4_S" textname="DI sensor 4"/>
<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"/>
</sensors> </sensors>
<thresholds name="thresholds"/> <thresholds name="thresholds"/>
<controllers name="Controllers"> <controllers name="Controllers">
......
...@@ -580,7 +580,6 @@ extensions/UNetUDP/UDPPacket.h ...@@ -580,7 +580,6 @@ extensions/UNetUDP/UDPPacket.h
extensions/UNetUDP/unet-udp-tester.cc extensions/UNetUDP/unet-udp-tester.cc
extensions/UNetUDP/UNetExchange.cc extensions/UNetUDP/UNetExchange.cc
extensions/UNetUDP/unetexchange.cc extensions/UNetUDP/unetexchange.cc
extensions/UNetUDP/UNetExchange.cc.c
extensions/UNetUDP/UNetExchange.h extensions/UNetUDP/UNetExchange.h
extensions/UNetUDP/UNetReceiver.cc extensions/UNetUDP/UNetReceiver.cc
extensions/UNetUDP/UNetReceiver.h extensions/UNetUDP/UNetReceiver.h
......
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