Commit de46f724 authored by Pavel Vainerman's avatar Pavel Vainerman

Рефактринг системы конфигурирования IOController-ов. Новый интерфейс IOConfig

и реализация IOConfig_XML. Попутно удалил устаревший и неиспользуемый RunLock.
parent ca499bb7
...@@ -89,6 +89,9 @@ DB: Сделать регулируемый буфер на INSERT-ы БД, чт ...@@ -89,6 +89,9 @@ DB: Сделать регулируемый буфер на INSERT-ы БД, чт
Разобраться с BigEndian и LittleEndian! Использовать htons,htol и т.п. (и реализации для 64bit) Разобраться с BigEndian и LittleEndian! Использовать htons,htol и т.п. (и реализации для 64bit)
timeout_t перевести всё на chrono.. чтобы использовать setTimeout( 2msec );
ВОЗМОЖНО СТОИТ: ВОЗМОЖНО СТОИТ:
Уйти от использования libxml2,DebugLog ==> и применять одну библиотеку libpoco (http://pocoproject.org/documentation/index.html) Уйти от использования libxml2,DebugLog ==> и применять одну библиотеку libpoco (http://pocoproject.org/documentation/index.html)
или всё-таки на boost? или всё-таки на boost?
......
#include "Configuration.h" #include "Configuration.h"
#include "NCRestorer.h" #include "IOConfig_XML.h"
#include "NullController.h" #include "NullController.h"
#include "PassiveTimer.h" #include "PassiveTimer.h"
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
...@@ -7,7 +7,7 @@ using namespace uniset; ...@@ -7,7 +7,7 @@ using namespace uniset;
using namespace std; using namespace std;
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
NullController::NullController( ObjectId id, const string& askdump, NullController::NullController( ObjectId id, const string& ioconfile,
const std::string& s_filterField, const std::string& s_filterField,
const std::string& s_filterValue, const std::string& s_filterValue,
const std::string& c_filterField, const std::string& c_filterField,
...@@ -18,11 +18,11 @@ NullController::NullController( ObjectId id, const string& askdump, ...@@ -18,11 +18,11 @@ NullController::NullController( ObjectId id, const string& askdump,
{ {
restorer = NULL; restorer = NULL;
shared_ptr<NCRestorer_XML> askd = make_shared<NCRestorer_XML>(askdump); auto ioconf = make_shared<IOConfig_XML>(ioconfile, uniset_conf());
askd->setItemFilter(s_filterField, s_filterValue); ioconf->setItemFilter(s_filterField, s_filterValue);
askd->setConsumerFilter(c_filterField, c_filterValue); ioconf->setConsumerFilter(c_filterField, c_filterValue);
restorer = std::static_pointer_cast<NCRestorer>(askd); restorer = std::static_pointer_cast<IOConfig>(ioconf);
/* /*
// askd->setReadItem( sigc::mem_fun(this,&NullController::readSItem) ); // askd->setReadItem( sigc::mem_fun(this,&NullController::readSItem) );
......
...@@ -4,18 +4,17 @@ ...@@ -4,18 +4,17 @@
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
#include <string> #include <string>
#include "IONotifyController.h" #include "IONotifyController.h"
#include "NCRestorer.h"
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
class NullController: class NullController:
public uniset::IONotifyController public uniset::IONotifyController
{ {
public: public:
NullController( uniset::ObjectId id, const std::string& restorfile, NullController(uniset::ObjectId id, const std::string& ioconfile,
const std::string& s_filterField = "", const std::string& s_filterField = "",
const std::string& s_filterValue = "", const std::string& s_filterValue = "",
const std::string& c_filterField = "", const std::string& c_filterField = "",
const std::string& c_filterValue = "", const std::string& c_filterValue = "",
bool _dumpingToDB = false ); bool _dumpingToDB = false );
virtual ~NullController(); virtual ~NullController();
......
#include <memory> #include <memory>
#include "Configuration.h" #include "Configuration.h"
#include "NCRestorer.h" #include "IOConfig_XML.h"
#include "NullSM.h" #include "NullSM.h"
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
using namespace uniset; using namespace uniset;
...@@ -8,10 +8,8 @@ using namespace std; ...@@ -8,10 +8,8 @@ using namespace std;
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
NullSM::NullSM( ObjectId id, const std::string& datfile ): NullSM::NullSM( ObjectId id, const std::string& datfile ):
IONotifyController(id) IONotifyController(id, static_pointer_cast<IOConfig>(make_shared<IOConfig_XML>(datfile, uniset_conf())) )
{ {
shared_ptr<NCRestorer_XML> r = make_shared<NCRestorer_XML>(datfile);
restorer = std::static_pointer_cast<NCRestorer>(r);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
NullSM::~NullSM() NullSM::~NullSM()
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
#include <string> #include <string>
#include "IONotifyController.h" #include "IONotifyController.h"
#include "NCRestorer.h"
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
class NullSM: class NullSM:
public uniset::IONotifyController public uniset::IONotifyController
...@@ -18,9 +17,6 @@ class NullSM: ...@@ -18,9 +17,6 @@ class NullSM:
virtual void logging( uniset::SensorMessage& sm ) override {}; virtual void logging( uniset::SensorMessage& sm ) override {};
virtual void dumpOrdersList( const uniset::ObjectId sid, const IONotifyController::ConsumerListInfo& lst ) override {};
virtual void dumpThresholdList( const uniset::ObjectId sid, const IONotifyController::ThresholdExtList& lst ) override {};
private: private:
}; };
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include "UniXML.h" #include "UniXML.h"
#include "NCRestorer.h" #include "IOConfig_XML.h"
#include "SharedMemory.h" #include "SharedMemory.h"
#include "Extensions.h" #include "Extensions.h"
#include "ORepHelpers.h" #include "ORepHelpers.h"
...@@ -64,8 +64,10 @@ namespace uniset ...@@ -64,8 +64,10 @@ namespace uniset
cout << LogServer::help_print("sm-logserver") << endl; cout << LogServer::help_print("sm-logserver") << endl;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
SharedMemory::SharedMemory( ObjectId id, const std::string& datafile, const std::string& confname ): SharedMemory::SharedMemory( ObjectId id,
IONotifyController(id), const std::shared_ptr<IOConfig_XML>& ioconf,
const std::string& confname ):
IONotifyController(id, static_pointer_cast<IOConfig>(ioconf)),
heartbeatCheckTime(5000), heartbeatCheckTime(5000),
histSaveTime(0), histSaveTime(0),
activated(false), activated(false),
...@@ -117,8 +119,6 @@ namespace uniset ...@@ -117,8 +119,6 @@ namespace uniset
histmap[i->fuse_id].push_back(i); histmap[i->fuse_id].push_back(i);
// ---------------------- // ----------------------
auto rxml = make_shared<NCRestorer_XML>(datafile);
string s_field(conf->getArgParam("--s-filter-field")); string s_field(conf->getArgParam("--s-filter-field"));
string s_fvalue(conf->getArgParam("--s-filter-value")); string s_fvalue(conf->getArgParam("--s-filter-value"));
string c_field(conf->getArgParam("--c-filter-field")); string c_field(conf->getArgParam("--c-filter-field"));
...@@ -137,12 +137,10 @@ namespace uniset ...@@ -137,12 +137,10 @@ namespace uniset
heartbeatCheckTime = conf->getArgInt("--heartbeat-check-time", "1000"); heartbeatCheckTime = conf->getArgInt("--heartbeat-check-time", "1000");
rxml->setItemFilter(s_field, s_fvalue); ioconf->setItemFilter(s_field, s_fvalue);
rxml->setConsumerFilter(c_field, c_fvalue); ioconf->setConsumerFilter(c_field, c_fvalue);
rxml->setThresholdsFilter(t_field, t_fvalue); ioconf->setThresholdsFilter(t_field, t_fvalue);
ioconf->setReadItem( sigc::mem_fun(this, &SharedMemory::readItem) );
restorer = std::static_pointer_cast<NCRestorer>(rxml);
rxml->setReadItem( sigc::mem_fun(this, &SharedMemory::readItem) );
string wdt_dev = conf->getArgParam("--wdt-device"); string wdt_dev = conf->getArgParam("--wdt-device");
...@@ -524,31 +522,38 @@ namespace uniset ...@@ -524,31 +522,38 @@ namespace uniset
shared_ptr<SharedMemory> SharedMemory::init_smemory( int argc, const char* const* argv ) shared_ptr<SharedMemory> SharedMemory::init_smemory( int argc, const char* const* argv )
{ {
auto conf = uniset_conf(); auto conf = uniset_conf();
string dfile = conf->getArgParam("--datfile", conf->getConfFileName()); string dfile = conf->getArgParam("--datfile", "");
// если dfile == confile, то преобразовывать имя не надо, чтобы сработала std::shared_ptr<uniset::IOConfig_XML> ioconf;
// оптимизация и когда NCRestorer_XML будет загружать файл, он использует conf->getUniXML()
// т.е. не будет загружать повторно.. (см. конструктор SharedMemory и NCRestorer_XML). if( !dfile.empty() )
if( dfile != conf->getConfFileName() )
{ {
if( dfile[0] != '.' && dfile[0] != '/' ) if( dfile[0] != '.' && dfile[0] != '/' )
dfile = conf->getConfDir() + dfile; dfile = conf->getConfDir() + dfile;
}
dinfo << "(smemory): init from datfile " << dfile << endl;
ioconf = make_shared<IOConfig_XML>(dfile, conf);
}
else
{
dinfo << "(smemory): init from configure: " << conf->getConfFileName() << endl;
UniXML::iterator it(conf->getXMLSensorsSection());
it.goChildren();
ioconf = make_shared<IOConfig_XML>(conf->getConfXML(), conf, it);
}
dinfo << "(smemory): datfile = " << dfile << endl;
uniset::ObjectId ID = conf->getControllerID(conf->getArgParam("--smemory-id", "SharedMemory")); uniset::ObjectId ID = conf->getControllerID(conf->getArgParam("--smemory-id", "SharedMemory"));
if( ID == uniset::DefaultObjectId ) if( ID == uniset::DefaultObjectId )
{ {
cerr << "(smemory): НЕ ЗАДАН идентификатор '" cerr << "(smemory): Not found ID for SharedMemory in section "
<< " или не найден в " << conf->getControllersSection() << conf->getControllersSection()
<< endl; << endl;
return 0; return nullptr;
} }
string cname = conf->getArgParam("--smemory--confnode", ORepHelpers::getShortName(conf->oind->getMapName(ID)) ); string cname = conf->getArgParam("--smemory--confnode", ORepHelpers::getShortName(conf->oind->getMapName(ID)) );
return make_shared<SharedMemory>(ID, dfile, cname); return make_shared<SharedMemory>(ID, ioconf, cname);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void SharedMemory::buildEventList( xmlNode* cnode ) void SharedMemory::buildEventList( xmlNode* cnode )
...@@ -619,7 +624,7 @@ namespace uniset ...@@ -619,7 +624,7 @@ namespace uniset
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void SharedMemory::addReadItem( Restorer_XML::ReaderSlot sl ) void SharedMemory::addReadItem( IOConfig_XML::ReaderSlot sl )
{ {
lstRSlot.push_back(sl); lstRSlot.push_back(sl);
} }
......
...@@ -25,12 +25,12 @@ ...@@ -25,12 +25,12 @@
#include "IONotifyController.h" #include "IONotifyController.h"
#include "Mutex.h" #include "Mutex.h"
#include "PassiveTimer.h" #include "PassiveTimer.h"
#include "NCRestorer.h"
#include "WDTInterface.h" #include "WDTInterface.h"
#include "LogServer.h" #include "LogServer.h"
#include "DebugStream.h" #include "DebugStream.h"
#include "LogAgregator.h" #include "LogAgregator.h"
#include "VMonitor.h" #include "VMonitor.h"
#include "IOConfig_XML.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#ifndef vmonit #ifndef vmonit
#define vmonit( var ) vmon.add( #var, var ) #define vmonit( var ) vmon.add( #var, var )
...@@ -326,7 +326,12 @@ namespace uniset ...@@ -326,7 +326,12 @@ namespace uniset
public IONotifyController public IONotifyController
{ {
public: public:
SharedMemory( uniset::ObjectId id, const std::string& datafile, const std::string& confname = "" );
// конструктор с конфигурированием через xml
SharedMemory( ObjectId id,
const std::shared_ptr<IOConfig_XML>& ioconf,
const std::string& confname = "" );
virtual ~SharedMemory(); virtual ~SharedMemory();
/*! глобальная функция для инициализации объекта */ /*! глобальная функция для инициализации объекта */
...@@ -342,7 +347,7 @@ namespace uniset ...@@ -342,7 +347,7 @@ namespace uniset
virtual uniset::SimpleInfo* getInfo( const char* userparam = 0 ) override; virtual uniset::SimpleInfo* getInfo( const char* userparam = 0 ) override;
void addReadItem( Restorer_XML::ReaderSlot sl ); void addReadItem( IOConfig_XML::ReaderSlot sl );
// ------------ HISTORY -------------------- // ------------ HISTORY --------------------
typedef std::deque<long> HBuffer; typedef std::deque<long> HBuffer;
...@@ -423,12 +428,11 @@ namespace uniset ...@@ -423,12 +428,11 @@ namespace uniset
} }
protected: protected:
typedef std::list<Restorer_XML::ReaderSlot> ReadSlotList; typedef std::list<IOConfig_XML::ReaderSlot> ReadSlotList;
ReadSlotList lstRSlot; ReadSlotList lstRSlot;
virtual void sysCommand( const uniset::SystemMessage* sm ) override; virtual void sysCommand( const uniset::SystemMessage* sm ) override;
virtual void timerInfo( const uniset::TimerMessage* tm ) override; virtual void timerInfo( const uniset::TimerMessage* tm ) override;
virtual void askSensors( UniversalIO::UIOCommand cmd ) {};
virtual std::string getTimerName(int id) const override; virtual std::string getTimerName(int id) const override;
void sendEvent( uniset::SystemMessage& sm ); void sendEvent( uniset::SystemMessage& sm );
...@@ -498,8 +502,6 @@ namespace uniset ...@@ -498,8 +502,6 @@ namespace uniset
int activateTimeout; int activateTimeout;
virtual void logging( uniset::SensorMessage& sm ) override; virtual void logging( uniset::SensorMessage& sm ) override;
virtual void dumpOrdersList( const uniset::ObjectId sid, const IONotifyController::ConsumerListInfo& lst ) override {}
virtual void dumpThresholdList( const uniset::ObjectId sid, const IONotifyController::ThresholdExtList& lst ) override {}
bool dblogging = { false }; bool dblogging = { false };
......
#include <memory> #include <memory>
#include "Configuration.h" #include "Configuration.h"
#include "NCRestorer.h" #include "IOConfig_XML.h"
#include "NullSM.h" #include "NullSM.h"
#include "PassiveTimer.h" #include "PassiveTimer.h"
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
...@@ -11,8 +11,8 @@ using namespace std; ...@@ -11,8 +11,8 @@ using namespace std;
NullSM::NullSM( ObjectId id, const std::string& datfile ): NullSM::NullSM( ObjectId id, const std::string& datfile ):
IONotifyController(id) IONotifyController(id)
{ {
shared_ptr<NCRestorer_XML> r = make_shared<NCRestorer_XML>(datfile); auto r = make_shared<IOConfig_XML>(datfile, uniset_conf());
restorer = std::static_pointer_cast<NCRestorer>(r); restorer = std::static_pointer_cast<IOConfig>(r);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
NullSM::~NullSM() NullSM::~NullSM()
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
#include <string> #include <string>
#include "IONotifyController.h" #include "IONotifyController.h"
#include "NCRestorer.h"
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
class NullSM: class NullSM:
public uniset::IONotifyController public uniset::IONotifyController
...@@ -18,9 +17,6 @@ class NullSM: ...@@ -18,9 +17,6 @@ class NullSM:
virtual void logging( uniset::SensorMessage& sm ) override {}; virtual void logging( uniset::SensorMessage& sm ) override {};
virtual void dumpOrdersList( const uniset::ObjectId sid, const IONotifyController::ConsumerListInfo& lst ) override {};
virtual void dumpThresholdList( const uniset::ObjectId sid, const IONotifyController::ThresholdExtList& lst ) override {};
private: private:
}; };
......
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
./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 --uniset-object-size-message-queue 2000000 --heartbeat-node localhost --heartbeat-check-time 1000 --TestObject-startup-timeout 0 --uniset-object-size-message-queue 2000000
#--ulog-add-levels crit,warn --dlog-add-levels any
#--sm-log-add-levels any --ulog-add-levels level4,warn,crit \ #--sm-log-add-levels any --ulog-add-levels level4,warn,crit \
#--TestObject-log-add-levels any #--TestObject-log-add-levels any
#--dlog-add-levels any #--dlog-add-levels any
...@@ -248,13 +248,13 @@ TEST_CASE("[REST API: /consumers]", "[restapi][consumers]") ...@@ -248,13 +248,13 @@ TEST_CASE("[REST API: /consumers]", "[restapi][consumers]")
// {"object":{"id":5003,"isActive":true,"lostMessages":0,"maxSizeOfMessageQueue":1000,"msgCount":0,"name":"SharedMemory","objectType":"IONotifyController"}, // {"object":{"id":5003,"isActive":true,"lostMessages":0,"maxSizeOfMessageQueue":1000,"msgCount":0,"name":"SharedMemory","objectType":"IONotifyController"},
// "sensors":[ // "sensors":[
// {"consumers":[ // {"consumers":[
// {"attempt":10,"id":6000,"lostEvents":0,"name":"TestProc","node":3000,"node_name":"localhost","smCount":0}
// ],
// "sensor":{"id":1,"name":"Input1_S"}},
// {"consumers":[
// {"attempt":4,"id":6000,"lostEvents":4,"name":"TestProc","node":3000,"node_name":"localhost","smCount":0} // {"attempt":4,"id":6000,"lostEvents":4,"name":"TestProc","node":3000,"node_name":"localhost","smCount":0}
// ], // ],
// "sensor":{"id":10,"name":"AI_AS"}} // "sensor":{"id":10,"name":"AI_AS"}}
// {"consumers":[
// {"attempt":10,"id":6000,"lostEvents":0,"name":"TestProc","node":3000,"node_name":"localhost","smCount":0}
// ],
// "sensor":{"id":1,"name":"Input1_S"}},
// ]} // ]}
...@@ -273,8 +273,8 @@ TEST_CASE("[REST API: /consumers]", "[restapi][consumers]") ...@@ -273,8 +273,8 @@ TEST_CASE("[REST API: /consumers]", "[restapi][consumers]")
auto sens = jret->get("sensor").extract<Poco::JSON::Object::Ptr>(); auto sens = jret->get("sensor").extract<Poco::JSON::Object::Ptr>();
REQUIRE(sens); REQUIRE(sens);
REQUIRE( sens->get("id").convert<ObjectId>() == 1 ); REQUIRE( sens->get("id").convert<ObjectId>() == 10 );
REQUIRE( sens->get("name").convert<std::string>() == "Input1_S" ); REQUIRE( sens->get("name").convert<std::string>() == "AI_AS" );
auto cons = jret->get("consumers").extract<Poco::JSON::Array::Ptr>(); auto cons = jret->get("consumers").extract<Poco::JSON::Array::Ptr>();
REQUIRE(cons); REQUIRE(cons);
......
#include <catch.hpp> #include <catch.hpp>
#include <time.h> #include <time.h>
#include "IOController_i.hh"
#include "UInterface.h" #include "UInterface.h"
#include "UniSetTypes.h" #include "UniSetTypes.h"
...@@ -174,6 +175,12 @@ TEST_CASE("UInterface", "[UInterface]") ...@@ -174,6 +175,12 @@ TEST_CASE("UInterface", "[UInterface]")
REQUIRE_NOTHROW( ui.askThreshold(aid, 12, UniversalIO::UIONotify, 20, 40, false, testOID) ); REQUIRE_NOTHROW( ui.askThreshold(aid, 12, UniversalIO::UIONotify, 20, 40, false, testOID) );
REQUIRE_THROWS_AS( ui.askThreshold(aid, 3, UniversalIO::UIONotify, 50, 20, false, testOID), IONotifyController_i::BadRange ); REQUIRE_THROWS_AS( ui.askThreshold(aid, 3, UniversalIO::UIONotify, 50, 20, false, testOID), IONotifyController_i::BadRange );
IONotifyController_i::ThresholdsListSeq_var slist = ui.getThresholdsList(aid);
REQUIRE( slist->length() == 1 ); // количество датчиков с порогоами = 1 (это aid)
// 3 порога мы создали выше(askThreshold) + 1 который в настроечном файле в секции <thresholds>
REQUIRE( slist[0].tlist.length() == 4 );
IONotifyController_i::ThresholdInfo ti1 = ui.getThresholdInfo(aid, 10); IONotifyController_i::ThresholdInfo ti1 = ui.getThresholdInfo(aid, 10);
REQUIRE( ti1.id == 10 ); REQUIRE( ti1.id == 10 );
REQUIRE( ti1.lowlimit == 90 ); REQUIRE( ti1.lowlimit == 90 );
......
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// --------------------------------------------------------------------------
#ifndef IOConfig_H_
#define IOConfig_H_
// ------------------------------------------------------------------------------------------
#include "IOController.h"
#include "IONotifyController.h"
// ------------------------------------------------------------------------------------------
namespace uniset
{
/*! Интерфейс конфигурирования IOController-ов */
class IOConfig
{
public:
IOConfig() {}
virtual ~IOConfig() {}
/*! считать список io */
virtual IOController::IOStateList read() = 0;
// /*! записать текущий список io */
// virtual bool write( const IOController::IOStateList& iolist ) = 0;
};
// --------------------------------------------------------------------------------------
} // end of uniset namespace
// --------------------------------------------------------------------------------------
#endif
...@@ -15,105 +15,162 @@ ...@@ -15,105 +15,162 @@
*/ */
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
/*! \file /*! \file
* \brief Интерфейс к объекту сохраняющему список заказчиков в файл и умеющему его потом прочитать * \brief Интерфейс к объекту сохраняющему список заказчиков для NotifyController-ов
* \author Pavel Vainerman * \author Pavel Vainerman
*/ */
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
#ifndef Restorer_H_ #ifndef IOConfig_XML_H_
#define Restorer_H_ #define IOConfig_XML_H_
// -------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------
#include <memory> #include <memory>
#include <sigc++/sigc++.h> #include <sigc++/sigc++.h>
#include <string> #include <string>
#include "UniXML.h" #include "UniXML.h"
#include "UniSetTypes.h" #include "UniSetTypes.h"
// -------------------------------------------------------------------------- #include "IOConfig.h"
// ------------------------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
/*! // ------------------------------------------------------------------------------------------
Это абстрактный интерфейс. /*! Реализация интерфейса конфигурирования на основе XML */
Содержит общие для всех xxx_XML интерфейсов функции. class IOConfig_XML:
Расчитан на работу с файлом формата файла проекта. public IOConfig
*/
class Restorer_XML
{ {
public: public:
virtual ~IOConfig_XML();
// реализация интерфейса IOConfig
virtual IOController::IOStateList read() override;
/*!
* \param fname - файл формата uniset-project
* \param conf - конфигурация
*/
IOConfig_XML( const std::string& fname, const std::shared_ptr<Configuration>& conf );
/*!
* \param xml - xml формата uniset-project
* \param conf - конфигурация
* \param root - узел с датчиками (если не задан, ищется "sensors")
*/
IOConfig_XML( const std::shared_ptr<UniXML>& _xml, const std::shared_ptr<Configuration>& conf, xmlNode* root = nullptr );
Restorer_XML();
virtual ~Restorer_XML();
/*! слот для подключения функции чтения датчика из xml-файла. /*! слот для подключения функции чтения датчика из xml-файла.
\param uxml - интерфейс для работы с xml-файлом \param uxml - интерфейс для работы с xml-файлом
\param it - итератор (указатель) на текущий считываемый xml-узел (item) \param it - итератор (указатель) на текущий считываемый xml-узел (item)
\param sec - итератор (указатель) на корневой узел секции (SubscriberList) \param sec - итератор (указатель) на корневой узел секции (SubscriberList)
\return TRUE - если чтение параметров прошло успешно, FALSE - если нет \return TRUE - если чтение параметров прошло успешно, FALSE - если нет
*/ */
typedef sigc::slot<bool, const std::shared_ptr<UniXML>&, UniXML::iterator&, xmlNode*> ReaderSlot; typedef sigc::slot<bool, const std::shared_ptr<UniXML>&, UniXML::iterator&, xmlNode*> ReaderSlot;
/*! установить функцию для callback-вызова при чтении списка сообщений /*! установить функцию для callback-вызова при чтении списка сообщений
For example: For example:
setReadItem( sigc::mem_fun(this,&MyClass::myReadItem) ); setReadItem( sigc::mem_fun(this,&MyClass::myReadItem) );
bool myReadItem::myfunc(UniXML& xml, bool myReadItem::myfunc(UniXML& xml,
UniXML::iterator& it, xmlNode* sec) UniXML::iterator& it, xmlNode* sec)
uxml - интерфейс для работы с xml-файлом uxml - интерфейс для работы с xml-файлом
it - интератор(указатель) на текущий считываемый xml-узел (item) it - интератор(указатель) на текущий считываемый xml-узел (item)
sec - указатель на корневой узел секции (SubscriberList) sec - указатель на корневой узел секции (SubscriberList)
*/ */
void setReadItem( ReaderSlot sl ); void setReadItem( ReaderSlot sl );
/*! установить функцию для callback-вызова при чтении списка заказчиков /*! установить функцию для callback-вызова при чтении списка заказчиков
For example: For example:
setReadItem( sigc::mem_fun(this,&MyClass::myReadItem) ); setReadItem( sigc::mem_fun(this,&MyClass::myReadItem) );
bool myReadItem::myfunc(UniXML& xml, bool myReadItem::myfunc(UniXML& xml,
UniXML::iterator& it, xmlNode* sec) UniXML::iterator& it, xmlNode* sec)
uxml - интерфейс для работы с xml-файлом uxml - интерфейс для работы с xml-файлом
it - интератор(указатель) на текущий считываемый xml-узел (<consumer>) it - интератор(указатель) на текущий считываемый xml-узел (<consumer>)
sec - указатель на текущий узел сообщения (<item>) sec - указатель на текущий узел сообщения (<item>)
*/ */
void setReadConsumerItem( ReaderSlot sl ); void setReadConsumerItem( ReaderSlot sl );
/*! Установить фильтр на чтение списка датчиков /*! Установить фильтр на чтение списка датчиков
\note Функцию необходимо вызывать до вызова read(...) \note Функцию необходимо вызывать до вызова read(...)
*/ */
void setItemFilter( const std::string& filterField, const std::string& filterValue = "" ); void setItemFilter( const std::string& filterField, const std::string& filterValue = "" );
/*! Установить фильтр на чтение списка заказчиков (по каждому датчику) /*! Установить фильтр на чтение списка заказчиков (по каждому датчику)
\note Функцию необходимо вызывать до вызова read(...) \note Функцию необходимо вызывать до вызова read(...)
*/ */
void setConsumerFilter( const std::string& filterField, const std::string& filterValue = "" ); void setConsumerFilter( const std::string& filterField, const std::string& filterValue = "" );
/*! универсальная функция получения информации о заказчике (id и node) /*! универсальная функция получения информации о заказчике (id и node)
по новому формату файла (<consumer name="xxxx" type="objects" />) по новому формату файла (<consumer name="xxxx" type="objects" />)
\return true - если идентификаторы определены \return true - если идентификаторы определены
*/ */
bool getConsumerInfo( UniXML::iterator& it, bool getConsumerInfo( UniXML::iterator& it,
uniset::ObjectId& cid, uniset::ObjectId& cnode ) const; uniset::ObjectId& cid, uniset::ObjectId& cnode ) const;
/*! Функция поиска по текущему уровню (без рекурсии для дочерних узлов) */ /*! Установить фильтр на чтение списка 'порогов' */
static xmlNode* find_node( const std::shared_ptr<UniXML>& xml, xmlNode* root, const std::string& nodename, const std::string& nm = "" ); void setThresholdsFilter( const std::string& filterField, const std::string& filterValue = "" );
protected: /*! установить функцию для callback-вызова
при чтении списка пороговых датчиков.
virtual bool check_list_item( UniXML::iterator& it ) const; bool xxxMyClass::myfunc(UniXML& xml,
virtual bool check_consumer_item( UniXML::iterator& it ) const; UniXML::iterator& it, xmlNode* sec)
uxml - интерфейс для работы с xml-файлом
it - интератор(указатель) на текущий считываемый xml-узел (<sensor>)
sec - указатель на корневой узел секции (<threshold>)
*/
void setReadThresholdItem( ReaderSlot sl );
ReaderSlot rslot;
ReaderSlot cslot; typedef sigc::slot<bool, const std::shared_ptr<UniXML>&, UniXML::iterator&, xmlNode*, std::shared_ptr<IOController::USensorInfo>&> NCReaderSlot;
/*! установить callback на событие формирования информации в формате IOController (USenorInfo) */
void setNCReadItem( NCReaderSlot sl );
protected:
IOConfig_XML();
bool check_list_item( UniXML::iterator& it ) const;
bool check_consumer_item( UniXML::iterator& it ) const;
bool check_thresholds_item( UniXML::iterator& it ) const;
void read_consumers( const std::shared_ptr<UniXML>& xml, xmlNode* node, std::shared_ptr<IOController::USensorInfo>& inf );
IOController::IOStateList read_list( xmlNode* node );
void init_thresholds( xmlNode* node, IOController::IOStateList& iolist );
void init_depends_signals( IOController::IOStateList& lst );
bool getBaseInfo( xmlNode* it, IOController_i::SensorInfo& si ) const;
bool getSensorInfo( xmlNode* snode, std::shared_ptr<IOController::USensorInfo>& si ) const;
bool getThresholdInfo(xmlNode* tnode, std::shared_ptr<IOController::UThresholdInfo>& ti) const;
// bool getConsumerList( const std::shared_ptr<UniXML>& xml, xmlNode* node, IONotifyController::ConsumerListInfo& lst) const;
static void set_dumptime( const std::shared_ptr<UniXML>& xml, xmlNode* node );
static xmlNode* bind_node( const std::shared_ptr<UniXML>& xml, xmlNode* root, const std::string& nodename, const std::string& nm = "");
static xmlNode* rebind_node( const std::shared_ptr<UniXML>& xml, xmlNode* root, const std::string& nodename, const std::string& nm = "");
std::string s_filterField = { "" };
std::string s_filterValue = { "" };
std::string t_filterField = { "" };
std::string t_filterValue = { "" };
std::string i_filterField = { "" }; std::string i_filterField = { "" };
std::string i_filterValue = { "" }; std::string i_filterValue = { "" };
std::string c_filterField = { "" }; std::string c_filterField = { "" };
std::string c_filterValue = { "" }; std::string c_filterValue = { "" };
std::string fname = { "" };
std::shared_ptr<Configuration> conf;
std::shared_ptr<UniXML> uxml;
xmlNode* root = { nullptr };
ReaderSlot rtslot;
ReaderSlot rslot;
ReaderSlot cslot;
NCReaderSlot ncrslot;
private:
}; };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
} // end of uniset namespace } // end of uniset namespace
// -------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#endif #endif // IOConfig_XML_H_
// --------------------------------------------------------------------------
...@@ -138,6 +138,7 @@ namespace uniset ...@@ -138,6 +138,7 @@ namespace uniset
// полнейшее нарушение икапсуляции // полнейшее нарушение икапсуляции
// но пока, это попытка оптимизировать работу с IOController через указатель. // но пока, это попытка оптимизировать работу с IOController через указатель.
// Т.е. работая с датчиками через итераторы.. // Т.е. работая с датчиками через итераторы..
#if 1
inline IOStateList::iterator ioBegin() inline IOStateList::iterator ioBegin()
{ {
return ioList.begin(); return ioList.begin();
...@@ -150,7 +151,7 @@ namespace uniset ...@@ -150,7 +151,7 @@ namespace uniset
{ {
return ioList.find(k); return ioList.find(k);
} }
#endif
inline int ioCount() const noexcept inline int ioCount() const noexcept
{ {
return ioList.size(); return ioList.size();
...@@ -200,10 +201,8 @@ namespace uniset ...@@ -200,10 +201,8 @@ namespace uniset
// signal по изменению определённого датчика // signal по изменению определённого датчика
InitSignal signal_init(); InitSignal signal_init();
/*! регистрация датчика /*! регистрация датчика в репозитории */
force=true - не проверять на дублирование (оптимизация) void ioRegistration(std::shared_ptr<USensorInfo>& usi );
*/
void ioRegistration(std::shared_ptr<USensorInfo>& usi, bool force = false );
/*! разрегистрация датчика */ /*! разрегистрация датчика */
void ioUnRegistration( const uniset::ObjectId sid ); void ioUnRegistration( const uniset::ObjectId sid );
...@@ -252,6 +251,12 @@ namespace uniset ...@@ -252,6 +251,12 @@ namespace uniset
IOStateList::iterator myioEnd(); IOStateList::iterator myioEnd();
IOStateList::iterator myiofind( uniset::ObjectId id ); IOStateList::iterator myiofind( uniset::ObjectId id );
void initIOList( const IOStateList&& l );
typedef std::function<void(std::shared_ptr<USensorInfo>&)> UFunction;
// функция работает с mutex
void for_iolist( UFunction f );
private: private:
friend class NCRestorer; friend class NCRestorer;
friend class SMInterface; friend class SMInterface;
...@@ -271,6 +276,10 @@ namespace uniset ...@@ -271,6 +276,10 @@ namespace uniset
std::mutex loggingMutex; /*!< logging info mutex */ std::mutex loggingMutex; /*!< logging info mutex */
public: public:
struct UThresholdInfo;
typedef std::list<std::shared_ptr<UThresholdInfo>> ThresholdExtList;
struct USensorInfo: struct USensorInfo:
public IOController_i::SensorIOInfo public IOController_i::SensorIOInfo
{ {
...@@ -305,7 +314,7 @@ namespace uniset ...@@ -305,7 +314,7 @@ namespace uniset
// Дополнительные (вспомогательные поля) // Дополнительные (вспомогательные поля)
uniset::uniset_rwmutex val_lock; /*!< флаг блокирующий работу со значением */ uniset::uniset_rwmutex val_lock; /*!< флаг блокирующий работу со значением */
// userdata (универасльный, небезопасный способ расширения информации связанной с датчиком) // userdata (универсальный, но небезопасный способ расширения информации связанной с датчиком)
static const size_t MaxUserData = 4; static const size_t MaxUserData = 4;
void* userdata[MaxUserData] = { nullptr, nullptr, nullptr, nullptr }; /*!< расширение для возможности хранения своей информации */ void* userdata[MaxUserData] = { nullptr, nullptr, nullptr, nullptr }; /*!< расширение для возможности хранения своей информации */
uniset::uniset_rwmutex userdata_lock; /*!< mutex для работы с userdata */ uniset::uniset_rwmutex userdata_lock; /*!< mutex для работы с userdata */
...@@ -326,6 +335,10 @@ namespace uniset ...@@ -326,6 +335,10 @@ namespace uniset
long d_off_value = { 0 }; /*!< блокирующее значение */ long d_off_value = { 0 }; /*!< блокирующее значение */
std::shared_ptr<USensorInfo> d_usi; // shared_ptr на датчик от которого зависит этот. std::shared_ptr<USensorInfo> d_usi; // shared_ptr на датчик от которого зависит этот.
// список пороговых датчиков для данного
uniset::uniset_rwmutex tmut;
ThresholdExtList thresholds;
size_t nchanges = { 0 }; // количество изменений датчика size_t nchanges = { 0 }; // количество изменений датчика
// функция обработки информации об изменении состояния датчика, от которого зависит данный // функция обработки информации об изменении состояния датчика, от которого зависит данный
...@@ -372,6 +385,57 @@ namespace uniset ...@@ -372,6 +385,57 @@ namespace uniset
return sm; return sm;
} }
}; };
/*! Информация о пороговом значении */
struct UThresholdInfo:
public IONotifyController_i::ThresholdInfo
{
UThresholdInfo( uniset::ThresholdId tid, CORBA::Long low, CORBA::Long hi, bool inv,
uniset::ObjectId _sid = uniset::DefaultObjectId ):
sid(_sid),
invert(inv)
{
id = tid;
hilimit = hi;
lowlimit = low;
state = IONotifyController_i::NormalThreshold;
}
/*! идентификатор дискретного датчика связанного с данным порогом */
uniset::ObjectId sid;
/*! итератор в списке датчиков (для быстрого доступа) */
IOController::IOStateList::iterator sit;
/*! инверсная логика */
bool invert;
inline bool operator== ( const ThresholdInfo& r ) const
{
return ((id == r.id) &&
(hilimit == r.hilimit) &&
(lowlimit == r.lowlimit) &&
(invert == r.invert) );
}
operator IONotifyController_i::ThresholdInfo()
{
IONotifyController_i::ThresholdInfo r;
r.id = id;
r.hilimit = hilimit;
r.lowlimit = lowlimit;
r.invert = invert;
r.tv_sec = tv_sec;
r.tv_nsec = tv_nsec;
r.state = state;
return r;
}
UThresholdInfo( const UThresholdInfo& ) = delete;
UThresholdInfo& operator=( const UThresholdInfo& ) = delete;
UThresholdInfo( UThresholdInfo&& ) = default;
UThresholdInfo& operator=(UThresholdInfo&& ) = default;
};
}; };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
} // end of uniset namespace } // end of uniset namespace
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
class NCRestorer; class IOConfig;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/*! /*!
\page page_IONotifyController Хранение информации о состоянии с уведомлениями об изменении (IONotifyController) \page page_IONotifyController Хранение информации о состоянии с уведомлениями об изменении (IONotifyController)
...@@ -136,8 +136,8 @@ namespace uniset ...@@ -136,8 +136,8 @@ namespace uniset
{ {
public: public:
IONotifyController(const std::string& name, const std::string& section, std::shared_ptr<NCRestorer> dumper = nullptr ); IONotifyController(const std::string& name, const std::string& section, std::shared_ptr<IOConfig> ioconf = nullptr );
IONotifyController(const uniset::ObjectId id, std::shared_ptr<NCRestorer> dumper = nullptr ); IONotifyController(const uniset::ObjectId id, std::shared_ptr<IOConfig> ioconf = nullptr );
virtual ~IONotifyController(); virtual ~IONotifyController();
...@@ -208,83 +208,14 @@ namespace uniset ...@@ -208,83 +208,14 @@ namespace uniset
/*! словарь: датчик -> список потребителей */ /*! словарь: датчик -> список потребителей */
typedef std::unordered_map<uniset::ObjectId, ConsumerListInfo> AskMap; typedef std::unordered_map<uniset::ObjectId, ConsumerListInfo> AskMap;
/*! Информация о пороговом значении */ // связь: id датчика --> id порога --> список заказчиков
struct ThresholdInfoExt: // т.к. каждый порог имеет уникальный указатель, используем его в качестве ключа
public IONotifyController_i::ThresholdInfo typedef std::unordered_map<UThresholdInfo*, ConsumerListInfo> AskThresholdMap;
{
ThresholdInfoExt( uniset::ThresholdId tid, CORBA::Long low, CORBA::Long hi, bool inv,
uniset::ObjectId _sid = uniset::DefaultObjectId ):
sid(_sid),
invert(inv)
{
id = tid;
hilimit = hi;
lowlimit = low;
state = IONotifyController_i::NormalThreshold;
}
ConsumerListInfo clst; /*!< список заказчиков данного порога */
/*! идентификатор дискретного датчика связанного с данным порогом */
uniset::ObjectId sid;
/*! итератор в списке датчиков (для оптимально-быстрого доступа) */
IOController::IOStateList::iterator sit;
/*! инверсная логика */
bool invert;
inline bool operator== ( const ThresholdInfo& r ) const
{
return ((id == r.id) &&
(hilimit == r.hilimit) &&
(lowlimit == r.lowlimit) &&
(invert == r.invert) );
}
operator IONotifyController_i::ThresholdInfo()
{
IONotifyController_i::ThresholdInfo r;
r.id = id;
r.hilimit = hilimit;
r.lowlimit = lowlimit;
r.invert = invert;
r.tv_sec = tv_sec;
r.tv_nsec = tv_nsec;
r.state = state;
return r;
}
ThresholdInfoExt( const ThresholdInfoExt& ) = delete;
ThresholdInfoExt& operator=( const ThresholdInfoExt& ) = delete;
ThresholdInfoExt( ThresholdInfoExt&& ) = default;
ThresholdInfoExt& operator=(ThresholdInfoExt&& ) = default;
};
/*! список порогов (информация по каждому порогу) */
typedef std::list<ThresholdInfoExt> ThresholdExtList;
struct ThresholdsListInfo
{
ThresholdsListInfo() {}
ThresholdsListInfo( const IOController_i::SensorInfo& si, ThresholdExtList&& list,
UniversalIO::IOType t = UniversalIO::AI ):
si(si), type(t), list( std::move(list) ) {}
uniset::uniset_rwmutex mut;
IOController_i::SensorInfo si = { uniset::DefaultObjectId, uniset::DefaultObjectId };
std::shared_ptr<USensorInfo> usi;
UniversalIO::IOType type = { UniversalIO::AI };
ThresholdExtList list; /*!< список порогов по данному аналоговому датчику */
};
/*! словарь: аналоговый датчик --> список порогов по нему */
typedef std::unordered_map<uniset::ObjectId, ThresholdsListInfo> AskThresholdMap;
protected: protected:
IONotifyController(); IONotifyController();
virtual bool activateObject() override; virtual bool activateObject() override;
virtual void sensorsRegistration() override;
virtual void initItem( std::shared_ptr<USensorInfo>& usi, IOController* ic ); virtual void initItem( std::shared_ptr<USensorInfo>& usi, IOController* ic );
//! посылка информации об изменении состояния датчика (всем или указанному заказчику) //! посылка информации об изменении состояния датчика (всем или указанному заказчику)
...@@ -292,25 +223,15 @@ namespace uniset ...@@ -292,25 +223,15 @@ namespace uniset
//! проверка срабатывания пороговых датчиков //! проверка срабатывания пороговых датчиков
virtual void checkThreshold( std::shared_ptr<USensorInfo>& usi, bool send = true ); virtual void checkThreshold( std::shared_ptr<USensorInfo>& usi, bool send = true );
virtual void checkThreshold(IOController::IOStateList::iterator& li, const uniset::ObjectId sid, bool send_msg = true ); virtual void checkThreshold( IOController::IOStateList::iterator& li, const uniset::ObjectId sid, bool send_msg = true );
//! поиск информации о пороговом датчике //! поиск информации о пороговом датчике
ThresholdInfoExt* findThreshold( AskThresholdMap& tmap, const uniset::ObjectId sid, const uniset::ThresholdId tid ); std::shared_ptr<UThresholdInfo> findThreshold( const uniset::ObjectId sid, const uniset::ThresholdId tid );
/*! сохранение списка заказчиков
По умолчанию делает dump, если объявлен dumper.
*/
virtual void dumpOrdersList( const uniset::ObjectId sid, const IONotifyController::ConsumerListInfo& lst );
/*! сохранение списка заказчиков пороговых датчиков
По умолчанию делает dump, если объявлен dumper.
*/
virtual void dumpThresholdList( const uniset::ObjectId sid, const IONotifyController::ThresholdExtList& lst );
/*! чтение dump-файла */ /*! чтение dump-файла */
virtual void readDump(); virtual void readConf();
std::shared_ptr<NCRestorer> restorer; std::shared_ptr<IOConfig> restorer;
void onChangeUndefinedState( std::shared_ptr<USensorInfo>& usi, IOController* ic ); void onChangeUndefinedState( std::shared_ptr<USensorInfo>& usi, IOController* ic );
...@@ -318,14 +239,6 @@ namespace uniset ...@@ -318,14 +239,6 @@ namespace uniset
virtual long localSetValue( std::shared_ptr<USensorInfo>& usi, virtual long localSetValue( std::shared_ptr<USensorInfo>& usi,
CORBA::Long value, uniset::ObjectId sup_id ) override; CORBA::Long value, uniset::ObjectId sup_id ) override;
//! \warning Оптимизация использует userdata! Это опасно, если кто-то ещё захочет его использовать!
// идентификаторы данные в userdata (см. USensorInfo::userdata)
enum UserDataID
{
udataConsumerList = 0,
udataThresholdList = 1
};
#ifndef DISABLE_REST_API #ifndef DISABLE_REST_API
// http api // http api
Poco::JSON::Object::Ptr request_consumers( const std::string& req, const Poco::URI::QueryParameters& p ); Poco::JSON::Object::Ptr request_consumers( const std::string& req, const Poco::URI::QueryParameters& p );
...@@ -340,22 +253,33 @@ namespace uniset ...@@ -340,22 +253,33 @@ namespace uniset
void showStatisticsForConsumersWithLostEvent( std::ostringstream& inf ); void showStatisticsForConsumersWithLostEvent( std::ostringstream& inf );
void showStatisticsForSensor( std::ostringstream& inf, const std::string& name ); void showStatisticsForSensor( std::ostringstream& inf, const std::string& name );
//! \warning Оптимизация использует userdata! Это опасно, если кто-то ещё захочет его использовать!
// идентификаторы данных в userdata (см. USensorInfo::userdata)
enum UserDataID
{
udataConsumerList = 0
};
private: private:
friend class NCRestorer; friend class NCRestorer;
//---------------------- //----------------------
bool addConsumer(ConsumerListInfo& lst, const uniset::ConsumerInfo& cons ); //!< добавить потребителя сообщения bool addConsumer( ConsumerListInfo& lst, const uniset::ConsumerInfo& cons ); //!< добавить потребителя сообщения
bool removeConsumer(ConsumerListInfo& lst, const uniset::ConsumerInfo& cons ); //!< удалить потребителя сообщения bool removeConsumer( ConsumerListInfo& lst, const uniset::ConsumerInfo& cons ); //!< удалить потребителя сообщения
//! обработка заказа //! обработка заказа
void ask(AskMap& askLst, const uniset::ObjectId sid, void ask(AskMap& askLst, const uniset::ObjectId sid,
const uniset::ConsumerInfo& ci, UniversalIO::UIOCommand cmd); const uniset::ConsumerInfo& ci, UniversalIO::UIOCommand cmd);
/*! добавить новый порог для датчика */ /*! добавить новый порог для датчика */
bool addThreshold(ThresholdExtList& lst, ThresholdInfoExt&& ti, const uniset::ConsumerInfo& ci); std::shared_ptr<UThresholdInfo> addThresholdIfNotExist( std::shared_ptr<USensorInfo>& usi, std::shared_ptr<UThresholdInfo>& ti );
bool addThresholdConsumer( std::shared_ptr<UThresholdInfo>& ti, const uniset::ConsumerInfo& ci );
/*! удалить порог для датчика */ /*! удалить порог для датчика */
bool removeThreshold(ThresholdExtList& lst, ThresholdInfoExt& ti, const uniset::ConsumerInfo& ci); bool removeThresholdConsumer( std::shared_ptr<USensorInfo>& usi,
std::shared_ptr<UThresholdInfo>& ti,
const uniset::ConsumerInfo& ci);
AskMap askIOList; /*!< список потребителей по датчикам */ AskMap askIOList; /*!< список потребителей по датчикам */
AskThresholdMap askTMap; /*!< список порогов по датчикам */ AskThresholdMap askTMap; /*!< список порогов по датчикам */
......
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Интерфейс к объекту сохраняющему список заказчиков для NotifyController-ов
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#ifndef NCRestorer_H_
#define NCRestorer_H_
// ------------------------------------------------------------------------------------------
#include <memory>
#include <sigc++/sigc++.h>
#include <string>
#include "UniXML.h"
#include "Restorer.h"
#include "IOController.h"
#include "IONotifyController.h"
// ------------------------------------------------------------------------------------------
namespace uniset
{
/*!
Интерфейс для записи в файл и восстановления из файла списка заказчиков по датчикам для
IONotifyController-а (NC).
\note Это абстрактный интерфейс. В чистом виде не используется.
*/
class NCRestorer
{
public:
NCRestorer();
virtual ~NCRestorer();
struct SInfo:
public IOController::USensorInfo
{
SInfo( const SInfo& ) = delete;
const SInfo& operator=(const SInfo& ) = delete;
SInfo( SInfo&& ) = default;
SInfo& operator=(SInfo&& ) = default;
SInfo( IOController_i::SensorInfo& si, UniversalIO::IOType& t,
uniset::Message::Message::Priority& p, long& def ) noexcept
{
this->si = si;
this->type = t;
this->priority = p;
this->default_val = def;
}
SInfo() noexcept
{
this->type = UniversalIO::DI;
this->priority = uniset::Message::Medium;
this->default_val = 0;
}
SInfo& operator=(const IOController_i::SensorIOInfo& inf);
SInfo( const IOController_i::SensorIOInfo& inf );
};
virtual void read( IONotifyController* ic, const std::string& fn = "" ) = 0;
virtual void dump(const IONotifyController* ic, std::shared_ptr<SInfo>& inf, const IONotifyController::ConsumerListInfo& lst) = 0;
virtual void dumpThreshold(const IONotifyController* ic, std::shared_ptr<SInfo>& inf, const IONotifyController::ThresholdExtList& lst) = 0;
// проверка поддерживаются ли функции dumpXXX (т.е. обновление списков)
virtual bool readOnly() const = 0;
protected:
// добавление списка заказчиков
static void addlist( IONotifyController* ic, std::shared_ptr<IOController::USensorInfo>& inf, IONotifyController::ConsumerListInfo&& lst, bool force = false );
// добавление списка порогов и заказчиков
static void addthresholdlist( IONotifyController* ic, std::shared_ptr<IOController::USensorInfo>& inf, IONotifyController::ThresholdExtList&& lst, bool force = false );
static inline void ioRegistration( IONotifyController* ic, std::shared_ptr<IOController::USensorInfo>& inf, bool force = false )
{
ic->ioRegistration(inf, force);
}
static inline IOController::IOStateList::iterator ioFind( IONotifyController* ic, uniset::ObjectId k ) noexcept
{
return ic->myiofind(k);
}
static inline IOController::IOStateList::iterator ioEnd( IONotifyController* ic ) noexcept
{
return ic->myioEnd();
}
static inline IOController::IOStateList::iterator ioBegin( IONotifyController* ic ) noexcept
{
return ic->myioBegin();
}
static void init_depends_signals( IONotifyController* ic );
};
// ------------------------------------------------------------------------------------------
/*!
* \brief Реализация сохранения списка заказчиков в xml.
Данный класс работает с глобальным xml-файлом проекта (обычно configure.xml),
поэтому НЕ реализаует функции записи (dump)-а.
*/
class NCRestorer_XML:
public Restorer_XML,
public NCRestorer
{
public:
/*!
\param fname - файл. (формата uniset-project)
*/
NCRestorer_XML( const std::string& fname );
/*!
\param fname - файл. (формата uniset-project)
\param sensor_filterField - читать из списка только те узлы, у которых filterField="filterValue"
\param sensor_filterValue - значение для фильтрования списка
*/
NCRestorer_XML( const std::string& fname, const std::string& sensor_filterField, const std::string& sensor_filterValue = "" );
virtual ~NCRestorer_XML();
NCRestorer_XML();
/*! Установить фильтр на чтение списка 'порогов' */
void setThresholdsFilter( const std::string& filterField, const std::string& filterValue = "" );
bool setFileName( const std::string& file, bool create );
inline std::string getFileName() const noexcept
{
return fname;
}
/*! установить функцию для callback-вызова
при чтении списка пороговых датчиков.
bool xxxMyClass::myfunc(UniXML& xml,
UniXML::iterator& it, xmlNode* sec)
uxml - интерфейс для работы с xml-файлом
it - интератор(указатель) на текущий считываемый xml-узел (<sensor>)
sec - указатель на корневой узел секции (<threshold>)
*/
void setReadThresholdItem( ReaderSlot sl );
typedef sigc::slot<bool, const std::shared_ptr<UniXML>&, UniXML::iterator&, xmlNode*, std::shared_ptr<IOController::USensorInfo>&> NCReaderSlot;
void setNCReadItem( NCReaderSlot sl );
virtual void read( IONotifyController* ic, const std::string& filename = "" );
virtual void read( IONotifyController* ic, const std::shared_ptr<UniXML>& xml );
virtual void dump(const IONotifyController* ic, std::shared_ptr<NCRestorer::SInfo>& inf, const IONotifyController::ConsumerListInfo& lst) override;
virtual void dumpThreshold(const IONotifyController* ic, std::shared_ptr<NCRestorer::SInfo>& inf, const IONotifyController::ThresholdExtList& lst) override;
virtual bool readOnly() const
{
return true;
}
protected:
bool check_thresholds_item( UniXML::iterator& it ) const;
void read_consumers( const std::shared_ptr<UniXML>& xml, xmlNode* node, std::shared_ptr<NCRestorer_XML::SInfo>& inf, IONotifyController* ic );
void read_list( const std::shared_ptr<UniXML>& xml, xmlNode* node, IONotifyController* ic);
void read_thresholds( const std::shared_ptr<UniXML>& xml, xmlNode* node, IONotifyController* ic);
void init( const std::string& fname );
bool getBaseInfo( const std::shared_ptr<UniXML>& xml, xmlNode* it, IOController_i::SensorInfo& si ) const;
bool getSensorInfo( const std::shared_ptr<UniXML>& xml, xmlNode* snode, std::shared_ptr<NCRestorer_XML::SInfo>& si ) const;
bool getConsumerList( const std::shared_ptr<UniXML>& xml, xmlNode* node, IONotifyController::ConsumerListInfo& lst) const;
bool getThresholdInfo(const std::shared_ptr<UniXML>& xml, xmlNode* tnode, IONotifyController::ThresholdInfoExt& ti) const;
static void set_dumptime( const std::shared_ptr<UniXML>& xml, xmlNode* node );
static xmlNode* bind_node( const std::shared_ptr<UniXML>& xml, xmlNode* root, const std::string& nodename, const std::string& nm = "");
static xmlNode* rebind_node( const std::shared_ptr<UniXML>& xml, xmlNode* root, const std::string& nodename, const std::string& nm = "");
std::string s_filterField = { "" };
std::string s_filterValue = { "" };
std::string t_filterField = { "" };
std::string t_filterValue = { "" };
std::string fname = { "" };
std::shared_ptr<UniXML> uxml;
ReaderSlot rtslot;
NCReaderSlot ncrslot;
private:
};
// -------------------------------------------------------------------------
} // end of uniset namespace
// ------------------------------------------------------------------------------------------
#endif
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Блокировка повторного запуска программы
* \author Ahton Korbin, Pavel Vainerman
*/
// ---------------------------------------------------------------------------
#ifndef RunLock_H_
#define RunLock_H_
// ---------------------------------------------------------------------------
#include <string>
// ---------------------------------------------------------------------------
namespace uniset
{
/*! Защита от поторного запуска программы(процесса).
При вызове lock(lockFile) в файл lockFile записывается pid текущего процесса.
При вызове isLocked() проверяется состояние процесса по его pid (записанному в файл).
unlock() - удаляет файл.
\warning Код не переносимый, т.к. рассчитан на наличие каталога /proc,
по которому проверяется статус процесса (по pid).
*/
class RunLock
{
public:
RunLock();
~RunLock();
static bool isLocked(const std::string& lockFile); //, char* **argv );
static bool lock(const std::string& lockFile);
static bool unlock(const std::string& lockFile);
protected:
};
// -------------------------------------------------------------------------
} // end of uniset namespace
// ----------------------------------------------------------------------------
#endif
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
namespace uniset namespace uniset
{ {
// класс обёртка, понадобился только для того, чтобы достучаться до "сырого" сокета // класс обёртка, понадобился только для того, чтобы достучаться до "сырого" сокета
// и иметь возможность использоватб его с libev // и иметь возможность использовать его с libev
class USocket: class USocket:
public Poco::Net::Socket public Poco::Net::Socket
{ {
......
...@@ -184,6 +184,12 @@ namespace uniset ...@@ -184,6 +184,12 @@ namespace uniset
//depth means number of times we can go to the children, if 0 we can't go only to elements of the same level //depth means number of times we can go to the children, if 0 we can't go only to elements of the same level
xmlNode* extFindNode( xmlNode* node, int depth, int width, const std::string& searchnode, const std::string& name = "", bool top = true ) const; xmlNode* extFindNode( xmlNode* node, int depth, int width, const std::string& searchnode, const std::string& name = "", bool top = true ) const;
// Функция поиска по текущему уровню (без рекурсии для дочерних узлов)
// root указывается исходный, внутри функции осуществляется переход к списку дочерних узлов
// (другими словами делать goChildren() не надо)
xmlNode* findNodeLevel1( xmlNode* root, const std::string& nodename, const std::string& nm = "" );
protected: protected:
std::string filename; std::string filename;
......
...@@ -248,7 +248,7 @@ void UniSetManager::managers( OManagerCommand cmd ) ...@@ -248,7 +248,7 @@ void UniSetManager::managers( OManagerCommand cmd )
//lock //lock
uniset_rwmutex_rlock lock(mlistMutex); uniset_rwmutex_rlock lock(mlistMutex);
for( const auto& li: mlist ) for( const auto& li : mlist )
{ {
if( !li ) if( !li )
continue; continue;
...@@ -347,7 +347,7 @@ void UniSetManager::objects(OManagerCommand cmd) ...@@ -347,7 +347,7 @@ void UniSetManager::objects(OManagerCommand cmd)
//lock //lock
uniset_rwmutex_rlock lock(olistMutex); uniset_rwmutex_rlock lock(olistMutex);
for( const auto& li: olist ) for( const auto& li : olist )
{ {
if( !li ) if( !li )
continue; continue;
...@@ -607,7 +607,7 @@ int UniSetManager::getObjectsInfo( const std::shared_ptr<UniSetManager>& mngr, S ...@@ -607,7 +607,7 @@ int UniSetManager::getObjectsInfo( const std::shared_ptr<UniSetManager>& mngr, S
if( ind > uplimit ) if( ind > uplimit )
return ind; return ind;
for( const auto& o: olist ) for( const auto& o : olist )
{ {
try try
{ {
...@@ -633,7 +633,7 @@ int UniSetManager::getObjectsInfo( const std::shared_ptr<UniSetManager>& mngr, S ...@@ -633,7 +633,7 @@ int UniSetManager::getObjectsInfo( const std::shared_ptr<UniSetManager>& mngr, S
return ind; return ind;
// а далее у его менеджеров (рекурсивно) // а далее у его менеджеров (рекурсивно)
for( const auto& m: mlist ) for( const auto& m : mlist )
{ {
ind = getObjectsInfo(m, seq, ind, uplimit, userparam ); ind = getObjectsInfo(m, seq, ind, uplimit, userparam );
...@@ -667,13 +667,13 @@ SimpleInfoSeq* UniSetManager::getObjectsInfo(CORBA::Long maxlength, const char* ...@@ -667,13 +667,13 @@ SimpleInfoSeq* UniSetManager::getObjectsInfo(CORBA::Long maxlength, const char*
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void UniSetManager::apply_for_objects( OFunction f ) void UniSetManager::apply_for_objects( OFunction f )
{ {
for( const auto& o: olist ) for( const auto& o : olist )
f(o); f(o);
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void UniSetManager::apply_for_managers(UniSetManager::MFunction f) void UniSetManager::apply_for_managers(UniSetManager::MFunction f)
{ {
for( const auto& m: mlist ) for( const auto& m : mlist )
f(m); f(m);
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
......
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// --------------------------------------------------------------------------
#include <sstream>
#include "Configuration.h"
#include "IOController.h"
#include "IONotifyController.h"
#include "IOConfig_XML.h"
// --------------------------------------------------------------------------
using namespace std;
// --------------------------------------------------------------------------
namespace uniset
{
// --------------------------------------------------------------------------
IOConfig_XML::IOConfig_XML()
{
}
// --------------------------------------------------------------------------
IOConfig_XML::IOConfig_XML( const std::string& confile,
const std::shared_ptr<Configuration>& _conf ):
conf(_conf)
{
uxml = make_shared<UniXML>(confile);
}
// --------------------------------------------------------------------------
IOConfig_XML::IOConfig_XML(const std::shared_ptr<UniXML>& _xml,
const std::shared_ptr<Configuration>& _conf,
xmlNode* _root ):
conf(_conf),
uxml(_xml),
root(_root)
{
}
// --------------------------------------------------------------------------
IOConfig_XML::~IOConfig_XML()
{
}
// --------------------------------------------------------------------------
IOController::IOStateList IOConfig_XML::read()
{
IOController::IOStateList lst;
if( !root )
{
root = uxml->findNode( uxml->getFirstNode(), "sensors");
UniXML::iterator it(root);
it.goChildren();
root = it.getCurrent();
}
if( root )
{
lst = read_list(root);
// только после чтения всех датчиков и формирования списка IOList
// можно инициализировать списки зависимостей
init_depends_signals(lst);
xmlNode* tnode = uxml->findNode(uxml->getFirstNode(), "thresholds");
if( tnode )
init_thresholds(tnode, lst);
}
return lst;
}
// --------------------------------------------------------------------------
IOController::IOStateList IOConfig_XML::read_list( xmlNode* node )
{
IOController::IOStateList lst;
UniXML::iterator it(node);
if( !it.getCurrent() )
return lst;
for( ; it.getCurrent(); ++it )
{
if( !check_list_item(it) )
continue;
auto inf = make_shared<IOController::USensorInfo>();
if( !getSensorInfo(it, inf) )
{
uwarn << "(IOConfig_XML::read_list): FAILED read parameters for " << it.getProp("name") << endl;
continue;
}
inf->undefined = false;
ncrslot(uxml, it, node, inf);
rslot(uxml, it, node);
// read_consumers(xml, it, inf);
lst.emplace( inf->si.id, std::move(inf) );
}
return lst;
}
// ------------------------------------------------------------------------------------------
bool IOConfig_XML::getBaseInfo( xmlNode* node, IOController_i::SensorInfo& si ) const
{
UniXML::iterator it(node);
string sname( it.getProp("name"));
if( sname.empty() )
{
uwarn << "(IOConfig_XML::getBaseInfo): Unknown sensor name... skipped..." << endl;
return false;
}
// преобразуем в полное имя
ObjectId sid = uniset::DefaultObjectId;
string id(it.getProp("id"));
if( !id.empty() )
sid = uni_atoi( id );
else
sid = conf->getSensorID(sname);
if( sid == uniset::DefaultObjectId )
{
ostringstream err;
err << "(IOConfig_XML::getBaseInfo): Not found ID for sensor --> " << sname;
ucrit << err.str() << endl;
throw SystemError(err.str());
}
ObjectId snode = conf->getLocalNode();
string snodename(it.getProp("node"));
if( !snodename.empty() )
snode = conf->getNodeID(snodename);
if( snode == uniset::DefaultObjectId )
{
ucrit << "(IOConfig_XML::getBaseInfo): Not found ID for node --> " << snodename << endl;
return false;
}
si.id = sid;
si.node = snode;
return true;
}
// ------------------------------------------------------------------------------------------
bool IOConfig_XML::getSensorInfo( xmlNode* node,
std::shared_ptr<IOController::USensorInfo>& inf ) const
{
if( !getBaseInfo(node, inf->si) )
return false;
UniXML::iterator it(node);
inf->priority = Message::Medium;
string prior(it.getProp("priority"));
if( prior == "Low" )
inf->priority = Message::Low;
else if( prior == "Medium" )
inf->priority = Message::Medium;
else if( prior == "High" )
inf->priority = Message::High;
else
inf->priority = Message::Medium;
inf->type = uniset::getIOType(it.getProp("iotype"));
if( inf->type == UniversalIO::UnknownIOType )
{
ostringstream err;
err << "(IOConfig_XML:getSensorInfo): unknown iotype=" << it.getProp("iotype")
<< " for " << it.getProp("name");
ucrit << err.str() << endl;
throw SystemError(err.str());
}
// калибровка
if( inf->type == UniversalIO::AI || inf->type == UniversalIO::AO )
{
inf->ci.minRaw = it.getIntProp("rmin");
inf->ci.maxRaw = it.getIntProp("rmax");
inf->ci.minCal = it.getIntProp("cmin");
inf->ci.maxCal = it.getIntProp("cmax");
inf->ci.precision = it.getIntProp("precision");
}
else
{
inf->ci.minRaw = 0;
inf->ci.maxRaw = 0;
inf->ci.minCal = 0;
inf->ci.maxCal = 0;
inf->ci.precision = 0;
}
inf->default_val = it.getIntProp("default");
inf->dbignore = it.getIntProp("dbignore");
inf->value = inf->default_val;
inf->undefined = false;
inf->real_value = inf->value;
string d_txt( it.getProp("depend") );
if( !d_txt.empty() )
{
inf->d_si.id = conf->getSensorID(d_txt);
if( inf->d_si.id == uniset::DefaultObjectId )
{
ostringstream err;
err << "(IOConfig_XML::getSensorInfo): sensor='"
<< it.getProp("name") << "' err: "
<< " Unknown SensorID for depend='" << d_txt;
ucrit << err.str() << endl;
throw SystemError(err.str());
}
inf->d_si.node = conf->getLocalNode();
// по умолчанию срабатывание на "1"
inf->d_value = it.getProp("depend_value").empty() ? 1 : it.getIntProp("depend_value");
inf->d_off_value = it.getPIntProp("depend_off_value", 0);
}
return true;
}
// ------------------------------------------------------------------------------------------
void IOConfig_XML::init_depends_signals( IOController::IOStateList& lst )
{
for( auto && it : lst )
{
// обновляем итераторы...
it.second->d_usi = it.second;
if( it.second->d_si.id == DefaultObjectId )
continue;
uinfo << "(IOConfig_XML::init_depends_signals): "
<< " init depend: '" << conf->oind->getMapName(it.second->si.id) << "'"
<< " dep_name=(" << it.second->d_si.id << ")'" << conf->oind->getMapName(it.second->d_si.id) << "'"
<< endl;
auto dit = lst.find(it.second->d_si.id);
if( dit != lst.end() )
{
uniset_rwmutex_rlock lock(it.second->val_lock);
dit->second->sigChange.connect( sigc::mem_fun( it.second.get(), &IOController::USensorInfo::checkDepend) );
}
}
}
// -----------------------------------------------------------------------------
void IOConfig_XML::init_thresholds( xmlNode* node, IOController::IOStateList& iolist )
{
UniXML::iterator it(node);
if( !it.goChildren() )
return;
for( ; it.getCurrent(); ++it )
{
if( !check_thresholds_item(it) )
continue;
IOController_i::SensorInfo si;
if( !getBaseInfo(it, si) )
{
ostringstream err;
err << "(IOConfig_XML::init_thresholds): failed read parameters for threashold " << it.getProp("name");
ucrit << err.str() << endl;
throw uniset::SystemError(err.str());
}
auto inf = iolist.find(si.id);
if( inf == iolist.end() )
{
ostringstream err;
err << "(IOConfig_XML::init_thresholds): NOT FOUND " << it.getProp("name");
ucrit << err.str() << endl;
throw uniset::SystemError(err.str());
}
ulog3 << "(IOConfig_XML::read_thresholds): " << it.getProp("name") << endl;
UniXML::iterator tit(it);
if( !tit.goChildren() )
continue;
IONotifyController::ThresholdExtList tlst;
for( ; tit.getCurrent(); tit++ )
{
auto ti = make_shared<IONotifyController::UThresholdInfo>(0, 0, 0, false);
if( !getThresholdInfo(tit, ti) )
{
ostringstream err;
err << "(IOConfig_XML::read_thresholds): FAILED read threshold parameters for "
<< conf->oind->getNameById(si.id);
ucrit << err.str() << endl;
throw uniset::SystemError(err.str());
}
ulog3 << "(IOConfig_XML::read_thresholds): \tthreshold low="
<< ti->lowlimit << " \thi=" << ti->hilimit
<< " \t sid=" << ti->sid
<< " \t invert=" << ti->invert
<< endl << flush;
// начальная инициализация итератора
ti->sit = iolist.end();
// порог добавляем в любом случае, даже если список заказчиков пуст...
tlst.emplace_back(ti);
rtslot(uxml, tit, it);
}
std::swap(inf->second->thresholds, tlst);
}
}
// ------------------------------------------------------------------------------------------
#if 0
void IOConfig_XML::read_consumers( const std::shared_ptr<UniXML>& xml, xmlNode* it,
std::shared_ptr<IOConfig_XML::SInfo>& inf )
{
// в новых ask-файлах список выделен <consumers>...</consumers>,
xmlNode* cnode = find_node(xml, it, "consumers", "");
if( cnode )
{
UniXML::iterator cit(cnode);
if( cit.goChildren() )
{
IONotifyController::ConsumerListInfo lst;
if( getConsumerList(xml, cit, lst) )
{
std::shared_ptr<IOController::USensorInfo> uinf = std::static_pointer_cast<IOController::USensorInfo>(inf);
addlist(ic, uinf, std::move(lst), true);
}
}
}
}
// ------------------------------------------------------------------------------------------
bool IOConfig_XML::getConsumerList( const std::shared_ptr<UniXML>& xml, xmlNode* node,
IONotifyController::ConsumerListInfo& lst ) const
{
UniXML::iterator it(node);
for(; it.getCurrent(); it++ )
{
if( !check_consumer_item(it) )
continue;
ConsumerInfo ci;
if( !getConsumerInfo(it, ci.id, ci.node) )
continue;
lst.clst.emplace_back( std::move(ci) );
cslot(xml, it, node);
}
return true;
}
#endif
// ------------------------------------------------------------------------------------------
bool IOConfig_XML::getThresholdInfo( xmlNode* node, std::shared_ptr<IONotifyController::UThresholdInfo>& ti ) const
{
UniXML::iterator uit(node);
string sid_name = uit.getProp("sid");
if( !sid_name.empty() )
{
ti->sid = conf->getSensorID(sid_name);
if( ti->sid == uniset::DefaultObjectId )
{
ostringstream err;
err << "(IOConfig_XML:getThresholdInfo): "
<< " Not found ID for " << sid_name;
ucrit << err.str() << endl;
throw uniset::SystemError(err.str());
}
else
{
UniversalIO::IOType iotype = conf->getIOType(ti->sid);
// Пока что IONotifyController поддерживает работу только с 'DI/DO'.
if( iotype != UniversalIO::DI && iotype != UniversalIO::DO )
{
ostringstream err;
err << "(IOConfig_XML:getThresholdInfo): "
<< " Bad iotype(" << iotype << ") for " << sid_name
<< ". iotype must be 'DI' or 'DO'.";
ucrit << err.str() << endl;
throw uniset::SystemError(err.str());
}
}
}
ti->id = uit.getIntProp("id");
ti->lowlimit = uit.getIntProp("lowlimit");
ti->hilimit = uit.getIntProp("hilimit");
ti->invert = uit.getIntProp("invert");
ti->state = IONotifyController_i::NormalThreshold;
return true;
}
// ------------------------------------------------------------------------------------------
bool IOConfig_XML::check_thresholds_item( UniXML::iterator& it ) const
{
return uniset::check_filter(it, t_filterField, t_filterValue);
}
// ------------------------------------------------------------------------------------------
void IOConfig_XML::setReadThresholdItem( ReaderSlot sl )
{
rtslot = sl;
}
// ------------------------------------------------------------------------------------------
void IOConfig_XML::setNCReadItem( NCReaderSlot sl )
{
ncrslot = sl;
}
// -----------------------------------------------------------------------------
void IOConfig_XML::setThresholdsFilter( const std::string& field, const std::string& val )
{
t_filterField = field;
t_filterValue = val;
}
// -----------------------------------------------------------------------------
void IOConfig_XML::setItemFilter( const string& field, const string& val )
{
i_filterField = field;
i_filterValue = val;
}
// -----------------------------------------------------------------------------
void IOConfig_XML::setConsumerFilter( const string& field, const string& val )
{
c_filterField = field;
c_filterValue = val;
}
// -----------------------------------------------------------------------------
bool IOConfig_XML::getConsumerInfo( UniXML::iterator& it,
ObjectId& cid, ObjectId& cnode ) const
{
if( !check_consumer_item(it) )
return false;
string cname( it.getProp("name"));
if( cname.empty() )
{
uwarn << "(Restorer_XML:getConsumerInfo): не указано имя заказчика..." << endl;
return false;
}
string otype(it.getProp("type"));
if( otype == "controllers" )
cname = uniset_conf()->getControllersSection() + "/" + cname;
else if( otype == "objects" )
cname = uniset_conf()->getObjectsSection() + "/" + cname;
else if( otype == "services" )
cname = uniset_conf()->getServicesSection() + "/" + cname;
else
{
uwarn << "(Restorer_XML:getConsumerInfo): неизвестный тип объекта "
<< otype << endl;
return false;
}
cid = uniset_conf()->oind->getIdByName(cname);
if( cid == uniset::DefaultObjectId )
{
ucrit << "(Restorer_XML:getConsumerInfo): НЕ НАЙДЕН ИДЕНТИФИКАТОР заказчика -->"
<< cname << endl;
return false;
}
string cnodename(it.getProp("node"));
if( !cnodename.empty() )
cnode = uniset_conf()->oind->getIdByName(cnodename);
else
cnode = uniset_conf()->getLocalNode();
if( cnode == uniset::DefaultObjectId )
{
ucrit << "(Restorer_XML:getConsumerInfo): НЕ НАЙДЕН ИДЕНТИФИКАТОР узла -->"
<< cnodename << endl;
return false;
}
uinfo << "(Restorer_XML:getConsumerInfo): " << cname << ":" << cnodename << endl;
return true;
}
// -----------------------------------------------------------------------------
bool IOConfig_XML::check_list_item( UniXML::iterator& it ) const
{
return uniset::check_filter(it, i_filterField, i_filterValue);
}
// -----------------------------------------------------------------------------
bool IOConfig_XML::check_consumer_item( UniXML::iterator& it ) const
{
return uniset::check_filter(it, c_filterField, c_filterValue);
}
// -----------------------------------------------------------------------------
void IOConfig_XML::setReadItem( ReaderSlot sl )
{
rslot = sl;
}
// -----------------------------------------------------------------------------
void IOConfig_XML::setReadConsumerItem( ReaderSlot sl )
{
cslot = sl;
}
// -----------------------------------------------------------------------------
} // end of uniset namespace
// --------------------------------------------------------------------------
...@@ -364,7 +364,7 @@ IOType IOController::getIOType( uniset::ObjectId sid ) ...@@ -364,7 +364,7 @@ IOType IOController::getIOType( uniset::ObjectId sid )
throw IOController_i::NameNotFound(err.str().c_str()); throw IOController_i::NameNotFound(err.str().c_str());
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void IOController::ioRegistration( std::shared_ptr<USensorInfo>& usi, bool force ) void IOController::ioRegistration( std::shared_ptr<USensorInfo>& usi )
{ {
// проверка задан ли контроллеру идентификатор // проверка задан ли контроллеру идентификатор
if( getId() == DefaultObjectId ) if( getId() == DefaultObjectId )
...@@ -375,35 +375,6 @@ void IOController::ioRegistration( std::shared_ptr<USensorInfo>& usi, bool force ...@@ -375,35 +375,6 @@ void IOController::ioRegistration( std::shared_ptr<USensorInfo>& usi, bool force
throw ResolveNameError(err.str()); throw ResolveNameError(err.str());
} }
{
// lock
uniset_rwmutex_wrlock lock(ioMutex);
if( !force )
{
auto li = ioList.find(usi->si.id);
if( li != ioList.end() )
{
ostringstream err;
err << "Попытка повторной регистрации датчика(" << usi->si.id << "). имя: "
<< uniset_conf()->oind->getNameById(usi->si.id);
throw ObjectNameAlready(err.str());
}
}
IOStateList::mapped_type ai = usi;
// запоминаем начальное время
struct timespec tm = uniset::now_to_timespec();
ai->tv_sec = tm.tv_sec;
ai->tv_nsec = tm.tv_nsec;
ai->value = ai->default_val;
ai->supplier = getId();
// более оптимальный способ(при условии вставки первый раз)
ioList.emplace( IOStateList::value_type(usi->si.id, std::move(ai) ));
}
try try
{ {
for( size_t i = 0; i < 2; i++ ) for( size_t i = 0; i < 2; i++ )
...@@ -659,12 +630,25 @@ IOController::IOStateList::iterator IOController::myioBegin() ...@@ -659,12 +630,25 @@ IOController::IOStateList::iterator IOController::myioBegin()
{ {
return ioList.begin(); return ioList.begin();
} }
// ----------------------------------------------------------------------------------------
IOController::IOStateList::iterator IOController::myioEnd() IOController::IOStateList::iterator IOController::myioEnd()
{ {
return ioList.end(); return ioList.end();
} }
// ----------------------------------------------------------------------------------------
void IOController::initIOList( const IOController::IOStateList&& l )
{
ioList = std::move(l);
}
// ----------------------------------------------------------------------------------------
void IOController::for_iolist( IOController::UFunction f )
{
uniset_rwmutex_rlock lck(ioMutex);
for( auto && s : ioList )
f(s.second);
}
// ----------------------------------------------------------------------------------------
IOController::IOStateList::iterator IOController::myiofind( const uniset::ObjectId id ) IOController::IOStateList::iterator IOController::myiofind( const uniset::ObjectId id )
{ {
return ioList.find(id); return ioList.find(id);
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include "IONotifyController.h" #include "IONotifyController.h"
#include "ORepHelpers.h" #include "ORepHelpers.h"
#include "Debug.h" #include "Debug.h"
#include "NCRestorer.h" #include "IOConfig.h"
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
using namespace UniversalIO; using namespace UniversalIO;
...@@ -46,7 +46,7 @@ IONotifyController::IONotifyController(): ...@@ -46,7 +46,7 @@ IONotifyController::IONotifyController():
} }
IONotifyController::IONotifyController(const string& name, const string& section, std::shared_ptr<NCRestorer> d ): IONotifyController::IONotifyController(const string& name, const string& section, std::shared_ptr<IOConfig> d ):
IOController(name, section), IOController(name, section),
restorer(d), restorer(d),
askIOMutex(name + "askIOMutex"), askIOMutex(name + "askIOMutex"),
...@@ -58,7 +58,7 @@ IONotifyController::IONotifyController(const string& name, const string& section ...@@ -58,7 +58,7 @@ IONotifyController::IONotifyController(const string& name, const string& section
conInit = signal_init().connect(sigc::mem_fun(*this, &IONotifyController::initItem)); conInit = signal_init().connect(sigc::mem_fun(*this, &IONotifyController::initItem));
} }
IONotifyController::IONotifyController( ObjectId id, std::shared_ptr<NCRestorer> d ): IONotifyController::IONotifyController( ObjectId id, std::shared_ptr<IOConfig> d ):
IOController(id), IOController(id),
restorer(d), restorer(d),
askIOMutex(string(uniset_conf()->oind->getMapName(id)) + "_askIOMutex"), askIOMutex(string(uniset_conf()->oind->getMapName(id)) + "_askIOMutex"),
...@@ -142,22 +142,17 @@ void IONotifyController::showStatisticsForConsumer( ostringstream& inf, const st ...@@ -142,22 +142,17 @@ void IONotifyController::showStatisticsForConsumer( ostringstream& inf, const st
{ {
uniset_rwmutex_rlock lock2(a.second.mut); uniset_rwmutex_rlock lock2(a.second.mut);
for( auto && t : a.second.list ) for( const auto& c : a.second.clst )
{ {
uniset_rwmutex_rlock lock3(t.clst.mut); if( c.id == consumer_id )
for( const auto& c : t.clst.clst )
{ {
if( c.id == consumer_id ) if( a.first->sid != DefaultObjectId )
{ stat.emplace_back(a.first->sid, c);
if( t.sid != DefaultObjectId ) else
stat.emplace_back(t.sid, c); stat.emplace_back(DefaultObjectId, c);
else
stat.emplace_back(a.first, c);
smCount += c.smCount; smCount += c.smCount;
break; break;
}
} }
} }
} }
...@@ -210,7 +205,7 @@ void IONotifyController::showStatisticsForLostConsumers( ostringstream& inf ) ...@@ -210,7 +205,7 @@ void IONotifyController::showStatisticsForLostConsumers( ostringstream& inf )
return; return;
} }
inf << "Statisctic for consumer with lost event:" inf << "Statistics 'consumers with lost events':"
<< endl << endl
<< "----------------------------------------" << "----------------------------------------"
<< endl; << endl;
...@@ -348,7 +343,7 @@ void IONotifyController::showStatisticsForSensor( ostringstream& inf, const stri ...@@ -348,7 +343,7 @@ void IONotifyController::showStatisticsForSensor( ostringstream& inf, const stri
clist = &(s->second); clist = &(s->second);
} }
inf << "Statisctic for sensor " inf << "Statisctics for sensor "
<< "(" << setw(6) << sid << ")[" << name << "]: " << endl << "(" << setw(6) << sid << ")[" << name << "]: " << endl
<< "--------------------------------------------------------------------" << endl; << "--------------------------------------------------------------------" << endl;
...@@ -513,7 +508,7 @@ bool IONotifyController::removeConsumer( ConsumerListInfo& lst, const ConsumerIn ...@@ -513,7 +508,7 @@ bool IONotifyController::removeConsumer( ConsumerListInfo& lst, const ConsumerIn
void IONotifyController::askSensor(const uniset::ObjectId sid, void IONotifyController::askSensor(const uniset::ObjectId sid,
const uniset::ConsumerInfo& ci, UniversalIO::UIOCommand cmd ) const uniset::ConsumerInfo& ci, UniversalIO::UIOCommand cmd )
{ {
uinfo << "(askSensor): поступил " << ( cmd == UIODontNotify ? "отказ" : "заказ" ) << " от " ulog2 << "(askSensor): поступил " << ( cmd == UIODontNotify ? "отказ" : "заказ" ) << " от "
<< uniset_conf()->oind->getNameById(ci.id) << "@" << ci.node << uniset_conf()->oind->getNameById(ci.id) << "@" << ci.node
<< " на аналоговый датчик " << " на аналоговый датчик "
<< uniset_conf()->oind->getNameById(sid) << endl; << uniset_conf()->oind->getNameById(sid) << endl;
...@@ -560,45 +555,13 @@ void IONotifyController::ask( AskMap& askLst, const uniset::ObjectId sid, ...@@ -560,45 +555,13 @@ void IONotifyController::ask( AskMap& askLst, const uniset::ObjectId sid,
case UniversalIO::UIONotifyChange: case UniversalIO::UIONotifyChange:
case UniversalIO::UIONotifyFirstNotNull: case UniversalIO::UIONotifyFirstNotNull:
{ {
if( askIterator == askLst.end() ) if( askIterator != askLst.end() )
addConsumer(askIterator->second, cons);
else
{ {
ConsumerListInfo newlst; // создаем новый список ConsumerListInfo newlst; // создаем новый список
addConsumer(newlst, cons); addConsumer(newlst, cons);
askLst.emplace(sid, std::move(newlst)); askLst.emplace(sid, std::move(newlst));
// т.к. мы делали move
// то теперь надо достучаться до списка..
auto i = askLst.find(sid);
if( i != askLst.end() )
{
try
{
dumpOrdersList(sid, i->second);
}
catch( const uniset::Exception& ex )
{
uwarn << myname << " не смогли сделать dump: " << ex << endl;
}
}
}
else
{
if( addConsumer(askIterator->second, cons) )
{
try
{
dumpOrdersList(sid, askIterator->second);
}
catch( const std::exception& ex )
{
uwarn << myname << " не смогли сделать dump: " << ex.what() << endl;
}
catch(...)
{
uwarn << myname << " не смогли сделать dump (catch...)" << endl;
}
}
} }
break; break;
...@@ -606,35 +569,8 @@ void IONotifyController::ask( AskMap& askLst, const uniset::ObjectId sid, ...@@ -606,35 +569,8 @@ void IONotifyController::ask( AskMap& askLst, const uniset::ObjectId sid,
case UniversalIO::UIODontNotify: // отказ case UniversalIO::UIODontNotify: // отказ
{ {
if( askIterator != askLst.end() ) // существует if( askIterator != askLst.end() )
{ removeConsumer(askIterator->second, cons);
if( removeConsumer(askIterator->second, cons) )
{
uniset_rwmutex_wrlock l(askIterator->second.mut);
if( askIterator->second.clst.empty() )
{
// не удаляем, т.к. могут поломаться итераторы
// используемые в это время в других потоках..
// askLst.erase(askIterator);
}
else
{
try
{
dumpOrdersList(sid, askIterator->second);
}
catch( const std::exception& ex )
{
uwarn << myname << " не смогли сделать dump: " << ex.what() << endl;
}
catch(...)
{
uwarn << myname << " не смогли сделать dump (catch...)" << endl;
}
}
}
}
break; break;
} }
...@@ -811,24 +747,32 @@ void IONotifyController::send( ConsumerListInfo& lst, const uniset::SensorMessag ...@@ -811,24 +747,32 @@ void IONotifyController::send( ConsumerListInfo& lst, const uniset::SensorMessag
bool IONotifyController::activateObject() bool IONotifyController::activateObject()
{ {
// сперва загружаем датчики и заказчиков.. // сперва загружаем датчики и заказчиков..
readDump(); readConf();
// а потом уже собственно активация.. // а потом уже собственно активация..
return IOController::activateObject(); return IOController::activateObject();
} }
// -------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------
void IONotifyController::readDump() void IONotifyController::sensorsRegistration()
{
for_iolist([this](std::shared_ptr<USensorInfo>& s)
{
ioRegistration(s);
});
}
// --------------------------------------------------------------------------------------------------------------
void IONotifyController::readConf()
{ {
try try
{ {
if( restorer ) if( restorer )
restorer->read(this); initIOList( std::move(restorer->read()) );
} }
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
// Если дамп не удалось считать, значит что-то не то в configure.xml // Если дамп не удалось считать, значит что-то не то в configure.xml
// и безопаснее "вылететь", чем запустится, т.к. часть датчиков не будет работать // и безопаснее "вылететь", чем запустится, т.к. часть датчиков не будет работать
// как ожидается. // как ожидается.
ucrit << myname << "(IONotifyController::readDump): " << ex.what() << endl; ucrit << myname << "(IONotifyController::readConf): " << ex.what() << endl;
//std::terminate(); // std::abort(); //std::terminate(); // std::abort();
uterminate(); uterminate();
} }
...@@ -840,50 +784,20 @@ void IONotifyController::initItem( std::shared_ptr<USensorInfo>& usi, IOControll ...@@ -840,50 +784,20 @@ void IONotifyController::initItem( std::shared_ptr<USensorInfo>& usi, IOControll
checkThreshold( usi, false ); checkThreshold( usi, false );
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void IONotifyController::dumpOrdersList( const uniset::ObjectId sid, void IONotifyController::askThreshold(uniset::ObjectId sid,
const IONotifyController::ConsumerListInfo& lst ) const uniset::ConsumerInfo& ci,
{
if( !restorer || restorer->readOnly() )
return;
try
{
IOController_i::SensorIOInfo ainf( getSensorIOInfo(sid) );
// делаем через tmp, т.к. у нас определён operator=
NCRestorer::SInfo tmp = ainf;
auto sinf = make_shared<NCRestorer::SInfo>( std::move(tmp) );
restorer->dump(this, sinf, lst);
}
catch( const uniset::Exception& ex )
{
uwarn << myname << "(IONotifyController::dumpOrderList): " << ex << endl;
}
}
// --------------------------------------------------------------------------------------------------------------
void IONotifyController::dumpThresholdList( const uniset::ObjectId sid, const IONotifyController::ThresholdExtList& lst )
{
if( !restorer || restorer->readOnly() )
return;
try
{
IOController_i::SensorIOInfo ainf(getSensorIOInfo(sid));
auto sinf = make_shared<NCRestorer::SInfo>( std::move(ainf) );
restorer->dumpThreshold(this, sinf, lst);
}
catch( const uniset::Exception& ex )
{
uwarn << myname << "(IONotifyController::dumpThresholdList): " << ex << endl;
}
}
// --------------------------------------------------------------------------------------------------------------
void IONotifyController::askThreshold(uniset::ObjectId sid, const uniset::ConsumerInfo& ci,
uniset::ThresholdId tid, uniset::ThresholdId tid,
CORBA::Long lowLimit, CORBA::Long hiLimit, CORBA::Boolean invert, CORBA::Long lowLimit, CORBA::Long hiLimit, CORBA::Boolean invert,
UniversalIO::UIOCommand cmd ) UniversalIO::UIOCommand cmd )
{ {
ulog2 << "(askThreshold): " << ( cmd == UIODontNotify ? "отказ" : "заказ" ) << " от "
<< uniset_conf()->oind->getNameById(ci.id) << "@" << ci.node
<< " на порог tid=" << tid
<< " [" << lowLimit << "," << hiLimit << ",invert=" << invert << "]"
<< " для датчика "
<< uniset_conf()->oind->getNameById(sid)
<< endl;
if( lowLimit > hiLimit ) if( lowLimit > hiLimit )
throw IONotifyController_i::BadRange(); throw IONotifyController_i::BadRange();
...@@ -893,7 +807,7 @@ void IONotifyController::askThreshold(uniset::ObjectId sid, const uniset::Consum ...@@ -893,7 +807,7 @@ void IONotifyController::askThreshold(uniset::ObjectId sid, const uniset::Consum
try try
{ {
// если такого дискретного датчика нет сдесь сработает исключение... // если такого датчика нет здесь сработает исключение...
val = localGetValue(li, sid); val = localGetValue(li, sid);
} }
catch( const IOController_i::Undefined& ex ) {} catch( const IOController_i::Undefined& ex ) {}
...@@ -902,62 +816,22 @@ void IONotifyController::askThreshold(uniset::ObjectId sid, const uniset::Consum ...@@ -902,62 +816,22 @@ void IONotifyController::askThreshold(uniset::ObjectId sid, const uniset::Consum
// lock // lock
uniset_rwmutex_wrlock lock(trshMutex); uniset_rwmutex_wrlock lock(trshMutex);
// поиск датчика в списке auto it = findThreshold(sid, tid);
auto it = askTMap.find(sid);
ThresholdInfoExt ti(tid, lowLimit, hiLimit, invert);
ti.sit = myioEnd();
switch( cmd ) switch( cmd )
{ {
case UniversalIO::UIONotify: // заказ case UniversalIO::UIONotify: // заказ
case UniversalIO::UIONotifyChange: case UniversalIO::UIONotifyChange:
{ {
if( it == askTMap.end() ) if( !it )
{ it = make_shared<IOController::UThresholdInfo>(tid, lowLimit, hiLimit, invert);
ThresholdExtList lst; // создаем новый список
ThresholdsListInfo tli;
tli.si.id = sid;
tli.si.node = uniset_conf()->getLocalNode();
tli.list = std::move(lst);
tli.type = li->second->type;
tli.usi = li->second;
// после этого вызова ti использовать нельзя
addThreshold(tli.list, std::move(ti), ci);
try
{
dumpThresholdList(sid, tli.list);
}
catch( const uniset::Exception& ex )
{
uwarn << myname << " не смогли сделать dump: " << ex << endl;
}
// т.к. делаем move... то надо гарантировать, что дальше уже tli не используется.. it = addThresholdIfNotExist(li->second, it);
askTMap.emplace(sid, std::move(tli)); addThresholdConsumer(it, ci);
}
else
{
if( addThreshold(it->second.list, std::move(ti), ci) )
{
try
{
dumpThresholdList(sid, it->second.list);
}
catch( const uniset::Exception& ex )
{
uwarn << myname << "(askThreshold): dump: " << ex << endl;
}
}
}
if( cmd == UniversalIO::UIONotifyChange ) if( cmd == UniversalIO::UIONotifyChange )
break; break;
it = askTMap.find(sid);
// посылка первый раз состояния // посылка первый раз состояния
SensorMessage sm(std::move(li->second->makeSensorMessage())); SensorMessage sm(std::move(li->second->makeSensorMessage()));
sm.consumer = ci.id; sm.consumer = ci.id;
...@@ -970,96 +844,77 @@ void IONotifyController::askThreshold(uniset::ObjectId sid, const uniset::Consum ...@@ -970,96 +844,77 @@ void IONotifyController::askThreshold(uniset::ObjectId sid, const uniset::Consum
else if( val >= hiLimit ) else if( val >= hiLimit )
sm.threshold = true; sm.threshold = true;
if( it != askTMap.end() ) auto clst = askTMap.find(it.get());
{
uniset_rwmutex_rlock l(it->second.mut);
for( auto i = it->second.list.begin(); i != it->second.list.end(); ++i ) if( clst != askTMap.end() )
{ send(clst->second, sm, &ci);
if( i->id == tid )
{
send(i->clst, sm, &ci);
break;
}
}
}
} }
break; break;
case UniversalIO::UIODontNotify: // отказ case UniversalIO::UIODontNotify: // отказ
{ {
if( it != askTMap.end() ) if( it )
{ removeThresholdConsumer(li->second, it, ci);
if( removeThreshold(it->second.list, ti, ci) )
{
try
{
dumpThresholdList(sid, it->second.list);
}
catch( const uniset::Exception& ex )
{
uwarn << myname << "(askThreshold): dump: " << ex << endl;
}
}
}
} }
break; break;
default: default:
break; break;
} }
// askTMap уже залочен trshMutex
if( it == askTMap.end() )
it = askTMap.find(sid);
if( li != myioEnd() )
li->second->setUserData(udataThresholdList, &(it->second));
} // unlock trshMutex } // unlock trshMutex
} }
// -------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------
bool IONotifyController::addThreshold( ThresholdExtList& lst, ThresholdInfoExt&& ti, const uniset::ConsumerInfo& ci ) std::shared_ptr<IOController::UThresholdInfo>
IONotifyController::addThresholdIfNotExist( std::shared_ptr<USensorInfo>& usi,
std::shared_ptr<UThresholdInfo>& ti )
{ {
for( auto it = lst.begin(); it != lst.end(); ++it) uniset::uniset_rwmutex_wrlock lck(usi->tmut);
{
if( ti == (*it) )
{
if( addConsumer(it->clst, ci) )
return true;
return false; for( auto && t : usi->thresholds )
} {
if( ti->id == t->id )
return t;
} }
addConsumer(ti.clst, ci);
// запоминаем начальное время
struct timespec tm = uniset::now_to_timespec(); struct timespec tm = uniset::now_to_timespec();
ti.tv_sec = tm.tv_sec;
ti.tv_nsec = tm.tv_nsec;
lst.emplace_back( std::move(ti) ); ti->tv_sec = tm.tv_sec;
return true;
ti->tv_nsec = tm.tv_nsec;
usi->thresholds.push_back(ti);
return ti;
}
// --------------------------------------------------------------------------------------------------------------
bool IONotifyController::addThresholdConsumer( std::shared_ptr<IOController::UThresholdInfo>& ti, const ConsumerInfo& ci )
{
auto i = askTMap.find(ti.get());
if( i != askTMap.end() )
return addConsumer(i->second, ci);
auto ret = askTMap.emplace(ti.get(), ConsumerListInfo());
return addConsumer( ret.first->second, ci );
} }
// -------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------
bool IONotifyController::removeThreshold( ThresholdExtList& lst, ThresholdInfoExt& ti, const uniset::ConsumerInfo& ci ) bool IONotifyController::removeThresholdConsumer( std::shared_ptr<USensorInfo>& usi,
std::shared_ptr<UThresholdInfo>& ti,
const uniset::ConsumerInfo& ci )
{ {
for( auto it = lst.begin(); it != lst.end(); ++it) uniset_rwmutex_wrlock lck(usi->tmut);
for( auto && t : usi->thresholds )
{ {
if( ti == (*it) ) if( t->id == ti->id )
{ {
if( removeConsumer(it->clst, ci) ) auto it = askTMap.find(ti.get());
{
/* Даже если список заказчиков по данному датчику стал пуст. if( it == askTMap.end() )
* Не удаляем датчик из списка, чтобы не поломать итераторы return false;
* которые могут использоваться в этот момент в других потоках
*/ return removeConsumer(it->second, ci);
// uniset_rwmutex_wrlock lock(it->clst.mut);
// if( it->clst.clst.empty() )
// lst.erase(it);
return true;
}
} }
} }
...@@ -1083,9 +938,9 @@ void IONotifyController::checkThreshold( std::shared_ptr<IOController::USensorIn ...@@ -1083,9 +938,9 @@ void IONotifyController::checkThreshold( std::shared_ptr<IOController::USensorIn
{ {
uniset_rwmutex_rlock lock(trshMutex); uniset_rwmutex_rlock lock(trshMutex);
ThresholdsListInfo* ti = static_cast<ThresholdsListInfo*>(usi->getUserData(udataThresholdList)); auto& ti = usi->thresholds;
if( !ti || ti->list.empty() ) if( ti.empty() )
return; return;
// обрабатываем текущее состояние датчика обязательно "залочив" значение.. // обрабатываем текущее состояние датчика обязательно "залочив" значение..
...@@ -1097,9 +952,9 @@ void IONotifyController::checkThreshold( std::shared_ptr<IOController::USensorIn ...@@ -1097,9 +952,9 @@ void IONotifyController::checkThreshold( std::shared_ptr<IOController::USensorIn
struct timespec tm = uniset::now_to_timespec(); struct timespec tm = uniset::now_to_timespec();
{ {
uniset_rwmutex_rlock l(ti->mut); uniset_rwmutex_rlock l(usi->tmut);
for( auto it = ti->list.begin(); it != ti->list.end(); ++it ) for( auto && it : ti )
{ {
// Используем здесь значение скопированное в sm.value // Используем здесь значение скопированное в sm.value
// чтобы не делать ещё раз lock на li->second->value // чтобы не делать ещё раз lock на li->second->value
...@@ -1154,22 +1009,30 @@ void IONotifyController::checkThreshold( std::shared_ptr<IOController::USensorIn ...@@ -1154,22 +1009,30 @@ void IONotifyController::checkThreshold( std::shared_ptr<IOController::USensorIn
// отдельно посылаем сообщения заказчикам по данному "порогу" // отдельно посылаем сообщения заказчикам по данному "порогу"
if( send_msg ) if( send_msg )
send(it->clst, sm); {
uniset_rwmutex_rlock lck(trshMutex);
auto i = askTMap.find(it.get());
if( i != askTMap.end() )
send(i->second, sm);
}
} }
} }
} }
// -------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------
IONotifyController::ThresholdInfoExt* IONotifyController::findThreshold( AskThresholdMap& tmap, const uniset::ObjectId sid, const uniset::ThresholdId tid ) std::shared_ptr<IOController::UThresholdInfo> IONotifyController::findThreshold( const uniset::ObjectId sid, const uniset::ThresholdId tid )
{ {
// поиск списка порогов auto it = myiofind(sid);
auto lst = tmap.find(sid);
if( lst != tmap.end() ) if( it != myioEnd() )
{ {
for( auto it = lst->second.list.begin(); it != lst->second.list.end(); ++it) auto usi = it->second;
uniset_rwmutex_rlock lck(usi->tmut);
for( auto && t : usi->thresholds )
{ {
if( it->id == tid ) if( t->id == tid )
return &(*it); return t;
} }
} }
...@@ -1180,10 +1043,9 @@ IONotifyController::ThresholdInfoExt* IONotifyController::findThreshold( AskThre ...@@ -1180,10 +1043,9 @@ IONotifyController::ThresholdInfoExt* IONotifyController::findThreshold( AskThre
IONotifyController_i::ThresholdInfo IONotifyController::getThresholdInfo( uniset::ObjectId sid, uniset::ThresholdId tid ) IONotifyController_i::ThresholdInfo IONotifyController::getThresholdInfo( uniset::ObjectId sid, uniset::ThresholdId tid )
{ {
uniset_rwmutex_rlock lock(trshMutex); uniset_rwmutex_rlock lock(trshMutex);
auto it = findThreshold(sid, tid);
auto it = askTMap.find(sid); if( !it )
if( it == askTMap.end() )
{ {
ostringstream err; ostringstream err;
err << myname << "(getThresholds): Not found sensor (" << sid << ") " err << myname << "(getThresholds): Not found sensor (" << sid << ") "
...@@ -1193,30 +1055,14 @@ IONotifyController_i::ThresholdInfo IONotifyController::getThresholdInfo( uniset ...@@ -1193,30 +1055,14 @@ IONotifyController_i::ThresholdInfo IONotifyController::getThresholdInfo( uniset
throw IOController_i::NameNotFound(err.str().c_str()); throw IOController_i::NameNotFound(err.str().c_str());
} }
for( const auto& it2 : it->second.list ) return IONotifyController_i::ThresholdInfo(*it);
{
/*! \warning На самом деле список разрешает иметь много порогов с одинаковым ID, для разных "заказчиков".
Но здесь мы возвращаем первый встретившийся..
*/
if( it2.id == tid )
return IONotifyController_i::ThresholdInfo( it2 );
}
ostringstream err;
err << myname << "(getThresholds): Not found for sensor (" << sid << ") "
<< uniset_conf()->oind->getNameById(sid) << " ThresholdID='" << tid << "'";
uinfo << err.str() << endl;
throw IOController_i::NameNotFound(err.str().c_str());
} }
// -------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------
IONotifyController_i::ThresholdList* IONotifyController::getThresholds( uniset::ObjectId sid ) IONotifyController_i::ThresholdList* IONotifyController::getThresholds( uniset::ObjectId sid )
{ {
uniset_rwmutex_rlock lock(trshMutex); auto it = myiofind(sid);
auto it = askTMap.find(sid);
if( it == askTMap.end() ) if( it == myioEnd() )
{ {
ostringstream err; ostringstream err;
err << myname << "(getThresholds): Not found sensor (" << sid << ") " err << myname << "(getThresholds): Not found sensor (" << sid << ") "
...@@ -1226,41 +1072,35 @@ IONotifyController_i::ThresholdList* IONotifyController::getThresholds( uniset:: ...@@ -1226,41 +1072,35 @@ IONotifyController_i::ThresholdList* IONotifyController::getThresholds( uniset::
throw IOController_i::NameNotFound(err.str().c_str()); throw IOController_i::NameNotFound(err.str().c_str());
} }
auto& usi = it->second;
IONotifyController_i::ThresholdList* res = new IONotifyController_i::ThresholdList(); IONotifyController_i::ThresholdList* res = new IONotifyController_i::ThresholdList();
try try
{ {
res->si = it->second.si; res->si = usi->si;
res->value = IOController::localGetValue(it->second.usi); res->value = IOController::localGetValue(usi);
res->type = it->second.type; res->type = usi->type;
} }
catch( const uniset::Exception& ex ) catch( const uniset::Exception& ex )
{ {
uwarn << myname << "(getThresholds): для датчика " uwarn << myname << "(getThresholds): для датчика "
<< uniset_conf()->oind->getNameById(it->second.si.id) << uniset_conf()->oind->getNameById(usi->si.id)
<< " " << ex << endl; << " " << ex << endl;
} }
/* uniset_rwmutex_rlock lck(usi->tmut);
catch( const IOController_i::NameNotFound& ex ) res->tlist.length( usi->thresholds.size() );
{
uwarn << myname << "(getThresholds): IOController_i::NameNotFound.. for sid"
<< uniset_conf()->oind->getNameById(it->second.si.id)
<< endl;
}
*/
res->tlist.length( it->second.list.size() );
size_t k = 0; size_t k = 0;
for( const auto& it2 : it->second.list ) for( const auto& it2 : usi->thresholds )
{ {
res->tlist[k].id = it2.id; res->tlist[k].id = it2->id;
res->tlist[k].hilimit = it2.hilimit; res->tlist[k].hilimit = it2->hilimit;
res->tlist[k].lowlimit = it2.lowlimit; res->tlist[k].lowlimit = it2->lowlimit;
res->tlist[k].state = it2.state; res->tlist[k].state = it2->state;
res->tlist[k].tv_sec = it2.tv_sec; res->tlist[k].tv_sec = it2->tv_sec;
res->tlist[k].tv_nsec = it2.tv_nsec; res->tlist[k].tv_nsec = it2->tv_nsec;
k++; k++;
} }
...@@ -1269,52 +1109,61 @@ IONotifyController_i::ThresholdList* IONotifyController::getThresholds( uniset:: ...@@ -1269,52 +1109,61 @@ IONotifyController_i::ThresholdList* IONotifyController::getThresholds( uniset::
// -------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------
IONotifyController_i::ThresholdsListSeq* IONotifyController::getThresholdsList() IONotifyController_i::ThresholdsListSeq* IONotifyController::getThresholdsList()
{ {
IONotifyController_i::ThresholdsListSeq* res = new IONotifyController_i::ThresholdsListSeq(); std::list< std::shared_ptr<USensorInfo> > slist;
res->length( askTMap.size() ); // ищем все датчики, у которых не пустой список порогов
for_iolist([&slist]( std::shared_ptr<USensorInfo>& usi )
{
uniset_rwmutex_rlock lock(trshMutex); if( !usi->thresholds.empty() )
slist.push_back(usi);
});
if( !askTMap.empty() ) IONotifyController_i::ThresholdsListSeq* res = new IONotifyController_i::ThresholdsListSeq();
res->length( slist.size() );
if( !slist.empty() )
{ {
size_t i = 0; size_t i = 0;
for( auto && it : askTMap ) for( auto && it : slist )
{ {
try try
{ {
(*res)[i].si = it.second.si; (*res)[i].si = it->si;
(*res)[i].value = IOController::localGetValue(it.second.usi); (*res)[i].value = IOController::localGetValue(it);
(*res)[i].type = it.second.type; (*res)[i].type = it->type;
} }
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
uwarn << myname << "(getThresholdsList): for sid=" uwarn << myname << "(getThresholdsList): for sid="
<< uniset_conf()->oind->getNameById(it.second.si.id) << uniset_conf()->oind->getNameById(it->si.id)
<< " " << ex.what() << endl; << " " << ex.what() << endl;
continue; continue;
} }
catch( const IOController_i::NameNotFound& ex ) catch( const IOController_i::NameNotFound& ex )
{ {
uwarn << myname << "(getThresholdsList): IOController_i::NameNotFound.. for sid=" uwarn << myname << "(getThresholdsList): IOController_i::NameNotFound.. for sid="
<< uniset_conf()->oind->getNameById(it.second.si.id) << uniset_conf()->oind->getNameById(it->si.id)
<< endl; << endl;
continue; continue;
} }
(*res)[i].tlist.length( it.second.list.size() ); uniset_rwmutex_rlock lck(it->tmut);
(*res)[i].tlist.length( it->thresholds.size() );
size_t k = 0; size_t k = 0;
for( const auto& it2 : it.second.list ) for( const auto& it2 : it->thresholds )
{ {
(*res)[i].tlist[k].id = it2.id; (*res)[i].tlist[k].id = it2->id;
(*res)[i].tlist[k].hilimit = it2.hilimit; (*res)[i].tlist[k].hilimit = it2->hilimit;
(*res)[i].tlist[k].lowlimit = it2.lowlimit; (*res)[i].tlist[k].lowlimit = it2->lowlimit;
(*res)[i].tlist[k].state = it2.state; (*res)[i].tlist[k].state = it2->state;
(*res)[i].tlist[k].tv_sec = it2.tv_sec; (*res)[i].tlist[k].tv_sec = it2->tv_sec;
(*res)[i].tlist[k].tv_nsec = it2.tv_nsec; (*res)[i].tlist[k].tv_nsec = it2->tv_nsec;
k++; k++;
} }
......
...@@ -6,7 +6,9 @@ noinst_LTLIBRARIES = libProcesses.la ...@@ -6,7 +6,9 @@ noinst_LTLIBRARIES = libProcesses.la
libProcesses_la_CXXFLAGS = -I$(top_builddir)/include $(SIGC_CFLAGS) $(EV_CFLAGS) libProcesses_la_CXXFLAGS = -I$(top_builddir)/include $(SIGC_CFLAGS) $(EV_CFLAGS)
libProcesses_la_LIBADD = $(SIGC_LIBS) $(EV_LIBS) libProcesses_la_LIBADD = $(SIGC_LIBS) $(EV_LIBS)
libProcesses_la_SOURCES = IOController_iSK.cc IOController.cc IONotifyController.cc \ libProcesses_la_SOURCES = IOController_iSK.cc IOController.cc IONotifyController.cc \
NCRestorer.cc NCRestorer_XML.cc EventLoopServer.cc CommonEventLoop.cc ProxyManager.cc PassiveObject.cc IOConfig_XML.cc EventLoopServer.cc CommonEventLoop.cc ProxyManager.cc PassiveObject.cc
# NCRestorer.cc NCRestorer_XML.cc
local-clean: local-clean:
rm -rf *iSK.cc rm -rf *iSK.cc
......
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#include "Debug.h"
#include "Configuration.h"
#include "NCRestorer.h"
#include "Exceptions.h"
// ------------------------------------------------------------------------------------------
using namespace std;
using namespace UniversalIO;
using namespace uniset;
// ------------------------------------------------------------------------------------------
NCRestorer::NCRestorer()
{
}
NCRestorer::~NCRestorer()
{
}
// ------------------------------------------------------------------------------------------
void NCRestorer::addlist( IONotifyController* ic, std::shared_ptr<IOController::USensorInfo>& inf, IONotifyController::ConsumerListInfo&& lst, bool force )
{
// Проверка зарегистрирован-ли данный датчик
// если такого дискретного датчика нет, то здесь сработает исключение...
if( !force )
{
try
{
ic->getIOType(inf->si.id);
}
catch(...)
{
// Регистрируем (если не найден)
switch(inf->type)
{
case UniversalIO::DI:
case UniversalIO::DO:
case UniversalIO::AI:
case UniversalIO::AO:
ic->ioRegistration(inf);
break;
default:
ucrit << ic->getName() << "(askDumper::addlist): НЕИЗВЕСТНЫЙ ТИП ДАТЧИКА! -> "
<< uniset_conf()->oind->getNameById(inf->si.id) << endl;
return;
}
}
}
switch(inf->type)
{
case UniversalIO::DI:
case UniversalIO::AI:
case UniversalIO::DO:
case UniversalIO::AO:
{
ic->askIOList[inf->si.id] = std::move(lst);
inf->setUserData(IONotifyController::udataConsumerList, &(ic->askIOList[inf->si.id]) );
break;
}
default:
ucrit << ic->getName() << "(NCRestorer::addlist): НЕИЗВЕСТНЫЙ ТИП ДАТЧИКА!-> "
<< uniset_conf()->oind->getNameById(inf->si.id) << endl;
break;
}
}
// ------------------------------------------------------------------------------------------
void NCRestorer::addthresholdlist( IONotifyController* ic, std::shared_ptr<IOController::USensorInfo>& inf, IONotifyController::ThresholdExtList&& lst, bool force )
{
// Проверка зарегистрирован-ли данный датчик
// если такого дискретного датчика нет сдесь сработает исключение...
if( !force )
{
try
{
ic->getIOType(inf->si.id);
}
catch(...)
{
// Регистрируем (если не найден)
switch(inf->type)
{
case UniversalIO::DI:
case UniversalIO::DO:
case UniversalIO::AI:
case UniversalIO::AO:
ic->ioRegistration(inf);
break;
default:
break;
}
}
}
// default init iterators
for( auto& it : lst )
it.sit = ic->myioEnd();
try
{
auto i = ic->myiofind(inf->si.id);
ic->askTMap[inf->si.id].usi = i->second;
//! \warning Оптимизация использует userdata! Это опасно, если кто-то ещё захочет его использовать!
if( i->second )
i->second->userdata[IONotifyController::udataThresholdList] = &(ic->askTMap[inf->si.id]);
}
catch(...) {}
ic->askTMap[inf->si.id].si = inf->si;
ic->askTMap[inf->si.id].type = inf->type;
ic->askTMap[inf->si.id].list = std::move(lst);
}
// ------------------------------------------------------------------------------------------
NCRestorer::SInfo::SInfo( const IOController_i::SensorIOInfo& inf )
{
(*this) = inf;
}
// ------------------------------------------------------------------------------------------
NCRestorer::SInfo& NCRestorer::SInfo::operator=( const IOController_i::SensorIOInfo& inf )
{
this->si = inf.si;
this->type = inf.type;
this->priority = inf.priority;
this->default_val = inf.default_val;
this->real_value = inf.real_value;
this->ci = inf.ci;
this->undefined = inf.undefined;
this->blocked = inf.blocked;
this->dbignore = inf.dbignore;
{
uniset_rwmutex_wrlock l(this->userdata_lock);
for( size_t i = 0; i < IOController::USensorInfo::MaxUserData; i++ )
this->userdata[i] = nullptr;
}
return *this;
}
// ------------------------------------------------------------------------------------------
void NCRestorer::init_depends_signals( IONotifyController* ic )
{
for( auto it = ic->ioList.begin(); it != ic->ioList.end(); ++it )
{
// обновляем итераторы...
it->second->d_usi = it->second;
if( it->second->d_si.id == DefaultObjectId )
continue;
uinfo << ic->getName() << "(NCRestorer::init_depends_signals): "
<< " init depend: '" << uniset_conf()->oind->getMapName(it->second->si.id) << "'"
<< " dep_name=(" << it->second->d_si.id << ")'" << uniset_conf()->oind->getMapName(it->second->d_si.id) << "'"
<< endl;
uniset_rwmutex_rlock lock(it->second->val_lock);
ic->signal_change_value(it->second->d_si.id).connect( sigc::mem_fun( it->second.get(), &IOController::USensorInfo::checkDepend) );
}
}
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#include <sstream>
#include "Debug.h"
#include "Configuration.h"
#include "NCRestorer.h"
#include "Exceptions.h"
#include "ORepHelpers.h"
// ------------------------------------------------------------------------------------------
using namespace std;
using namespace UniversalIO;
using namespace uniset;
// ------------------------------------------------------------------------------------------
NCRestorer_XML::NCRestorer_XML( const string& fname ):
s_filterField(""),
s_filterValue(""),
t_filterField(""),
t_filterValue(""),
fname(fname),
uxml(nullptr)
{
init(fname);
}
NCRestorer_XML::NCRestorer_XML(const string& fname,
const std::string& f_field,
const std::string& f_value):
s_filterField(f_field),
s_filterValue(f_value),
t_filterField(""),
t_filterValue(""),
fname(fname),
uxml(nullptr)
{
init(fname);
setItemFilter(f_field, f_value);
}
NCRestorer_XML::NCRestorer_XML():
fname(""),
uxml(nullptr)
{
}
// ------------------------------------------------------------------------------------------
NCRestorer_XML::~NCRestorer_XML()
{
if( uxml )
{
uxml->close();
uxml.reset();
}
}
// ------------------------------------------------------------------------------------------
void NCRestorer_XML::init( const std::string& xmlfile )
{
/*!
\warning Файл открывается только при создании...
Т.е. не будут учтены изменения в промежутке между записью(dump-а) файла
*/
try
{
if( xmlfile == uniset_conf()->getConfFileName() )
uxml = uniset_conf()->getConfXML();
else
{
if( uxml )
{
uxml->close();
uxml.reset();
}
uxml = make_shared<UniXML>(xmlfile);
}
fname = xmlfile;
}
catch( uniset::NameNotFound& ex )
{
uwarn << "(NCRestorer_XML): файл " << xmlfile << " не найден, создаём новый...\n";
}
}
// ------------------------------------------------------------------------------------------
void NCRestorer_XML::dump(const IONotifyController* ic, std::shared_ptr<SInfo>& inf,
const IONotifyController::ConsumerListInfo& lst)
{
uwarn << "NCRestorer_XML::dump NOT SUPPORT!!!!" << endl;
}
// ------------------------------------------------------------------------------------------
void NCRestorer_XML::dumpThreshold(const IONotifyController* ic, std::shared_ptr<SInfo>& inf,
const IONotifyController::ThresholdExtList& lst)
{
uwarn << "NCRestorer_XML::dumpThreshold NOT SUPPORT!!!!" << endl;
}
// ------------------------------------------------------------------------------------------
void NCRestorer_XML::read_list( const std::shared_ptr<UniXML>& xml, xmlNode* node, IONotifyController* ic )
{
UniXML::iterator it(node);
if( !it.goChildren() )
return;
for( ; it.getCurrent(); it.goNext() )
{
if( !check_list_item(it) )
continue;
auto inf = make_shared<NCRestorer_XML::SInfo>();
if( !getSensorInfo(xml, it, inf) )
{
uwarn << ic->getName() << "(read_list): не смог получить информацию по датчику " << endl;
continue;
}
inf->undefined = false;
// т.к. в функции может обновится inf
// вызываем перед регистрацией
// (потому-что в xxRegistration inf будет скопирована
auto uinf = std::static_pointer_cast<IOController::USensorInfo>(inf);
ncrslot(xml, it, node, uinf);
switch(inf->type)
{
case UniversalIO::DO:
case UniversalIO::DI:
case UniversalIO::AO:
case UniversalIO::AI:
{
try
{
ioRegistration(ic, uinf, true);
}
catch( const uniset::Exception& ex )
{
uwarn << "(read_list): " << ex << endl;
}
}
break;
default:
break;
}
rslot(xml, it, node);
read_consumers(xml, it, inf, ic);
}
}
// ------------------------------------------------------------------------------------------
void NCRestorer_XML::read( IONotifyController* ic, const string& fn )
{
const std::shared_ptr<UniXML> confxml = uniset_conf()->getConfXML();
if( !fn.empty() )
{
// оптимизация (не загружаем второй раз xml-файл)
if( fn == uniset_conf()->getConfFileName() && confxml )
read( ic, confxml );
else
{
shared_ptr<UniXML> xml = make_shared<UniXML>(fn);
read( ic, xml );
xml->close();
}
}
else if( !fname.empty() )
{
// оптимизация (не загружаем второй раз xml-файл)
if( confxml && fname == confxml->getFileName() )
read(ic, confxml);
else if( uxml && uxml->isOpen() && uxml->getFileName() == fname )
read(ic, uxml);
else
{
uxml->close();
uxml->open(fname);
read(ic, uxml);
}
}
}
// ------------------------------------------------------------------------------------------
void NCRestorer_XML::read( IONotifyController* ic, const std::shared_ptr<UniXML>& xml )
{
xmlNode* node;
if( xml == uniset_conf()->getConfXML() )
node = uniset_conf()->getXMLSensorsSection();
else
node = xml->findNode( xml->getFirstNode(), "sensors");
if( node )
{
read_list(xml, node, ic);
// только после чтения всех датчиков и формирования списка IOList
// можно инициализировать списки зависимостей
init_depends_signals(ic);
}
xmlNode* tnode = xml->findNode(xml->getFirstNode(), "thresholds");
if( tnode )
read_thresholds(xml, tnode, ic);
}
// ------------------------------------------------------------------------------------------
bool NCRestorer_XML::getBaseInfo( const std::shared_ptr<UniXML>& xml, xmlNode* it, IOController_i::SensorInfo& si ) const
{
string sname( xml->getProp(it, "name"));
if( sname.empty() )
{
uwarn << "(getBaseInfo): не указано имя датчика... пропускаем..." << endl;
return false;
}
// преобразуем в полное имя
ObjectId sid = uniset::DefaultObjectId;
string id(xml->getProp(it, "id"));
if( !id.empty() )
sid = uni_atoi( id );
else
sid = uniset_conf()->getSensorID(sname);
if( sid == uniset::DefaultObjectId )
{
ostringstream err;
err << "(getBaseInfo): НЕ НАЙДЕН ИДЕНТИФИКАТОР датчика --> " << sname;
ucrit << err.str() << endl;
throw SystemError(err.str());
}
ObjectId snode = uniset_conf()->getLocalNode();
string snodename(xml->getProp(it, "node"));
if( !snodename.empty() )
snode = uniset_conf()->getNodeID(snodename);
if( snode == uniset::DefaultObjectId )
{
ucrit << "(getBaseInfo): НЕ НАЙДЕН ИДЕНТИФИКАТОР узла --> " << snodename << endl;
return false;
}
si.id = sid;
si.node = snode;
return true;
}
// ------------------------------------------------------------------------------------------
bool NCRestorer_XML::getSensorInfo( const std::shared_ptr<UniXML>& xml, xmlNode* it, std::shared_ptr<NCRestorer_XML::SInfo>& inf ) const
{
if( !getBaseInfo(xml, it, inf->si) )
return false;
inf->priority = Message::Medium;
string prior(xml->getProp(it, "priority"));
if( prior == "Low" )
inf->priority = Message::Low;
else if( prior == "Medium" )
inf->priority = Message::Medium;
else if( prior == "High" )
inf->priority = Message::High;
else
inf->priority = Message::Medium;
inf->type = uniset::getIOType(xml->getProp(it, "iotype"));
if( inf->type == UniversalIO::UnknownIOType )
{
ostringstream err;
err << "(NCRestorer_XML:getSensorInfo): unknown iotype=" << xml->getProp(it, "iotype")
<< " for " << xml->getProp(it, "name");
ucrit << err.str() << endl;
throw SystemError(err.str());
}
// калибровка
if( inf->type == UniversalIO::AI || inf->type == UniversalIO::AO )
{
inf->ci.minRaw = xml->getIntProp(it, "rmin");
inf->ci.maxRaw = xml->getIntProp(it, "rmax");
inf->ci.minCal = xml->getIntProp(it, "cmin");
inf->ci.maxCal = xml->getIntProp(it, "cmax");
inf->ci.precision = xml->getIntProp(it, "precision");
}
else
{
inf->ci.minRaw = 0;
inf->ci.maxRaw = 0;
inf->ci.minCal = 0;
inf->ci.maxCal = 0;
inf->ci.precision = 0;
}
inf->default_val = xml->getIntProp(it, "default");
inf->dbignore = xml->getIntProp(it, "dbignore");
inf->value = inf->default_val;
inf->undefined = false;
inf->real_value = inf->value;
string d_txt( xml->getProp(it, "depend") );
if( !d_txt.empty() )
{
inf->d_si.id = uniset_conf()->getSensorID(d_txt);
if( inf->d_si.id == uniset::DefaultObjectId )
{
ostringstream err;
err << "(NCRestorer_XML:getSensorInfo): sensor='"
<< xml->getProp(it, "name") << "' err: "
<< " Unknown SensorID for depend='" << d_txt;
ucrit << err.str() << endl;
throw SystemError(err.str());
}
inf->d_si.node = uniset_conf()->getLocalNode();
// по умолчанию срабатывание на "1"
inf->d_value = xml->getProp(it, "depend_value").empty() ? 1 : xml->getIntProp(it, "depend_value");
inf->d_off_value = xml->getPIntProp(it, "depend_off_value", 0);
}
return true;
}
// ------------------------------------------------------------------------------------------
void NCRestorer_XML::read_thresholds( const std::shared_ptr<UniXML>& xml, xmlNode* node, IONotifyController* ic )
{
UniXML::iterator it(node);
if( !it.goChildren() )
return;
for( ; it.getCurrent(); it.goNext() )
{
if( !check_thresholds_item(it) )
continue;
IOController_i::SensorInfo si;
if( !getBaseInfo(xml, it.getCurrent(), si) )
{
ostringstream err;
err << ic->getName()
<< "(read_thresholds): не смог получить информацию о пороге"
<< " для датчика " << it.getProp("name");
ucrit << err.str() << endl;
throw uniset::SystemError(err.str());
}
auto inf = ic->find(si.id);
if( inf == ic->ioEnd() )
{
ostringstream err;
err << ic->getName()
<< "(read_thresholds): датчик " << it.getProp("name")
<< " НЕ НАЙДЕН В СПИСКЕ датчиков";
ucrit << err.str() << endl;
throw uniset::SystemError(err.str());
}
ulog3 << ic->getName() << "(read_thresholds): " << it.getProp("name") << endl;
UniXML::iterator tit(it);
if( !tit.goChildren() )
continue;
IONotifyController::ThresholdExtList tlst;
for( ; tit.getCurrent(); tit++ )
{
IONotifyController::ThresholdInfoExt ti(0, 0, 0, false);
if( !getThresholdInfo(xml, tit, ti) )
{
ostringstream err;
err << ic->getName()
<< "(read_thresholds): не смог получить информацию о пороге"
<< " для датчика "
<< uniset_conf()->oind->getNameById(si.id);
ucrit << err.str() << endl;
throw uniset::SystemError(err.str());
}
ulog3 << "(read_thresholds): \tthreshold low="
<< ti.lowlimit << " \thi=" << ti.hilimit
<< " \t sid=" << ti.sid
<< " \t invert=" << ti.invert
<< endl << flush;
xmlNode* cnode = find_node(xml, tit, "consumers", "");
if( cnode )
{
UniXML::iterator ask_it(cnode);
if( ask_it.goChildren() )
{
if( !getConsumerList(xml, ask_it, ti.clst) )
{
uwarn << ic->getName()
<< "(read_thresholds): не смог получить список заказчиков"
<< " для порога " << ti.id
<< " датчика " << uniset_conf()->oind->getNameById(si.id) << endl;
}
}
}
// порог добавляем в любом случае, даже если список заказчиков пуст...
tlst.emplace_back( std::move(ti) );
rtslot(xml, tit, it);
}
std::shared_ptr<IOController::USensorInfo> uinf = std::static_pointer_cast<IOController::USensorInfo>(inf->second);
addthresholdlist(ic, uinf, std::move(tlst) );
}
}
// ------------------------------------------------------------------------------------------
void NCRestorer_XML::read_consumers( const std::shared_ptr<UniXML>& xml, xmlNode* it,
std::shared_ptr<NCRestorer_XML::SInfo>& inf, IONotifyController* ic )
{
// в новых ask-файлах список выделен <consumers>...</consumers>,
xmlNode* cnode = find_node(xml, it, "consumers", "");
if( cnode )
{
UniXML::iterator cit(cnode);
if( cit.goChildren() )
{
IONotifyController::ConsumerListInfo lst;
if( getConsumerList(xml, cit, lst) )
{
std::shared_ptr<IOController::USensorInfo> uinf = std::static_pointer_cast<IOController::USensorInfo>(inf);
addlist(ic, uinf, std::move(lst), true);
}
}
}
}
// ------------------------------------------------------------------------------------------
bool NCRestorer_XML::getConsumerList( const std::shared_ptr<UniXML>& xml, xmlNode* node,
IONotifyController::ConsumerListInfo& lst ) const
{
UniXML::iterator it(node);
for(; it.getCurrent(); it++ )
{
if( !check_consumer_item(it) )
continue;
ConsumerInfo ci;
if( !getConsumerInfo(it, ci.id, ci.node) )
continue;
lst.clst.emplace_back( std::move(ci) );
cslot(xml, it, node);
}
return true;
}
// ------------------------------------------------------------------------------------------
bool NCRestorer_XML::getThresholdInfo( const std::shared_ptr<UniXML>& xml, xmlNode* node,
IONotifyController::ThresholdInfoExt& ti ) const
{
UniXML::iterator uit(node);
string sid_name = uit.getProp("sid");
if( !sid_name.empty() )
{
ti.sid = uniset_conf()->getSensorID(sid_name);
if( ti.sid == uniset::DefaultObjectId )
{
ostringstream err;
err << "(NCRestorer_XML:getThresholdInfo): "
<< " Not found ID for " << sid_name;
ucrit << err.str() << endl;
throw SystemError(err.str());
}
else
{
UniversalIO::IOType iotype = uniset_conf()->getIOType(ti.sid);
// Пока что IONotifyController поддерживает работу только с 'DI/DO'.
if( iotype != UniversalIO::DI && iotype != UniversalIO::DO )
{
ostringstream err;
err << "(NCRestorer_XML:getThresholdInfo): "
<< " Bad iotype(" << iotype << ") for " << sid_name
<< ". iotype must be 'DI' or 'DO'.";
ucrit << err.str() << endl;
throw SystemError(err.str());
}
}
}
ti.id = uit.getIntProp("id");
ti.lowlimit = uit.getIntProp("lowlimit");
ti.hilimit = uit.getIntProp("hilimit");
ti.invert = uit.getIntProp("invert");
ti.state = IONotifyController_i::NormalThreshold;
return true;
}
// ------------------------------------------------------------------------------------------
bool NCRestorer_XML::check_thresholds_item( UniXML::iterator& it ) const
{
return uniset::check_filter(it, t_filterField, t_filterValue);
}
// ------------------------------------------------------------------------------------------
void NCRestorer_XML::setReadThresholdItem( ReaderSlot sl )
{
rtslot = sl;
}
// ------------------------------------------------------------------------------------------
void NCRestorer_XML::setNCReadItem( NCReaderSlot sl )
{
ncrslot = sl;
}
// -----------------------------------------------------------------------------
void NCRestorer_XML::setThresholdsFilter( const std::string& field, const std::string& val )
{
t_filterField = field;
t_filterValue = val;
}
// -----------------------------------------------------------------------------
...@@ -6,7 +6,7 @@ noinst_LTLIBRARIES = libVarious.la ...@@ -6,7 +6,7 @@ noinst_LTLIBRARIES = libVarious.la
libVarious_la_CPPFLAGS = $(SIGC_CFLAGS) $(POCO_CFLAGS) libVarious_la_CPPFLAGS = $(SIGC_CFLAGS) $(POCO_CFLAGS)
libVarious_la_LIBADD = $(SIGC_LIBS) $(POCO_LIBS) libVarious_la_LIBADD = $(SIGC_LIBS) $(POCO_LIBS)
libVarious_la_SOURCES = UniXML.cc MQMutex.cc MQAtomic.cc \ libVarious_la_SOURCES = UniXML.cc MQMutex.cc MQAtomic.cc \
Restorer_XML.cc RunLock.cc Mutex.cc SViewer.cc SMonitor.cc WDTInterface.cc VMonitor.cc \ Mutex.cc SViewer.cc SMonitor.cc WDTInterface.cc VMonitor.cc \
ujson.cc ujson.cc
local-clean: local-clean:
......
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#include <sstream>
#include "Debug.h"
#include "Configuration.h"
#include "Restorer.h"
#include "Exceptions.h"
#include "ORepHelpers.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniversalIO;
using namespace uniset;
// -----------------------------------------------------------------------------
Restorer_XML::Restorer_XML():
i_filterField(""),
i_filterValue(""),
c_filterField(""),
c_filterValue("")
{
}
// -----------------------------------------------------------------------------
Restorer_XML::~Restorer_XML()
{
}
// -----------------------------------------------------------------------------
void Restorer_XML::setItemFilter( const string& field, const string& val )
{
i_filterField = field;
i_filterValue = val;
}
// -----------------------------------------------------------------------------
void Restorer_XML::setConsumerFilter( const string& field, const string& val )
{
c_filterField = field;
c_filterValue = val;
}
// -----------------------------------------------------------------------------
bool Restorer_XML::getConsumerInfo( UniXML::iterator& it,
ObjectId& cid, ObjectId& cnode ) const
{
if( !check_consumer_item(it) )
return false;
string cname( it.getProp("name"));
if( cname.empty() )
{
uwarn << "(Restorer_XML:getConsumerInfo): не указано имя заказчика..." << endl;
return false;
}
string otype(it.getProp("type"));
if( otype == "controllers" )
cname = uniset_conf()->getControllersSection() + "/" + cname;
else if( otype == "objects" )
cname = uniset_conf()->getObjectsSection() + "/" + cname;
else if( otype == "services" )
cname = uniset_conf()->getServicesSection() + "/" + cname;
else
{
uwarn << "(Restorer_XML:getConsumerInfo): неизвестный тип объекта "
<< otype << endl;
return false;
}
cid = uniset_conf()->oind->getIdByName(cname);
if( cid == uniset::DefaultObjectId )
{
ucrit << "(Restorer_XML:getConsumerInfo): НЕ НАЙДЕН ИДЕНТИФИКАТОР заказчика -->"
<< cname << endl;
return false;
}
string cnodename(it.getProp("node"));
if( !cnodename.empty() )
cnode = uniset_conf()->oind->getIdByName(cnodename);
else
cnode = uniset_conf()->getLocalNode();
if( cnode == uniset::DefaultObjectId )
{
ucrit << "(Restorer_XML:getConsumerInfo): НЕ НАЙДЕН ИДЕНТИФИКАТОР узла -->"
<< cnodename << endl;
return false;
}
uinfo << "(Restorer_XML:getConsumerInfo): " << cname << ":" << cnodename << endl;
return true;
}
// -----------------------------------------------------------------------------
bool Restorer_XML::check_list_item( UniXML::iterator& it ) const
{
return uniset::check_filter(it, i_filterField, i_filterValue);
}
// -----------------------------------------------------------------------------
bool Restorer_XML::check_consumer_item( UniXML::iterator& it ) const
{
return uniset::check_filter(it, c_filterField, c_filterValue);
}
// -----------------------------------------------------------------------------
xmlNode* Restorer_XML::find_node( const std::shared_ptr<UniXML>& xml, xmlNode* root,
const string& nodename, const string& nm )
{
UniXML::iterator it(root);
if( it.goChildren() )
{
for( ; it; it.goNext() )
{
if( it.getName() == nodename )
{
if( nm.empty() )
return it;
if( xml->getProp(it, "name") == nm )
return it;
}
}
}
return 0;
}
// -----------------------------------------------------------------------------
void Restorer_XML::setReadItem( ReaderSlot sl )
{
rslot = sl;
}
// -----------------------------------------------------------------------------
void Restorer_XML::setReadConsumerItem( ReaderSlot sl )
{
cslot = sl;
}
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Блокировка повторного запуска программы
* \author Ahton Korbin<ahtoh>, Pavel Vainerman
*/
// --------------------------------------------------------------------------
#include <dirent.h>
#include <unistd.h>
#include "RunLock.h"
#include "Configuration.h"
// --------------------------------------------------------------------------
using namespace uniset;
using namespace std;
// --------------------------------------------------------------------------
RunLock::RunLock()
{
}
RunLock::~RunLock()
{
}
// --------------------------------------------------------------------------
bool RunLock::isLocked( const string& name )
{
FILE* out = fopen( string(name + ".lock" ).c_str(), "r" );
if( out == NULL )
return false;
char ptr[10];
int n = fscanf( out, "%9s", ptr );
if( n < 1 )
{
fclose(out);
return false;
}
DIR* d = opendir( "/proc" );
dirent* dir;
while((dir = readdir(d)))
{
if( !strcmp( ptr, dir->d_name ) )
{
// по хорошему здесь надо бы проверять
// статус на зомби
/*
string path(dir->d_name);
path = "/proc/" + path + "/status";
FILE *out_st = fopen( path.c_str(), "r" );
if(out_st)
{
char ptr_st[1000];
fread(ptr_st, sizeof(ptr_st), 1, out_st);
string str(ptr_st);
if(str.find(exename) == str.npos)
{
fclose(out_st);
break;
}
}
*/
uinfo << "(RunLock): programm " << name << " already run" << endl;
fclose(out);
closedir(d);
return true;
}
}
fclose(out);
closedir(d);
return false;
}
// --------------------------------------------------------------------------
bool RunLock::lock( const string& name )
{
if( !isLocked(name) )
{
FILE* out = fopen( string(name + ".lock" ).c_str(), "w+" );
if(out)
{
fprintf( out, "%d\n", getpid() );
fclose(out);
return true;
}
}
return false;
}
// --------------------------------------------------------------------------
bool RunLock::unlock(const string& name)
{
string fname(name + ".lock");
FILE* out = fopen( fname.c_str(), "r" );
if( out )
{
fclose(out);
unlink(fname.c_str());
return true;
}
return false;
}
// --------------------------------------------------------------------------
...@@ -379,6 +379,28 @@ xmlNode* UniXML::extFindNode( xmlNode* node, int depth, int width, const string& ...@@ -379,6 +379,28 @@ xmlNode* UniXML::extFindNode( xmlNode* node, int depth, int width, const string&
return NULL; return NULL;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
xmlNode* UniXML::findNodeLevel1( xmlNode* root, const string& nodename, const string& nm )
{
UniXML::iterator it(root);
if( it.goChildren() )
{
for( ; it; it.goNext() )
{
if( it.getName() == nodename )
{
if( nm.empty() )
return it;
if( it.getProp("name") == nm )
return it;
}
}
}
return 0;
}
// -----------------------------------------------------------------------------
bool UniXML_iterator::goNext() noexcept bool UniXML_iterator::goNext() noexcept
{ {
if( !curNode ) // || !curNode->next ) if( !curNode ) // || !curNode->next )
......
...@@ -164,6 +164,19 @@ TEST_CASE("UniXML::iterator::find", "[unixml][iterator-find][basic]" ) ...@@ -164,6 +164,19 @@ TEST_CASE("UniXML::iterator::find", "[unixml][iterator-find][basic]" )
REQUIRE( sIt.getProp("name") == "Test5" ); REQUIRE( sIt.getProp("name") == "Test5" );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_CASE("UniXML::iterator::find1Level", "[unixml][find1levels]" )
{
UniXML uxml("tests_unixml.xml");
CHECK( uxml.isOpen() );
xmlNode* onode = uxml.findNode(uxml.getFirstNode(), "onelevelfind");
REQUIRE( onode != NULL );
UniXML::iterator oit(onode);
UniXML::iterator oit2 = uxml.findNodeLevel1(oit,"item","l2");
REQUIRE(oit2);
REQUIRE(oit2.getProp("prop") == "yes");
}
// -----------------------------------------------------------------------------
TEST_CASE("UniXML::iterator::getPropList", "[unixml][iterator-proplist][basic]" ) TEST_CASE("UniXML::iterator::getPropList", "[unixml][iterator-proplist][basic]" )
{ {
UniXML uxml("tests_unixml.xml"); UniXML uxml("tests_unixml.xml");
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
</UniSet> </UniSet>
<dlog name="dlog"/> <dlog name="dlog"/>
<LogServer name="smplus" port="3333" host="localhost" /> <LogServer name="smplus" port="3333" host="localhost" />
<settings> <settings>
<TestData x="10" y="100" text="text" zero="0" negative="-10"/> <TestData x="10" y="100" text="text" zero="0" negative="-10"/>
<TestNode name="TestNode1"/> <TestNode name="TestNode1"/>
...@@ -171,6 +171,25 @@ ...@@ -171,6 +171,25 @@
<item rra="RRA:MAX:0.5:1:4320"/> <item rra="RRA:MAX:0.5:1:4320"/>
</rrd> </rrd>
</RRDServer1> </RRDServer1>
<onelevelfind name="onelevelfind">
<item name="l1">
<item name="l1"/>
<item name="l2" prop="bad"/>
<item name="l3"/>
</item>
<item name="l2" prop="yes">
<item name="l1"/>
<item name="l2" prop="bad"/>
<item name="l3"/>
</item>
<item name="l3">
<item name="l1"/>
<item name="l2" prop="bad"/>
<item name="l3"/>
</item>
<item name="l4"/>
</onelevelfind>
</settings> </settings>
<ObjectsMap idfromfile="1"> <ObjectsMap idfromfile="1">
<!-- <!--
......
...@@ -310,7 +310,8 @@ include/LT_Object.h ...@@ -310,7 +310,8 @@ include/LT_Object.h
include/Makefile.am include/Makefile.am
include/MessageType.h include/MessageType.h
include/Mutex.h include/Mutex.h
include/NCRestorer.h include/IOConfig.h
include/IOConfig_XML.h
include/ObjectIndex.h include/ObjectIndex.h
include/ObjectIndex_Array.h include/ObjectIndex_Array.h
include/ObjectIndex_idXML.h include/ObjectIndex_idXML.h
...@@ -322,8 +323,6 @@ include/PassiveObject.h ...@@ -322,8 +323,6 @@ include/PassiveObject.h
include/PassiveTimer.h include/PassiveTimer.h
include/ProxyManager.h include/ProxyManager.h
include/Pulse.h include/Pulse.h
include/Restorer.h
include/RunLock.h
include/SMonitor.h include/SMonitor.h
include/VMonitor.h include/VMonitor.h
include/SViewer.h include/SViewer.h
...@@ -432,12 +431,11 @@ src/ObjectRepository/ORepHelpers.cc ...@@ -432,12 +431,11 @@ src/ObjectRepository/ORepHelpers.cc
src/Processes/IOController.cc src/Processes/IOController.cc
src/Processes/IONotifyController.cc src/Processes/IONotifyController.cc
src/Processes/Makefile.am src/Processes/Makefile.am
src/Processes/NCRestorer.cc
src/Processes/NCRestorer_XML.cc
src/Processes/CommonEventLoop.cc src/Processes/CommonEventLoop.cc
src/Processes/EventLoopServer.cc src/Processes/EventLoopServer.cc
src/Processes/PassiveObject.cc src/Processes/PassiveObject.cc
src/Processes/ProxyManager.cc src/Processes/ProxyManager.cc
src/Processes/IOConfig_XML.cc
src/Services/DBServer.cc src/Services/DBServer.cc
src/Services/DBInterface.cc src/Services/DBInterface.cc
...@@ -452,8 +450,6 @@ src/Timers/LT_Object.cc ...@@ -452,8 +450,6 @@ src/Timers/LT_Object.cc
src/Various/Makefile.am src/Various/Makefile.am
src/Various/Mutex.cc src/Various/Mutex.cc
src/Various/Restorer_XML.cc
src/Various/RunLock.cc
src/Various/SMonitor.cc src/Various/SMonitor.cc
src/Various/VMonitor.cc src/Various/VMonitor.cc
src/Various/SViewer.cc src/Various/SViewer.cc
......
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