Commit 3cebcf9c authored by Pavel Vainerman's avatar Pavel Vainerman

(IONotifyController): Испралена ошибка в механизме "depend". Не приходило

уведомление об изменнии "заблокированного датчика" (setbug #9302)
parent ff594bc2
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
Name: libuniset2 Name: libuniset2
Version: 2.2 Version: 2.2
Release: alt30 Release: alt31
Summary: UniSet - library for building distributed industrial control systems Summary: UniSet - library for building distributed industrial control systems
License: LGPL License: LGPL
...@@ -486,6 +486,9 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname ...@@ -486,6 +486,9 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
# .. # ..
%changelog %changelog
* Wed Mar 23 2016 Pavel Vainerman <pv@altlinux.ru> 2.2-alt31
- IONotifyContoller: fixed bug in depend (notify)(setbug #9302)
* Tue Mar 22 2016 Pavel Vainerman <pv@altlinux.ru> 2.2-alt30 * Tue Mar 22 2016 Pavel Vainerman <pv@altlinux.ru> 2.2-alt30
- minor fixes in DealyTimer and MBExchange (not respond logic) - minor fixes in DealyTimer and MBExchange (not respond logic)
......
...@@ -215,7 +215,7 @@ void SharedMemory::timerInfo( const TimerMessage* tm ) ...@@ -215,7 +215,7 @@ void SharedMemory::timerInfo( const TimerMessage* tm )
{ {
bool st = (bool)localGetValue(itPulsar, sidPulsar); bool st = (bool)localGetValue(itPulsar, sidPulsar);
st ^= true; st ^= true;
localSetValue(itPulsar, sidPulsar, (st ? 1 : 0), getId() ); localSetValueIt(itPulsar, sidPulsar, (st ? 1 : 0), getId() );
} }
} }
} }
...@@ -357,9 +357,9 @@ void SharedMemory::checkHeartBeat() ...@@ -357,9 +357,9 @@ void SharedMemory::checkHeartBeat()
if( val < -1 ) if( val < -1 )
val = -1; val = -1;
localSetValue(it.a_it, it.a_sid, val, getId()); localSetValueIt(it.a_it, it.a_sid, val, getId());
localSetValue(it.d_it, it.d_sid, ( val >= 0 ? true : false), getId()); localSetValueIt(it.d_it, it.d_sid, ( val >= 0 ? true : false), getId());
// проверяем нужна ли "перезагрузка" по данному датчику // проверяем нужна ли "перезагрузка" по данному датчику
if( wdt && it.ptReboot.getInterval() ) if( wdt && it.ptReboot.getInterval() )
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
<item node="localhost" name="ReservSharedMemory"/> <item node="localhost" name="ReservSharedMemory"/>
</ReservList> </ReservList>
</SharedMemory> </SharedMemory>
<TestObject name="TestObject" sensor_s="DI2_S" output_c="AO2_C" heartbeat_id="TO_Heartbeat_Counter" heartbeatTime="500" heartbeat_max="5"/> <TestObject name="TestObject" sensor_s="DI2_S" output_c="AO2_C" dependDI_s="DependDI_S" dependAI_s="DependAI_S" heartbeat_id="TO_Heartbeat_Counter" heartbeatTime="500" heartbeat_max="5"/>
</settings> </settings>
<ObjectsMap idfromfile="1"> <ObjectsMap idfromfile="1">
<nodes port="2809" unet_broadcast_ip="192.168.1.255" unet_broadcast_ip2="192.168.122.255"> <nodes port="2809" unet_broadcast_ip="192.168.1.255" unet_broadcast_ip2="192.168.122.255">
...@@ -50,6 +50,10 @@ ...@@ -50,6 +50,10 @@
<item id="509" iotype="DI" name="DI2_S" priority="Medium" textname="TestObject test"/> <item id="509" iotype="DI" name="DI2_S" priority="Medium" textname="TestObject test"/>
<item heartbeat="1" heartbeat_ds_name="TO_Heartbeat_DS" heartbeat_node="localhost" id="510" iotype="AI" name="TO_Heartbeat_Counter" textname="TestObject: heartbeat counter"/> <item heartbeat="1" heartbeat_ds_name="TO_Heartbeat_DS" heartbeat_node="localhost" id="510" iotype="AI" name="TO_Heartbeat_Counter" textname="TestObject: heartbeat counter"/>
<item id="511" iotype="DI" name="TO_Heartbeat_DS" textname="TestObject: heartbeat"/> <item id="511" iotype="DI" name="TO_Heartbeat_DS" textname="TestObject: heartbeat"/>
<item id="512" iotype="AI" name="DependAI_S" depend="Depend_BlockSensor_S" depend_value="1" depend_off_value="1000" priority="Medium" textname="Depend AI sesnor"/>
<item id="513" iotype="DI" name="DependDI_S" depend="Depend_BlockSensor_S" depend_value="0" depend_off_value="0" priority="Medium" textname="Depend DI sesnor"/>
<item id="514" iotype="DI" name="Depend_BlockSensor_S" priority="Medium" textname="Block Sensor for depend"/>
</sensors> </sensors>
<thresholds name="thresholds"> <thresholds name="thresholds">
<sensor iotype="AI" name="AI1_AS"> <sensor iotype="AI" name="AI1_AS">
......
...@@ -177,3 +177,68 @@ TEST_CASE("[SM]: heartbeat test N2", "[sm][heartbeat]") ...@@ -177,3 +177,68 @@ TEST_CASE("[SM]: heartbeat test N2", "[sm][heartbeat]")
CHECK( ui->getValue(511) ); CHECK( ui->getValue(511) );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_CASE("[SM]: depend test", "[sm][depend]")
{
InitTest();
REQUIRE( ui->getValue(514) == 0 );
REQUIRE( ui->getValue(512) == 1000 );
REQUIRE( ui->getValue(513) == 0 );
// проверяем что датчик DI работает
ui->setValue(513,1);
msleep(300);
REQUIRE( obj->in_dependDI_s == 1 );
ui->setValue(513,0);
msleep(300);
REQUIRE( obj->in_dependDI_s == 0 );
// проверяем что датчик AI не работает, т.к. забклоирован
ui->setValue(512,100);
REQUIRE( ui->getValue(512) == 1000 );
msleep(300);
REQUIRE( obj->in_dependAI_s == 1000 );
ui->setValue(512,50);
REQUIRE( ui->getValue(512) == 1000 );
msleep(300);
REQUIRE( obj->in_dependAI_s == 1000 );
// проверяем что после разблолокирования датчик принимает текущее значение
// и процесс приходит sensorInfo
ui->setValue(512,40); // выставляем значение (находясь под блокировкой)
REQUIRE( obj->in_dependAI_s == 1000 ); // у процесса пока блокированное значение
// ----- разблокируем
ui->setValue(514,1);
msleep(300);
REQUIRE( ui->getValue(514) == 1 );
// проверяем dependAI
REQUIRE( ui->getValue(512) == 40 );
msleep(300);
REQUIRE( obj->in_dependAI_s == 40 );
// dependDI наоборот заблокировался
REQUIRE( ui->getValue(513) == 0 );
ui->setValue(513,1);
msleep(300);
REQUIRE( ui->getValue(513) == 0 );
REQUIRE( obj->in_dependDI_s == 0 );
// ----- блокируем
ui->setValue(514,0);
msleep(300);
REQUIRE( ui->getValue(514) == 0 );
// проверяем dependAI
REQUIRE( ui->getValue(512) == 1000 );
msleep(300);
REQUIRE( obj->in_dependAI_s == 1000 );
// dependDI наоборот разблокировался
REQUIRE( ui->getValue(513) == 1 );
msleep(300);
REQUIRE( obj->in_dependDI_s == 1 );
}
// -----------------------------------------------------------------------------
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
<smap> <smap>
<item name="sensor_s" vartype="in" iotype="DI" comment="Test input"/> <item name="sensor_s" vartype="in" iotype="DI" comment="Test input"/>
<item name="output_c" vartype="out" iotype="AO" comment="Test output"/> <item name="output_c" vartype="out" iotype="AO" comment="Test output"/>
<item name="dependDI_s" vartype="in" iotype="DI" comment="Test input"/>
<item name="dependAI_s" vartype="in" iotype="AI" comment="Test input"/>
</smap> </smap>
<msgmap> <msgmap>
......
...@@ -82,7 +82,10 @@ int main(int argc, const char* argv[] ) ...@@ -82,7 +82,10 @@ int main(int argc, const char* argv[] )
while( !pt.checkTime() && !shm->exist() ) while( !pt.checkTime() && !shm->exist() )
msleep(100); msleep(100);
if( !shm->exist() ) while( !pt.checkTime() && !obj->exist() )
msleep(100);
if( !shm->exist() || !obj->exist() )
{ {
cerr << "(tests): SharedMemory not exist! (timeout=" << tout << ")" << endl; cerr << "(tests): SharedMemory not exist! (timeout=" << tout << ")" << endl;
return 1; return 1;
......
...@@ -9,5 +9,6 @@ ...@@ -9,5 +9,6 @@
./uniset2-start.sh -f ./tests $* -- --confile ./sm-configure.xml --pulsar-id Pulsar_S --pulsar-msec 1000 --e-filter evnt_test \ ./uniset2-start.sh -f ./tests $* -- --confile ./sm-configure.xml --pulsar-id Pulsar_S --pulsar-msec 1000 --e-filter evnt_test \
--heartbeat-node localhost --heartbeat-check-time 1000 --TestObject-startup-timeout 0 --heartbeat-node localhost --heartbeat-check-time 1000 --TestObject-startup-timeout 0
#--sm-log-add-levels any --TestObject-log-add-levels any #--sm-log-add-levels any --ulog-add-levels level4,warn,crit \
#--TestObject-log-add-levels any
#--dlog-add-levels any #--dlog-add-levels any
...@@ -236,11 +236,7 @@ using namespace UniSetTypes; ...@@ -236,11 +236,7 @@ using namespace UniSetTypes;
if( !ic ) if( !ic )
return setValue(sid, value); return setValue(sid, value);
// CHECK_IC_PTR(localSetValue) ic->localSetValueIt(it, sid, value, sup_id);
IOController_i::SensorInfo si;
si.id = sid;
si.node = ui->getConf()->getLocalNode();
ic->localSetValue(it, si.id, value, sup_id);
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
long SMInterface::localGetValue( IOController::IOStateList::iterator& it, UniSetTypes::ObjectId sid ) long SMInterface::localGetValue( IOController::IOStateList::iterator& it, UniSetTypes::ObjectId sid )
......
...@@ -140,13 +140,13 @@ class IOController: ...@@ -140,13 +140,13 @@ class IOController:
} }
// доступ к элементам через итератор // доступ к элементам через итератор
virtual void localSetValue( IOStateList::iterator& it, const UniSetTypes::ObjectId sid, virtual void localSetValueIt( IOStateList::iterator& it, const UniSetTypes::ObjectId sid,
CORBA::Long value, UniSetTypes::ObjectId sup_id ); CORBA::Long value, UniSetTypes::ObjectId sup_id );
virtual long localGetValue( IOStateList::iterator& it, const UniSetTypes::ObjectId sid ); virtual long localGetValue( IOStateList::iterator& it, const UniSetTypes::ObjectId sid );
// вариант с указателем // вариант с указателем
void localSetValue( std::shared_ptr<USensorInfo>& usi, UniSetTypes::ObjectId sid, virtual void localSetValue( std::shared_ptr<USensorInfo>& usi, UniSetTypes::ObjectId sid,
CORBA::Long value, UniSetTypes::ObjectId sup_id ); CORBA::Long value, UniSetTypes::ObjectId sup_id );
long localGetValue( std::shared_ptr<USensorInfo>& it, const UniSetTypes::ObjectId sid ); long localGetValue( std::shared_ptr<USensorInfo>& it, const UniSetTypes::ObjectId sid );
......
...@@ -154,11 +154,10 @@ class IONotifyController: ...@@ -154,11 +154,10 @@ class IONotifyController:
// -------------------------------------------- // --------------------------------------------
// функция для работы напрямую черех iterator (оптимизация) // функция для работы напрямую с указателем (оптимизация)
virtual void localSetValue( IOController::IOStateList::iterator& it, virtual void localSetValue( std::shared_ptr<USensorInfo>& usi,
UniSetTypes::ObjectId sid, UniSetTypes::ObjectId sid,
CORBA::Long value, UniSetTypes::ObjectId sup_id ) override; CORBA::Long value, UniSetTypes::ObjectId sup_id ) override;
// -------------------------------------------- // --------------------------------------------
/*! Информация о заказчике */ /*! Информация о заказчике */
...@@ -283,7 +282,8 @@ class IONotifyController: ...@@ -283,7 +282,8 @@ class IONotifyController:
virtual void send( ConsumerListInfo& lst, UniSetTypes::SensorMessage& sm ); virtual void send( ConsumerListInfo& lst, UniSetTypes::SensorMessage& sm );
//! проверка срабатывания пороговых датчиков //! проверка срабатывания пороговых датчиков
virtual void checkThreshold( IOStateList::iterator& li, const UniSetTypes::ObjectId sid, bool send = true ); virtual void checkThreshold( std::shared_ptr<USensorInfo>& usi, const UniSetTypes::ObjectId sid, bool send = true );
virtual void checkThreshold(IOController::IOStateList::iterator& li, const UniSetTypes::ObjectId sid, bool send_msg=true );
//! поиск информации о пороговом датчике //! поиск информации о пороговом датчике
ThresholdExtList::iterator findThreshold( const UniSetTypes::ObjectId sid, const UniSetTypes::ThresholdId tid ); ThresholdExtList::iterator findThreshold( const UniSetTypes::ObjectId sid, const UniSetTypes::ThresholdId tid );
......
...@@ -240,7 +240,7 @@ void IOController::fastSetValue( UniSetTypes::ObjectId sid, CORBA::Long value, U ...@@ -240,7 +240,7 @@ void IOController::fastSetValue( UniSetTypes::ObjectId sid, CORBA::Long value, U
try try
{ {
auto li = ioList.end(); auto li = ioList.end();
localSetValue( li, sid, value, sup_id ); localSetValueIt( li, sid, value, sup_id );
} }
catch(...) {} catch(...) {}
} }
...@@ -248,10 +248,10 @@ void IOController::fastSetValue( UniSetTypes::ObjectId sid, CORBA::Long value, U ...@@ -248,10 +248,10 @@ void IOController::fastSetValue( UniSetTypes::ObjectId sid, CORBA::Long value, U
void IOController::setValue( UniSetTypes::ObjectId sid, CORBA::Long value, UniSetTypes::ObjectId sup_id ) void IOController::setValue( UniSetTypes::ObjectId sid, CORBA::Long value, UniSetTypes::ObjectId sup_id )
{ {
auto li = ioList.end(); auto li = ioList.end();
localSetValue( li, sid, value, sup_id ); localSetValueIt( li, sid, value, sup_id );
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void IOController::localSetValue( IOController::IOStateList::iterator& li, void IOController::localSetValueIt( IOController::IOStateList::iterator& li,
UniSetTypes::ObjectId sid, UniSetTypes::ObjectId sid,
CORBA::Long value, UniSetTypes::ObjectId sup_id ) CORBA::Long value, UniSetTypes::ObjectId sup_id )
{ {
...@@ -289,12 +289,15 @@ void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi, ...@@ -289,12 +289,15 @@ void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi,
// поэтому передаём (и затем сохраняем) напрямую(ссылку) value (а не const value) // поэтому передаём (и затем сохраняем) напрямую(ссылку) value (а не const value)
bool blocked = ( usi->blocked || usi->undefined ); bool blocked = ( usi->blocked || usi->undefined );
if( checkIOFilters(usi, value, sup_id) || blocked ) if( checkIOFilters(usi, value, sup_id) || blocked )
{ {
uinfo << myname << ": save sensor value (" << sid << ")" ulog4 << myname << ": save sensor value (" << sid << ")"
<< " name: " << uniset_conf()->oind->getNameById(sid) << " name: " << uniset_conf()->oind->getNameById(sid)
<< " value=" << value << endl; << " newvalue=" << value
<< " value=" << usi->value
<< " blocked=" << usi->blocked
<< " real_value=" << usi->real_value
<< endl;
long prev = usi->value; long prev = usi->value;
...@@ -721,7 +724,7 @@ IDSeq* IOController::setOutputSeq(const IOController_i::OutSeq& lst, ObjectId su ...@@ -721,7 +724,7 @@ IDSeq* IOController::setOutputSeq(const IOController_i::OutSeq& lst, ObjectId su
if( it != ioList.end() ) if( it != ioList.end() )
{ {
localSetValue(it, sid, lst[i].value, sup_id); localSetValueIt(it, sid, lst[i].value, sup_id);
continue; continue;
} }
} }
...@@ -842,6 +845,15 @@ void IOController::USensorInfo::checkDepend( std::shared_ptr<USensorInfo>& d_it, ...@@ -842,6 +845,15 @@ void IOController::USensorInfo::checkDepend( std::shared_ptr<USensorInfo>& d_it,
sup_id = d_it->supplier; sup_id = d_it->supplier;
} }
ulog4 << ic->getName() << "(checkDepend): check si.id=" << si.id
<< " d_it->value=" << d_it->value
<< " d_value=" << d_value
<< " d_off_value=" << d_off_value
<< " blocked=" << blocked
<< " changed=" << changed
<< " real_value=" << real_value
<< endl;
if( changed ) if( changed )
ic->localSetValue( it, si.id, real_value, sup_id ); ic->localSetValue( it, si.id, real_value, sup_id );
} }
......
...@@ -275,16 +275,16 @@ bool IONotifyController::myIOFilter( std::shared_ptr<USensorInfo>& ai, ...@@ -275,16 +275,16 @@ bool IONotifyController::myIOFilter( std::shared_ptr<USensorInfo>& ai,
return true; return true;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void IONotifyController::localSetValue( IOController::IOStateList::iterator& li, void IONotifyController::localSetValue( std::shared_ptr<IOController::USensorInfo>& usi,
UniSetTypes::ObjectId sid, UniSetTypes::ObjectId sid,
CORBA::Long value, UniSetTypes::ObjectId sup_id ) CORBA::Long value, UniSetTypes::ObjectId sup_id )
{ {
// Если датчик не найден сдесь сработает исключение
long prevValue = 0; long prevValue = 0;
try try
{ {
prevValue = IOController::localGetValue( li, sid ); // Если датчик не найден сдесь сработает исключение
prevValue = IOController::localGetValue( usi, sid );
} }
catch( IOController_i::Undefined ) catch( IOController_i::Undefined )
{ {
...@@ -293,46 +293,35 @@ void IONotifyController::localSetValue( IOController::IOStateList::iterator& li, ...@@ -293,46 +293,35 @@ void IONotifyController::localSetValue( IOController::IOStateList::iterator& li,
prevValue = value + 1; prevValue = value + 1;
} }
IOController::localSetValue(usi, sid, value, sup_id);
if( li == myioEnd() ) // ???
{
ostringstream err;
err << myname << "(localSetValue): вход(выход) с именем "
<< uniset_conf()->oind->getNameById(sid) << " не найден";
uinfo << err.str() << endl;
throw IOController_i::NameNotFound(err.str().c_str());
}
IOController::localSetValue(li, sid, value, sup_id);
// сравниваем именно с li->second->value // сравниваем именно с li->second->value
// т.к. фактическое сохранённое значение может быть изменено // т.к. фактическое сохранённое значение может быть изменено
// фильтрами или блокировками.. // фильтрами или блокировками..
SensorMessage sm(sid, li->second->value); SensorMessage sm(sid, usi->value);
{ {
// lock // lock
uniset_rwmutex_rlock lock(li->second->val_lock); uniset_rwmutex_rlock lock(usi->val_lock);
if( prevValue == li->second->value ) if( prevValue == usi->value )
return; return;
// Рассылаем уведомления только в слуае изменения значения // Рассылаем уведомления только в слуае изменения значения
sm.id = sid; sm.id = sid;
sm.node = uniset_conf()->getLocalNode(); sm.node = uniset_conf()->getLocalNode();
sm.value = li->second->value; sm.value = usi->value;
sm.undefined = li->second->undefined; sm.undefined = usi->undefined;
sm.priority = (Message::Priority)li->second->priority; sm.priority = (Message::Priority)usi->priority;
sm.supplier = sup_id; // owner_id sm.supplier = sup_id; // owner_id
sm.sensor_type = li->second->type; sm.sensor_type = usi->type;
sm.sm_tv_sec = li->second->tv_sec; sm.sm_tv_sec = usi->tv_sec;
sm.sm_tv_usec = li->second->tv_usec; sm.sm_tv_usec = usi->tv_usec;
sm.ci = li->second->ci; sm.ci = usi->ci;
} // unlock } // unlock
try try
{ {
if( !li->second->dbignore ) if( !usi->dbignore )
loggingInfo(sm); loggingInfo(sm);
} }
catch(...) {} catch(...) {}
...@@ -348,11 +337,11 @@ void IONotifyController::localSetValue( IOController::IOStateList::iterator& li, ...@@ -348,11 +337,11 @@ void IONotifyController::localSetValue( IOController::IOStateList::iterator& li,
// проверка порогов // проверка порогов
try try
{ {
checkThreshold(li, sid, true); checkThreshold(usi, sid, true);
} }
catch(...) {} catch(...) {}
} }
// ------------------------------------------------------------------------------------------ // -----------------------------------------------------------------------------------------
/*! /*!
\note В случае зависания в функции push, будут остановлены рассылки другим объектам. \note В случае зависания в функции push, будут остановлены рассылки другим объектам.
Возможно нужно ввести своего агента на удалённой стороне, который будет заниматься Возможно нужно ввести своего агента на удалённой стороне, который будет заниматься
...@@ -682,7 +671,20 @@ bool IONotifyController::removeThreshold( ThresholdExtList& lst, ThresholdInfoEx ...@@ -682,7 +671,20 @@ bool IONotifyController::removeThreshold( ThresholdExtList& lst, ThresholdInfoEx
return false; return false;
} }
// -------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------
void IONotifyController::checkThreshold( IOStateList::iterator& li, void IONotifyController::checkThreshold( IOController::IOStateList::iterator& li,
const UniSetTypes::ObjectId sid,
bool send_msg )
{
if( li == myioEnd() )
li = myiofind(sid);
if( li == myioEnd() )
return; // ???
checkThreshold(li->second,sid,send_msg);
}
// --------------------------------------------------------------------------------------------------------------
void IONotifyController::checkThreshold( std::shared_ptr<IOController::USensorInfo>& s,
const UniSetTypes::ObjectId sid, const UniSetTypes::ObjectId sid,
bool send_msg ) bool send_msg )
{ {
...@@ -700,14 +702,6 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li, ...@@ -700,14 +702,6 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li,
return; return;
} }
if( li == myioEnd() )
li = myiofind(sid);
if( li == myioEnd() )
return; // ???
auto s = li->second;
SensorMessage sm(s->makeSensorMessage()); SensorMessage sm(s->makeSensorMessage());
// текущее время // текущее время
...@@ -766,7 +760,7 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li, ...@@ -766,7 +760,7 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li,
{ {
try try
{ {
localSetValue(it->sit, it->sid, (sm.threshold ? 1 : 0), s->supplier); localSetValueIt(it->sit, it->sid, (sm.threshold ? 1 : 0), s->supplier);
} }
catch( UniSetTypes::Exception& ex ) catch( UniSetTypes::Exception& ex )
{ {
......
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