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
...@@ -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);
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
......
...@@ -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);
......
...@@ -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) );
}
}
// -----------------------------------------------------------------------------
...@@ -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