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

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

дописал немного тестов, корректировка значений по умолчанию.
parent 50b9549f
......@@ -9,7 +9,7 @@ int main( int argc, char **argv )
{
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;
}
......
......@@ -411,6 +411,7 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
%changelog
* Thu Mar 12 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt21
- codegen: adjustment documentation
- unetudp: add tests, minor optimization (thank`s uzum)
* Fri Mar 06 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt20
- (modbustcpmaster): minor fixes in error messages
......
......@@ -39,12 +39,12 @@ no_sender(false)
int recvTimeout = conf->getArgPInt("--" + prefix + "-recv-timeout",it.getProp("recvTimeout"), 5000);
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 sendpause = conf->getArgPInt("--" + prefix + "-sendpause",it.getProp("sendpause"), 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);
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);
no_sender = conf->getArgInt("--" + prefix + "-nosender",it.getProp("nosender"));
......
......@@ -25,14 +25,14 @@ recvpause(10),
updatepause(100),
recvTimeout(5000),
prepareTime(2000),
lostTimeout(5000),
lostTimeout(200), /* 2*updatepause */
lostPackets(0),
sidRespond(UniSetTypes::DefaultObjectId),
respondInvert(false),
sidLostPackets(UniSetTypes::DefaultObjectId),
activated(false),
pnum(0),
maxDifferens(1000),
maxDifferens(20),
waitClean(false),
rnum(0),
maxProcessingCount(100),
......@@ -245,10 +245,20 @@ void UNetReceiver::real_update()
// чтобы констатировать потерю пакета..
if( sub > 1 && sub < maxDifferens )
{
// если p.num < pnum, то это какой-то "дубль",
// т.к мы все пакеты <= pnum уже "отработали".
// а значит можно не ждать, а откидывать пакет и
// дальше работать..
if( p.num < pnum )
{
qpack.pop();
continue;
}
if( !ptLostTimeout.checkTime() )
return;
lostPackets++;
lostPackets += sub;
}
else if( p.num == pnum )
{
......@@ -256,9 +266,16 @@ void UNetReceiver::real_update()
* для надёжности лучше обрабатывать..
* для "оптимизации".. лучше игнорировать
*/
qpack.pop(); // пока выбрали вариант "оптимизации"
qpack.pop(); // пока выбрали вариант "оптимизации" (выкидываем из очереди и идём дальше)
continue;
}
if( sub >= maxDifferens )
{
// считаем сколько пакетов потеряли..
if( p.num > pnum )
lostPackets+=sub;
}
}
ptLostTimeout.reset();
......
......@@ -65,7 +65,7 @@ class UNetReceiver:
inline std::string getName(){ return myname; }
// блокировать сохранение данный в SM
// блокировать сохранение данных в SM
void setLockUpdate( bool st );
void resetTimeout();
......@@ -110,6 +110,19 @@ class UNetReceiver:
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:
UNetReceiver();
......@@ -141,15 +154,6 @@ class UNetReceiver:
std::shared_ptr< ThreadCreator<UNetReceiver> > r_thr; // receive 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; /*!< очередь принятых пакетов (отсортированных по возрастанию номера пакета) */
UniSetUDP::UDPMessage pack; /*!< просто буфер для получения очередного сообщения */
UniSetUDP::UDPPacket r_buf;
......
......@@ -24,6 +24,8 @@ static int s_nodeID = 3003;
static int s_procID = 123;
static int s_numpack = 1;
static ObjectId node2_respond_s = 12;
static ObjectId node2_lostpackets_as = 13;
static int maxDifferense = 5; // см. unetudp-test-configure.xml --unet-maxdifferense
// -----------------------------------------------------------------------------
void InitTest()
{
......@@ -47,7 +49,7 @@ void InitTest()
}
// -----------------------------------------------------------------------------
// pnum - минималный номер ожидаемого пакета ( 0 - любой пришедщий )
// ncycle - сколько пакетов разрещено "пропустить" прежде чем дождёмся нужного.. (чтобы не ждать бесконечно)
// ncycle - сколько пакетов разрешено "пропустить" прежде чем дождёмся нужного.. (чтобы не ждать бесконечно)
static UniSetUDP::UDPMessage receive( unsigned int pnum = 0, timeout_t tout = 2000, int ncycle = 10 )
{
UniSetUDP::UDPMessage pack;
......@@ -84,6 +86,44 @@ void send( UniSetUDP::UDPMessage& pack, int tout=2000 )
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]")
{
SECTION("UDPMessage::isFull()")
......@@ -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[] )
if( !shm )
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 )
return 1;
......
......@@ -9,5 +9,5 @@ cd ../../../Utilities/Admin/
cd -
./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
#!/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 @@
<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_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>
<!-- ************************ Датчики ********************** -->
<sensors name="Sensors">
......@@ -54,6 +54,8 @@
<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="12" iotype="DI" name="Node2_Respond_S" textname="Node2 respond"/>
<item id="13" iotype="AI" name="Node2_LostPackets_AS" textname="Node2 lost packets"/>
</sensors>
<thresholds name="thresholds"/>
<controllers name="Controllers">
......
......@@ -580,7 +580,6 @@ extensions/UNetUDP/UDPPacket.h
extensions/UNetUDP/unet-udp-tester.cc
extensions/UNetUDP/UNetExchange.cc
extensions/UNetUDP/unetexchange.cc
extensions/UNetUDP/UNetExchange.cc.c
extensions/UNetUDP/UNetExchange.h
extensions/UNetUDP/UNetReceiver.cc
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