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

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

уведомление об изменнии "заблокированного датчика" (setbug #9302)
parent ff594bc2
......@@ -14,7 +14,7 @@
Name: libuniset2
Version: 2.2
Release: alt30
Release: alt31
Summary: UniSet - library for building distributed industrial control systems
License: LGPL
......@@ -486,6 +486,9 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
# ..
%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
- minor fixes in DealyTimer and MBExchange (not respond logic)
......
......@@ -215,7 +215,7 @@ void SharedMemory::timerInfo( const TimerMessage* tm )
{
bool st = (bool)localGetValue(itPulsar, sidPulsar);
st ^= true;
localSetValue(itPulsar, sidPulsar, (st ? 1 : 0), getId() );
localSetValueIt(itPulsar, sidPulsar, (st ? 1 : 0), getId() );
}
}
}
......@@ -357,9 +357,9 @@ void SharedMemory::checkHeartBeat()
if( 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() )
......
......@@ -30,7 +30,7 @@
<item node="localhost" name="ReservSharedMemory"/>
</ReservList>
</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>
<ObjectsMap idfromfile="1">
<nodes port="2809" unet_broadcast_ip="192.168.1.255" unet_broadcast_ip2="192.168.122.255">
......@@ -50,6 +50,10 @@
<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 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>
<thresholds name="thresholds">
<sensor iotype="AI" name="AI1_AS">
......
......@@ -177,3 +177,68 @@ TEST_CASE("[SM]: heartbeat test N2", "[sm][heartbeat]")
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 @@
<smap>
<item name="sensor_s" vartype="in" iotype="DI" comment="Test input"/>
<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>
<msgmap>
......
......@@ -82,7 +82,10 @@ int main(int argc, const char* argv[] )
while( !pt.checkTime() && !shm->exist() )
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;
return 1;
......
......@@ -9,5 +9,6 @@
./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
#--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
......@@ -236,11 +236,7 @@ using namespace UniSetTypes;
if( !ic )
return setValue(sid, value);
// CHECK_IC_PTR(localSetValue)
IOController_i::SensorInfo si;
si.id = sid;
si.node = ui->getConf()->getLocalNode();
ic->localSetValue(it, si.id, value, sup_id);
ic->localSetValueIt(it, sid, value, sup_id);
}
// --------------------------------------------------------------------------
long SMInterface::localGetValue( IOController::IOStateList::iterator& it, UniSetTypes::ObjectId sid )
......
......@@ -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 );
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 );
long localGetValue( std::shared_ptr<USensorInfo>& it, const UniSetTypes::ObjectId sid );
......
......@@ -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,
CORBA::Long value, UniSetTypes::ObjectId sup_id ) override;
// --------------------------------------------
/*! Информация о заказчике */
......@@ -283,7 +282,8 @@ class IONotifyController:
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 );
......
......@@ -240,7 +240,7 @@ void IOController::fastSetValue( UniSetTypes::ObjectId sid, CORBA::Long value, U
try
{
auto li = ioList.end();
localSetValue( li, sid, value, sup_id );
localSetValueIt( li, sid, value, sup_id );
}
catch(...) {}
}
......@@ -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 )
{
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,
CORBA::Long value, UniSetTypes::ObjectId sup_id )
{
......@@ -289,12 +289,15 @@ void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi,
// поэтому передаём (и затем сохраняем) напрямую(ссылку) value (а не const value)
bool blocked = ( usi->blocked || usi->undefined );
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)
<< " value=" << value << endl;
<< " newvalue=" << value
<< " value=" << usi->value
<< " blocked=" << usi->blocked
<< " real_value=" << usi->real_value
<< endl;
long prev = usi->value;
......@@ -721,7 +724,7 @@ IDSeq* IOController::setOutputSeq(const IOController_i::OutSeq& lst, ObjectId su
if( it != ioList.end() )
{
localSetValue(it, sid, lst[i].value, sup_id);
localSetValueIt(it, sid, lst[i].value, sup_id);
continue;
}
}
......@@ -842,6 +845,15 @@ void IOController::USensorInfo::checkDepend( std::shared_ptr<USensorInfo>& d_it,
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 )
ic->localSetValue( it, si.id, real_value, sup_id );
}
......
......@@ -275,16 +275,16 @@ bool IONotifyController::myIOFilter( std::shared_ptr<USensorInfo>& ai,
return true;
}
// ------------------------------------------------------------------------------------------
void IONotifyController::localSetValue( IOController::IOStateList::iterator& li,
void IONotifyController::localSetValue( std::shared_ptr<IOController::USensorInfo>& usi,
UniSetTypes::ObjectId sid,
CORBA::Long value, UniSetTypes::ObjectId sup_id )
{
// Если датчик не найден сдесь сработает исключение
long prevValue = 0;
try
{
prevValue = IOController::localGetValue( li, sid );
// Если датчик не найден сдесь сработает исключение
prevValue = IOController::localGetValue( usi, sid );
}
catch( IOController_i::Undefined )
{
......@@ -293,46 +293,35 @@ void IONotifyController::localSetValue( IOController::IOStateList::iterator& li,
prevValue = value + 1;
}
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);
IOController::localSetValue(usi, sid, value, sup_id);
// сравниваем именно с li->second->value
// т.к. фактическое сохранённое значение может быть изменено
// фильтрами или блокировками..
SensorMessage sm(sid, li->second->value);
SensorMessage sm(sid, usi->value);
{
// 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;
// Рассылаем уведомления только в слуае изменения значения
sm.id = sid;
sm.node = uniset_conf()->getLocalNode();
sm.value = li->second->value;
sm.undefined = li->second->undefined;
sm.priority = (Message::Priority)li->second->priority;
sm.value = usi->value;
sm.undefined = usi->undefined;
sm.priority = (Message::Priority)usi->priority;
sm.supplier = sup_id; // owner_id
sm.sensor_type = li->second->type;
sm.sm_tv_sec = li->second->tv_sec;
sm.sm_tv_usec = li->second->tv_usec;
sm.ci = li->second->ci;
sm.sensor_type = usi->type;
sm.sm_tv_sec = usi->tv_sec;
sm.sm_tv_usec = usi->tv_usec;
sm.ci = usi->ci;
} // unlock
try
{
if( !li->second->dbignore )
if( !usi->dbignore )
loggingInfo(sm);
}
catch(...) {}
......@@ -348,11 +337,11 @@ void IONotifyController::localSetValue( IOController::IOStateList::iterator& li,
// проверка порогов
try
{
checkThreshold(li, sid, true);
checkThreshold(usi, sid, true);
}
catch(...) {}
}
// ------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------
/*!
\note В случае зависания в функции push, будут остановлены рассылки другим объектам.
Возможно нужно ввести своего агента на удалённой стороне, который будет заниматься
......@@ -682,7 +671,20 @@ bool IONotifyController::removeThreshold( ThresholdExtList& lst, ThresholdInfoEx
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,
bool send_msg )
{
......@@ -700,14 +702,6 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li,
return;
}
if( li == myioEnd() )
li = myiofind(sid);
if( li == myioEnd() )
return; // ???
auto s = li->second;
SensorMessage sm(s->makeSensorMessage());
// текущее время
......@@ -766,7 +760,7 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li,
{
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 )
{
......
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