Commit 12cca635 authored by Pavel Vainerman's avatar Pavel Vainerman

backported to p8 as 2.5-alt18.M80P.19 (with rpmbph script)

parents 9f6a6de2 d2ae7b28
......@@ -41,8 +41,8 @@ static struct option longopts[] =
{ "start", no_argument, 0, 's' },
{ "finish", no_argument, 0, 'f' },
{ "foldUp", no_argument, 0, 'u' },
{ "configure", required_argument, 0, 'r' },
{ "logrotate", required_argument, 0, 'l' },
{ "configure", optional_argument, 0, 'r' },
{ "logrotate", optional_argument, 0, 'l' },
{ "info", required_argument, 0, 'i' },
{ "setValue", required_argument, 0, 'x' },
{ "getValue", required_argument, 0, 'g' },
......@@ -60,6 +60,7 @@ string conffile("configure.xml");
// --------------------------------------------------------------------------
static bool commandToAll( const string& section, std::shared_ptr<ObjectRepository>& rep, Command cmd );
static void createSections(const std::shared_ptr<Configuration>& c );
static void errDoNotReolve( const std::string& oname );
// --------------------------------------------------------------------------
int omap();
int configure( const string& args, UInterface& ui );
......@@ -183,7 +184,8 @@ int main(int argc, char** argv)
auto conf = uniset_init(argc, argv, conffile);
UInterface ui(conf);
ui.initBackId(UniSetTypes::AdminID);
return setValue(optarg, ui);
string name = ( optarg ) ? optarg : "";
return setValue(name, ui);
}
break;
......@@ -193,7 +195,8 @@ int main(int argc, char** argv)
auto conf = uniset_init(argc, argv, conffile);
UInterface ui(conf);
ui.initBackId(UniSetTypes::AdminID);
return getValue(optarg, ui);
string name = ( optarg ) ? optarg : "";
return getValue(name, ui);
}
break;
......@@ -203,7 +206,8 @@ int main(int argc, char** argv)
auto conf = uniset_init(argc, argv, conffile);
UInterface ui(conf);
ui.initBackId(UniSetTypes::AdminID);
return getRawValue(optarg, ui);
string name = ( optarg ) ? optarg : "";
return getRawValue(name, ui);
}
break;
......@@ -212,7 +216,8 @@ int main(int argc, char** argv)
auto conf = uniset_init(argc, argv, conffile);
UInterface ui(conf);
ui.initBackId(UniSetTypes::AdminID);
return getChangedTime(optarg, ui);
string name = ( optarg ) ? optarg : "";
return getChangedTime(name, ui);
}
break;
......@@ -270,7 +275,8 @@ int main(int argc, char** argv)
auto conf = uniset_init(argc, argv, conffile);
UInterface ui(conf);
ui.initBackId(UniSetTypes::AdminID);
return configure(optarg, ui);
string name = ( optarg ) ? optarg : "";
return configure(name, ui);
}
break;
......@@ -298,7 +304,8 @@ int main(int argc, char** argv)
auto conf = uniset_init(argc, argv, conffile);
UInterface ui(conf);
ui.initBackId(UniSetTypes::AdminID);
return logRotate(optarg, ui);
string name = ( optarg ) ? optarg : "";
return logRotate(name, ui);
}
break;
......@@ -308,7 +315,8 @@ int main(int argc, char** argv)
auto conf = uniset_init(argc, argv, conffile);
UInterface ui(conf);
ui.initBackId(UniSetTypes::AdminID);
return getCalibrate(optarg, ui);
string name = ( optarg ) ? optarg : "";
return getCalibrate(name, ui);
}
break;
......@@ -365,6 +373,11 @@ int main(int argc, char** argv)
cerr << " mesg: " << fe.errmsg() << endl;
}
}
catch( std::exception& ex )
{
if( !quiet )
cerr << "exception: " << ex.what() << endl;
}
catch(...)
{
if( !quiet )
......@@ -418,7 +431,11 @@ static bool commandToAll(const string& section, std::shared_ptr<ObjectRepository
{
case StartUp:
{
if(CORBA::is_nil(obj)) break;
if( CORBA::is_nil(obj) )
{
errDoNotReolve(ob);
break;
}
SystemMessage msg(SystemMessage::StartUp);
obj->push( Message::transport(msg) );
......@@ -430,7 +447,11 @@ static bool commandToAll(const string& section, std::shared_ptr<ObjectRepository
case FoldUp:
{
if(CORBA::is_nil(obj)) break;
if(CORBA::is_nil(obj))
{
errDoNotReolve(ob);
break;
}
SystemMessage msg(SystemMessage::FoldUp);
obj->push( Message::transport(msg) );
......@@ -442,7 +463,11 @@ static bool commandToAll(const string& section, std::shared_ptr<ObjectRepository
case Finish:
{
if(CORBA::is_nil(obj)) break;
if(CORBA::is_nil(obj))
{
errDoNotReolve(ob);
break;
}
SystemMessage msg(SystemMessage::Finish);
obj->push( Message::transport(msg) );
......@@ -511,6 +536,9 @@ static bool commandToAll(const string& section, std::shared_ptr<ObjectRepository
}
catch( ORepFailed )
{
if( !quiet )
cerr << "..ORepFailed.." << endl;
cout.setf(old_flags);
return false;
}
......@@ -875,7 +903,7 @@ int logRotate( const string& arg, UInterface& ui )
auto conf = ui.getConf();
// посылка всем
if( arg.empty() || (arg.c_str())[0] != '-' )
if( arg.empty() || arg[0] == '-' )
{
auto rep = make_shared<ObjectRepository>(conf);
commandToAll(conf->getServicesSection(), rep, (Command)LogRotate);
......@@ -884,12 +912,16 @@ int logRotate( const string& arg, UInterface& ui )
}
else // посылка определённому объекту
{
UniSetTypes::ObjectId id = conf->oind->getIdByName(arg);
UniSetTypes::ObjectId id = conf->getObjectID(arg);
if( id == DefaultObjectId )
id = conf->getControllerID(arg);
else if( id == DefaultObjectId )
id = conf->getServiceID(arg);
if( id == DefaultObjectId )
{
if( !quiet )
cout << "(logrotate): name='" << arg << "' не найдено!!!\n";
cout << "(logrotate): not found ID for name='" << arg << "'" << endl;
return 1;
}
......@@ -911,7 +943,7 @@ int configure( const string& arg, UInterface& ui )
auto conf = ui.getConf();
// посылка всем
if( arg.empty() || (arg.c_str())[0] != '-' )
if( arg.empty() || arg[0] == '-' )
{
auto rep = make_shared<ObjectRepository>(conf);
commandToAll(conf->getServicesSection(), rep, (Command)Configure);
......@@ -920,7 +952,12 @@ int configure( const string& arg, UInterface& ui )
}
else // посылка определённому объекту
{
UniSetTypes::ObjectId id = conf->oind->getIdByName(arg);
UniSetTypes::ObjectId id = conf->getObjectID(arg);
if( id == DefaultObjectId )
id = conf->getControllerID(arg);
if( id == DefaultObjectId )
id = conf->getServiceID(arg);
if( id == DefaultObjectId )
{
......@@ -1010,3 +1047,9 @@ int oinfo( const string& args, UInterface& ui, int userparam )
}
// --------------------------------------------------------------------------------------
void errDoNotReolve( const std::string& oname )
{
if( verb )
cerr << oname << ": resolve failed.." << endl;
}
// --------------------------------------------------------------------------------------
......@@ -87,7 +87,7 @@ int main( int argc, char** argv )
LogServerTypes::Command cmd = LogServerTypes::cmdNOP;
int cmdonly = 0;
timeout_t tout = UniSetTimer::WaitUpTime;
timeout_t rdelay = 5000;
timeout_t rdelay = 8000;
string logfile("");
bool logtruncate = false;
......
......@@ -167,7 +167,6 @@ int main( int argc, char** argv )
la->printLogList(cout);
return 0;
#endif
LogServer ls(la);
ls.setMaxSessionCount(msess);
......@@ -214,9 +213,9 @@ int main( int argc, char** argv )
{
cerr << "(logserver): " << ex << endl;
}
catch(...)
catch( std::exception& ex)
{
cerr << "(logserver): catch(...)" << endl;
cerr << "(logserver): " << ex.what() << endl;
}
return 0;
......
......@@ -474,6 +474,9 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::preSysCommand( const SystemMessage*
mylog->logFile(fname.c_str(),true);
mylogany &lt;&lt; myname &lt;&lt; "(preSysCommand): ***************** mylog LOG ROTATE *****************" &lt;&lt; endl;
}
if( logserv &amp;&amp; !logserv_host.empty() &amp;&amp; logserv_port != 0 )
logserv-&gt;check(true);
}
break;
......@@ -493,7 +496,16 @@ UniSetTypes::SimpleInfo* <xsl:value-of select="$CLASSNAME"/>_SK::getInfo( CORBA:
ostringstream inf;
inf &lt;&lt; i->info &lt;&lt; endl;
inf &lt;&lt; "LogServer: " &lt;&lt; logserv_host &lt;&lt; ":" &lt;&lt; logserv_port &lt;&lt; endl;
if( logserv /* &amp;&amp; userparam &lt; 0 */ )
{
inf &lt;&lt; "LogServer: " &lt;&lt; logserv_host &lt;&lt; ":" &lt;&lt; logserv_port
&lt;&lt; ( logserv->isRunning() ? " [RUNNIG]" : " [FAILED]" ) &lt;&lt; endl;
inf &lt;&lt; " " &lt;&lt; logserv->getShortInfo() &lt;&lt; endl;
}
else
inf &lt;&lt; "LogServer: NONE" &lt;&lt; endl;
inf &lt;&lt; dumpIO() &lt;&lt; endl;
inf &lt;&lt; endl;
auto timers = getTimersList();
......@@ -658,8 +670,8 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::waitSM( int wait_msec, ObjectId _te
mycrit &lt;&lt; err.str() &lt;&lt; endl;
// terminate();
// abort();
raise(SIGTERM);
terminate();
// raise(SIGTERM);
std::terminate();
// throw SystemError(err.str());
}
......@@ -673,7 +685,8 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::waitSM( int wait_msec, ObjectId _te
mycrit &lt;&lt; err.str() &lt;&lt; endl;
// terminate();
// abort();
raise(SIGTERM);
//raise(SIGTERM);
std::terminate();
// throw SystemError(err.str());
}
}
......@@ -1121,6 +1134,7 @@ end_private(false)
vmonit(maxHeartBeat);
vmonit(activateTimeout);
vmonit(smReadyTimeout);
vmonit(smTestID);
// help надо выводить в конце, когда уже все переменные инициализированы по умолчанию
......@@ -1510,6 +1524,9 @@ askPause(uniset_conf()->getPIntProp(cnode,"askPause",2000))
if( smTestID == DefaultObjectId )
smTestID = getSMTestID();
vmonit(smTestID);
vmonit(smReadyTimeout);
activateTimeout = conf->getArgPInt("--" + argprefix + "activate-timeout", 20000);
int msec = conf->getArgPInt("--" + argprefix + "startup-timeout", 10000);
......
......@@ -42,6 +42,7 @@ TestGen::TestGen()
// -----------------------------------------------------------------------------
void TestGen::step()
{
#if 0
cout << "strval: " << strval(input2_s) << endl;
cout << "str: " << str(input2_s) << endl;
cout << "===========" << endl;
......@@ -53,7 +54,7 @@ void TestGen::step()
int_var++;
bool_var ^= true;
cout << vmon << endl;
#endif
// cout << vmon.pretty_str() << endl;
}
// -----------------------------------------------------------------------------
......
......@@ -2,8 +2,9 @@
ulimit -Sc 1000000
uniset2-start.sh -f ./test --name TestProc --confile test.xml --ulog-add-levels warn,crit \
--test-sm-ready-timeout 15000 --test-run-logserver --test-log-add-levels any $*
uniset2-start.sh -f ./test --name TestProc --confile test.xml --ulog-add-levels system,warn,crit \
--test-sm-ready-timeout 15000 --test-run-logserver --test-logserver-host 192.192.192.192
#--test-log-add-levels any $*
#info,warn,crit,system,level9 > 1.log
#--c-filter-field cfilter --c-filter-value test1 --s-filter-field io --s-filter-value 1
......
......@@ -16,7 +16,7 @@
Name: libuniset2
Version: 2.5
Release: alt13.M80P.14
Release: alt18.M80P.19
Summary: UniSet - library for building distributed industrial control systems
License: LGPL
......@@ -488,9 +488,40 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
# ..
%changelog
* Tue Sep 13 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt13.M80P.14
* Tue Oct 11 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt18.M80P.19
- backport to ALTLinux p8 (by rpmbph script)
* Tue Oct 11 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt19
- Calibration: fixed bug in getValue(), refactoring
- correction after verification static analyzer
- LogServer: fixed bug "connection refuse"
* Sat Oct 08 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt18
- LogServer: fixed bug "do not close connection"
* Fri Sep 30 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt17
- ModbusMultiMaster: add new check connection strategy
- LogServer: minor fixes
* Tue Sep 27 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt16
- LogSession: add more logs
- codegen: add logserver information in getInfo()
* Tue Sep 20 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt15
- up build
* Tue Sep 20 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt14.4
- UTCPStream: check POCO_INVALID_SOCKET
* Mon Sep 19 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt14.3
- UTCPStream: shudown and close (for disconnect)
* Mon Sep 19 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt14.2
- (ModbusTCPMaster): added disconnect() function
* Mon Sep 19 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt14.1
- (ModbusTCPMaster): added catch exceptions
* Mon Sep 12 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt14
- up build
......
......@@ -50,4 +50,3 @@
\note Описание составлено на основе описания мьютексов из книги А.Цимбала "Технология CORBA для профессионалов".
*/
\ No newline at end of file
......@@ -34,4 +34,10 @@ d_DATA = html/*
# exampledir = $(docdir)/examples
# example_DATA = examples/*
pdf:
doxygen UniSetDox.cfg
subst 's|OT1|T2A|g' latex/doxygen.sty
subst 's|Times-Roman|Liberation Sans|g' latex/*
cd latex; make; cd -;
endif
......@@ -247,12 +247,12 @@ EXTENSION_MAPPING =
# func(std::string) {}). This also makes the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
BUILTIN_STL_SUPPORT = NO
BUILTIN_STL_SUPPORT = YES
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
CPP_CLI_SUPPORT = NO
CPP_CLI_SUPPORT = YES
# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
# Doxygen will parse them like normal C++ but will assume all classes use public
......@@ -377,7 +377,7 @@ EXTRACT_LOCAL_METHODS = NO
# name of the file that contains the anonymous namespace. By default
# anonymous namespaces are hidden.
EXTRACT_ANON_NSPACES = NO
EXTRACT_ANON_NSPACES = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
......@@ -421,7 +421,7 @@ INTERNAL_DOCS = NO
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
CASE_SENSE_NAMES = YES
CASE_SENSE_NAMES = NO
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
......@@ -433,7 +433,7 @@ HIDE_SCOPE_NAMES = NO
# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
SHOW_INCLUDE_FILES = NO
# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
# will list include files with double quotes in the documentation
......@@ -499,25 +499,25 @@ STRICT_PROTO_MATCHING = NO
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = YES
GENERATE_TODOLIST = NO
# The GENERATE_TESTLIST tag can be used to enable (YES) or
# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = YES
GENERATE_TESTLIST = NO
# The GENERATE_BUGLIST tag can be used to enable (YES) or
# disable (NO) the bug list. This list is created by putting \bug
# commands in the documentation.
GENERATE_BUGLIST = YES
GENERATE_BUGLIST = NO
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
# disable (NO) the deprecated list. This list is created by putting
# \deprecated commands in the documentation.
GENERATE_DEPRECATEDLIST= YES
GENERATE_DEPRECATEDLIST= NO
# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
......@@ -532,25 +532,25 @@ ENABLED_SECTIONS =
# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
MAX_INITIALIZER_LINES = 30
MAX_INITIALIZER_LINES = 25
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = YES
SHOW_USED_FILES = NO
# If the sources in your project are distributed over multiple directories
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
# in the documentation. The default is NO.
SHOW_DIRECTORIES = YES
SHOW_DIRECTORIES = NO
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
SHOW_FILES = YES
SHOW_FILES = NO
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
# Namespaces page. This will remove the Namespaces entry from the Quick Index
......@@ -800,13 +800,13 @@ STRIP_CODE_COMMENTS = YES
# then for each documented function all documented
# functions referencing it will be listed.
REFERENCED_BY_RELATION = YES
REFERENCED_BY_RELATION = NO
# If the REFERENCES_RELATION tag is set to YES
# then for each documented function all documented entities
# called/used by that function will be listed.
REFERENCES_RELATION = YES
REFERENCES_RELATION = NO
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
......@@ -837,7 +837,7 @@ VERBATIM_HEADERS = YES
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX = NO
ALPHABETICAL_INDEX = YES
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
......@@ -1222,7 +1222,7 @@ SERVER_BASED_SEARCH = NO
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = NO
GENERATE_LATEX = YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
......@@ -1248,7 +1248,7 @@ MAKEINDEX_CMD_NAME = makeindex
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
COMPACT_LATEX = YES
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, letter, legal and
......@@ -1280,13 +1280,13 @@ LATEX_FOOTER =
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = NO
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = NO
USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
......@@ -1328,13 +1328,13 @@ GENERATE_RTF = NO
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
RTF_OUTPUT = rtf
RTF_OUTPUT = rtf2
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
COMPACT_RTF = YES
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
......@@ -1608,7 +1608,7 @@ HIDE_UNDOC_RELATIONS = YES
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = NO
HAVE_DOT = YES
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
# allowed to run in parallel. When set to 0 (the default) doxygen will
......@@ -1770,7 +1770,7 @@ MAX_DOT_GRAPH_DEPTH = 0
# enabling this option may lead to badly anti-aliased labels on the edges of
# a graph (i.e. they become hard to read).
DOT_TRANSPARENT = YES
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
......
......@@ -384,10 +384,12 @@ void DBServer_MySQL::timerInfo( const UniSetTypes::TimerMessage* tm )
askTimer(DBServer_MySQL::ReconnectTimer, 0);
askTimer(DBServer_MySQL::PingTimer, PingTime);
}
else
{
connect_ok = false;
dbwarn << myname << "(timerInfo): DB no connection.." << endl;
}
}
else
initDBServer();
}
......
......@@ -220,10 +220,9 @@ void DBServer_PostgreSQL::flushInsertBuffer()
}
ibuf.erase(beg, end);
ibufSize -= delnum;
if( ibufSize < 0 )
ibufSize = 0;
// ibufSize - беззнаковое, так что надо аккуратно
ibufSize = (delnum < ibufSize) ? (ibufSize-delnum) : 0;
dbwarn << myname << "(flushInsertBuffer): overflow: clear data " << delnum << " records." << endl;
return;
......@@ -438,10 +437,12 @@ void DBServer_PostgreSQL::timerInfo( const UniSetTypes::TimerMessage* tm )
askTimer(DBServer_PostgreSQL::ReconnectTimer, 0);
askTimer(DBServer_PostgreSQL::PingTimer, PingTime);
}
else
{
connect_ok = false;
dbwarn << myname << "(timerInfo): DB no connection.." << endl;
}
}
else
initDBServer();
}
......
......@@ -110,7 +110,7 @@ class DBServer_PostgreSQL:
typedef std::queue<std::string> QueryBuffer;
QueryBuffer qbuf;
unsigned int qbufSize; // размер буфера сообщений.
size_t qbufSize; // размер буфера сообщений.
bool lastRemove = { false };
void flushBuffer();
......
......@@ -359,10 +359,12 @@ void DBServer_SQLite::timerInfo( const UniSetTypes::TimerMessage* tm )
askTimer(DBServer_SQLite::ReconnectTimer, 0);
askTimer(DBServer_SQLite::PingTimer, PingTime);
}
else
{
connect_ok = false;
dbwarn << myname << "(timerInfo): DB no connection.." << endl;
}
}
else
initDBServer();
}
......
......@@ -69,9 +69,9 @@ IOControl::IOControl(UniSetTypes::ObjectId id, UniSetTypes::ObjectId icID,
auto conf = uniset_conf();
string cname = conf->getArgParam("--" + prefix + "-confnode", myname);
cnode = conf->getNode(cname);
confnode = conf->getNode(cname);
if( cnode == NULL )
if( confnode == NULL )
throw SystemError("Not found conf-node " + cname + " for " + myname);
iolog = make_shared<DebugStream>();
......@@ -89,10 +89,10 @@ IOControl::IOControl(UniSetTypes::ObjectId id, UniSetTypes::ObjectId icID,
ioinfo << myname << "(init): numcards=" << numcards << endl;
UniXML::iterator it(cnode);
UniXML::iterator it(confnode);
logserv = make_shared<LogServer>(loga);
logserv->init( prefix + "-logserver", cnode );
logserv->init( prefix + "-logserver", confnode );
if( findArgParam("--" + prefix + "-run-logserver", conf->getArgc(), conf->getArgv()) != -1 )
{
......@@ -306,7 +306,7 @@ IOControl::~IOControl()
void IOControl::execute()
{
// set_signals(true);
UniXML::iterator it(cnode);
UniXML::iterator it(confnode);
waitSM(); // необходимо дождаться, чтобы нормально инициализировать итераторы
......@@ -1055,7 +1055,9 @@ void IOControl::check_testmode()
// если режим "выключено всё"
// то гасим все выходы
if( testmode == tmOffPoll )
if( testmode == tmOffPoll ||
testmode == tmConfigEnable ||
testmode == tmConfigDisable )
{
// выставляем безопасные состояния
for( auto& it : iomap )
......@@ -1602,17 +1604,15 @@ void IOControl::buildCardsList()
return;
}
//xmlNode* cnode = xml->findNode(mynode,"iocards","");
//xmlNode* extFindNode(xmlNode* node, int depth, int width, const std::string searchnode, const std::string name = "", bool top=true );
xmlNode* cnode = xml->extFindNode(mynode, 1, 1, "iocards", "");
xmlNode* cardsnode = xml->extFindNode(mynode, 1, 1, "iocards", "");
if( !cnode )
if( !cardsnode )
{
iowarn << myname << "(buildCardsList): Not found <iocards> for node=" << conf->getLocalNodeName() << "(" << conf->getLocalNode() << ")" << endl;
return;
}
UniXML::iterator it(cnode);
UniXML::iterator it(cardsnode);
if( !it.goChildren() )
{
......
......@@ -335,7 +335,7 @@ class IOControl:
void waitSM();
xmlNode* cnode = { 0 }; /*!< xml-узел в настроечном файле */
xmlNode* confnode = { 0 }; /*!< xml-узел в настроечном файле */
int polltime = { 150 }; /*!< переодичность обновления данных (опроса карт в/в), [мсек] */
CardList cards; /*!< список карт - массив созданных ComediInterface */
......
......@@ -72,7 +72,6 @@ int subdev = 0;
int chan = 0;
int range = 0;
int aref = AREF_GROUND;
bool go = true;
static struct option longopts[] =
{
......
......@@ -78,10 +78,11 @@ MBTCPMultiMaster::MBTCPMultiMaster( UniSetTypes::ObjectId objId, UniSetTypes::Ob
continue;
}
MBSlaveInfo sinf;
sinf.ip = it1.getProp("ip");
auto sinf = make_shared<MBSlaveInfo>();
if( sinf.ip.empty() )
sinf->ip = it1.getProp("ip");
if( sinf->ip.empty() )
{
ostringstream err;
err << myname << "(init): ip='' in <GateList>";
......@@ -89,21 +90,21 @@ MBTCPMultiMaster::MBTCPMultiMaster( UniSetTypes::ObjectId objId, UniSetTypes::Ob
throw UniSetTypes::SystemError(err.str());
}
sinf.port = it1.getIntProp("port");
sinf->port = it1.getIntProp("port");
if( sinf.port <= 0 )
if( sinf->port <= 0 )
{
ostringstream err;
err << myname << "(init): ERROR: port=''" << sinf.port << " for ip='" << sinf.ip << "' in <GateList>";
err << myname << "(init): ERROR: port=''" << sinf->port << " for ip='" << sinf->ip << "' in <GateList>";
mbcrit << err.str() << endl;
throw UniSetTypes::SystemError(err.str());
}
if( !it1.getProp("respondSensor").empty() )
{
sinf.respond_id = conf->getSensorID( it1.getProp("respondSensor") );
sinf->respond_id = conf->getSensorID( it1.getProp("respondSensor") );
if( sinf.respond_id == DefaultObjectId )
if( sinf->respond_id == DefaultObjectId )
{
ostringstream err;
err << myname << "(init): ERROR: Unknown SensorID for '" << it1.getProp("respondSensor") << "' in <GateList>";
......@@ -112,33 +113,51 @@ MBTCPMultiMaster::MBTCPMultiMaster( UniSetTypes::ObjectId objId, UniSetTypes::Ob
}
}
sinf.priority = it1.getIntProp("priority");
sinf.mbtcp = std::make_shared<ModbusTCPMaster>();
sinf->priority = it1.getIntProp("priority");
sinf->mbtcp = std::make_shared<ModbusTCPMaster>();
sinf->ptIgnoreTimeout.setTiming( it1.getPIntProp("ignore_timeout", ignore_timeout) );
sinf->recv_timeout = it1.getPIntProp("recv_timeout", recv_timeout);
sinf->aftersend_pause = it1.getPIntProp("aftersend_pause", aftersend_pause);
sinf->sleepPause_usec = it1.getPIntProp("sleepPause_msec", sleepPause_msec);
sinf->respond_invert = it1.getPIntProp("invert", 0);
sinf->respond_force = it1.getPIntProp("force", 0);
int fn = conf->getArgPInt("--" + prefix + "-check-func", it.getProp("checkFunc"), ModbusRTU::fnUnknown);
if( fn != ModbusRTU::fnUnknown &&
fn != ModbusRTU::fnReadCoilStatus &&
fn != ModbusRTU::fnReadInputStatus &&
fn != ModbusRTU::fnReadOutputRegisters &&
fn != ModbusRTU::fnReadInputRegisters )
{
ostringstream err;
err << myname << "(init): BAD check function ='" << fn << "'. Must be [1,2,3,4]";
mbcrit << err.str() << endl;
throw SystemError(err.str());
}
sinf->checkFunc = (ModbusRTU::SlaveFunctionCode)fn;
sinf.ptIgnoreTimeout.setTiming( it1.getPIntProp("ignore_timeout", ignore_timeout) );
sinf.recv_timeout = it1.getPIntProp("recv_timeout", recv_timeout);
sinf.aftersend_pause = it1.getPIntProp("aftersend_pause", aftersend_pause);
sinf.sleepPause_usec = it1.getPIntProp("sleepPause_msec", sleepPause_msec);
sinf.respond_invert = it1.getPIntProp("invert", 0);
sinf.respond_force = it1.getPIntProp("force", 0);
sinf->checkAddr = conf->getArgPInt("--" + prefix + "-check-addr", it.getProp("checkAddr"), 0);
sinf->checkReg = conf->getArgPInt("--" + prefix + "-check-reg", it.getProp("checkReg"), 0);
int tout = it1.getPIntProp("timeout", channelTimeout);
sinf.channel_timeout = (tout >= 0 ? tout : channelTimeout);
sinf->channel_timeout = (tout >= 0 ? tout : channelTimeout);
// делаем только задержку на отпускание..
sinf.respondDelay.set(0, sinf.channel_timeout);
sinf->respondDelay.set(0, sinf->channel_timeout);
sinf.force_disconnect = it.getPIntProp("persistent_connection", !force_disconnect) ? false : true;
sinf->force_disconnect = it.getPIntProp("persistent_connection", !force_disconnect) ? false : true;
ostringstream n;
n << sinf.ip << ":" << sinf.port;
sinf.myname = n.str();
n << sinf->ip << ":" << sinf->port;
sinf->myname = n.str();
auto l = loga->create(sinf.myname);
sinf.mbtcp->setLog(l);
auto l = loga->create(sinf->myname);
sinf->mbtcp->setLog(l);
mbinfo << myname << "(init): add slave channel " << sinf.myname << endl;
mblist.emplace_back(std::move(sinf));
mbinfo << myname << "(init): add slave channel " << sinf->myname << endl;
mblist.emplace_back(sinf);
}
if( ic )
......@@ -154,7 +173,8 @@ MBTCPMultiMaster::MBTCPMultiMaster( UniSetTypes::ObjectId objId, UniSetTypes::Ob
}
mblist.sort();
mbi = mblist.rbegin();
mbi = mblist.rbegin(); // т.к. mbi это reverse_iterator
(*mbi)->setUse(true);
if( shm->isLocalwork() )
{
......@@ -214,64 +234,69 @@ std::shared_ptr<ModbusClient> MBTCPMultiMaster::initMB( bool reopen )
if( mbi == mblist.rend() )
mbi = mblist.rbegin();
mbi->init(mblog);
auto m = (*mbi);
m->init(mblog);
// переопределяем timeout на данный канал
ptReopen.setTiming( mbi->channel_timeout );
ptReopen.setTiming( m->channel_timeout );
mb = mbi->mbtcp;
return mbi->mbtcp;
m->setUse(true);
mb = m->mbtcp;
return m->mbtcp;
}
{
// сперва надо обновить все ignore
// т.к. фактически флаги выставляются и сбрасываются только здесь
for( auto it = mblist.rbegin(); it != mblist.rend(); ++it )
for( auto&& it: mblist )
it->ignore = !it->ptIgnoreTimeout.checkTime();
// если reopen=true - значит почему-то по текущему каналу связи нет (хотя соединение есть)
// тогда выставляем ему признак игнорирования
if( mbi != mblist.rend() && reopen )
{
mbi->setUse(false);
mbi->ignore = true;
mbi->ptIgnoreTimeout.reset();
mbwarn << myname << "(initMB): set ignore=true for " << mbi->ip << ":" << mbi->port << endl;
auto m = (*mbi);
m->setUse(false);
m->ignore = true;
m->ptIgnoreTimeout.reset();
mbwarn << myname << "(initMB): set ignore=true for " << m->ip << ":" << m->port << endl;
}
// Если по текущему каналу связь есть (и мы его не игнорируем), то возвращаем его
if( mbi != mblist.rend() && !mbi->ignore && mbi->respond )
if( mbi != mblist.rend() && !(*mbi)->ignore && (*mbi)->respond )
{
auto m = (*mbi);
// ещё раз проверим соединение (в неблокирующем режиме)
mbi->respond = mbi->check();
m->respond = m->check();
if( mbi->respond && (mbi->mbtcp->isConnection() || mbi->init(mblog)) )
if( m->respond && (m->mbtcp->isConnection() || m->init(mblog)) )
{
mblog4 << myname << "(initMB): SELECT CHANNEL " << mbi->ip << ":" << mbi->port << endl;
mb = mbi->mbtcp;
mbi->setUse(true);
ptReopen.setTiming( mbi->channel_timeout );
return mbi->mbtcp;
mblog4 << myname << "(initMB): SELECT CHANNEL " << m->ip << ":" << m->port << endl;
mb = m->mbtcp;
m->setUse(true);
ptReopen.setTiming( m->channel_timeout );
return m->mbtcp;
}
mbi->setUse(false);
m->setUse(false);
}
if( mbi != mblist.rend() )
mbi->mbtcp->forceDisconnect();
(*mbi)->mbtcp->forceDisconnect();
}
// проходим по списку (в обратном порядке, т.к. самый приоритетный в конце)
for( auto it = mblist.rbegin(); it != mblist.rend(); ++it )
{
if( it->respond && !it->ignore && it->init(mblog) )
auto m = (*it);
if( m->respond && !m->ignore && m->init(mblog) )
{
mbi = it;
mb = mbi->mbtcp;
mbi->setUse(true);
ptReopen.setTiming( mbi->channel_timeout );
mblog4 << myname << "(initMB): SELECT CHANNEL " << mbi->ip << ":" << mbi->port << endl;
return it->mbtcp;
mb = m->mbtcp;
m->setUse(true);
ptReopen.setTiming( m->channel_timeout );
mblog4 << myname << "(initMB): SELECT CHANNEL " << m->ip << ":" << m->port << endl;
return m->mbtcp;
}
}
......@@ -280,15 +305,16 @@ std::shared_ptr<ModbusClient> MBTCPMultiMaster::initMB( bool reopen )
// значит сейчас просто находим первый у кого есть связь и делаем его главным
for( auto it = mblist.rbegin(); it != mblist.rend(); ++it )
{
if( it->respond && it->check() && it->init(mblog) )
auto& m = (*it);
if( m->respond && m->check() && m->init(mblog) )
{
mbi = it;
mb = mbi->mbtcp;
mbi->ignore = false;
mbi->setUse(true);
ptReopen.setTiming( mbi->channel_timeout );
mblog4 << myname << "(initMB): SELECT CHANNEL " << mbi->ip << ":" << mbi->port << endl;
return it->mbtcp;
mb = m->mbtcp;
m->ignore = false;
m->setUse(true);
ptReopen.setTiming( m->channel_timeout );
mblog4 << myname << "(initMB): SELECT CHANNEL " << m->ip << ":" << m->port << endl;
return m->mbtcp;
}
}
......@@ -307,13 +333,80 @@ void MBTCPMultiMaster::final_thread()
}
// -----------------------------------------------------------------------------
bool MBTCPMultiMaster::MBSlaveInfo::check() const
bool MBTCPMultiMaster::MBSlaveInfo::check()
{
std::unique_lock<std::mutex> lock(mutInit, std::try_to_lock);
// т.к. check вызывается периодически, то нем не страшно сделать return
// и в следующий раз проверить ещё раз..
if( !lock.owns_lock() )
return use; // возвращаем 'use' т.к. если use=1 то считается что связь есть..
if( !mbtcp )
return false;
if( use )
return true;
// cerr << myname << "(check): check connection..." << ip << ":" << port
// << " mbfunc=" << checkFunc
// << " mbaddr=" << ModbusRTU::addr2str(checkAddr)
// << " mbreg=" << (int)checkReg << "(" << ModbusRTU::dat2str(checkReg) << ")"
// << endl;
try
{
mbtcp->connect(ip,port,false);
switch(checkFunc)
{
case ModbusRTU::fnReadCoilStatus:
{
auto ret = mbtcp->read01(checkAddr,checkReg,1);
return true;
}
break;
case ModbusRTU::fnReadInputStatus:
{
auto ret = mbtcp->read02(checkAddr,checkReg,1);
return true;
}
break;
case ModbusRTU::fnReadOutputRegisters:
{
auto ret = mbtcp->read03(checkAddr,checkReg,1);
return true;
}
break;
case ModbusRTU::fnReadInputRegisters:
{
auto ret = mbtcp->read04(checkAddr,checkReg,1);
return true;
}
break;
default: // просто проверка..
return mbtcp->checkConnection(ip, port, recv_timeout);
}
}
catch(...){}
return false;
}
// -----------------------------------------------------------------------------
void MBTCPMultiMaster::MBSlaveInfo::setUse( bool st )
{
std::lock_guard<std::mutex> l(mutInit);
respond_init = !( st && !use );
use = st;
}
// -----------------------------------------------------------------------------
bool MBTCPMultiMaster::MBSlaveInfo::init( std::shared_ptr<DebugStream>& mblog )
{
std::lock_guard<std::mutex> l(mutInit);
mbinfo << myname << "(init): connect..." << endl;
if( initOK )
......@@ -339,6 +432,8 @@ void MBTCPMultiMaster::sysCommand( const UniSetTypes::SystemMessage* sm )
if( sm->command == SystemMessage::StartUp )
{
initCheckConnectionParameters();
pollThread->start();
if( checktime > 0 )
......@@ -387,7 +482,7 @@ void MBTCPMultiMaster::check_thread()
{
while( checkProcActive() )
{
for( auto it = mblist.begin(); it != mblist.end(); ++it )
for( auto&& it: mblist )
{
try
{
......@@ -409,6 +504,9 @@ void MBTCPMultiMaster::check_thread()
if( it->respond_init )
r = it->respondDelay.check( r );
if( !checkProcActive() )
break;
try
{
if( it->respond_id != DefaultObjectId && (it->respond_force || !it->respond_init || r != it->respond) )
......@@ -450,7 +548,7 @@ void MBTCPMultiMaster::initIterators()
MBExchange::initIterators();
for( auto && it : mblist )
shm->initIterator(it.respond_it);
shm->initIterator(it->respond_it);
}
// -----------------------------------------------------------------------------
void MBTCPMultiMaster::sigterm( int signo )
......@@ -509,6 +607,87 @@ bool MBTCPMultiMaster::deactivateObject()
return MBExchange::deactivateObject();
}
// -----------------------------------------------------------------------------
void MBTCPMultiMaster::initCheckConnectionParameters()
{
auto conf = uniset_conf();
bool initFromRegMap = ( findArgParam("--" + prefix + "-check-init-from-regmap", conf->getArgc(), conf->getArgv()) != -1 );
if( !initFromRegMap )
return;
mbinfo << myname << "(init): init check connection parameters from regmap.." << endl;
// берём первый попавшийся read-регистр из списка
// от первого попавшегося устройства..
ModbusRTU::SlaveFunctionCode checkFunc = ModbusRTU::fnUnknown;
ModbusRTU::ModbusAddr checkAddr = { 0x00 };
ModbusRTU::ModbusData checkReg = { 0 };
if( devices.empty() )
{
mbwarn << myname << "(init): devices list empty?!" << endl;
return;
}
// идём по устройствам
for( const auto& d: devices )
{
checkAddr = d.second->mbaddr;
if( d.second->pollmap.empty() )
continue;
// идём по списку опрашиваемых регистров
for( auto p = d.second->pollmap.begin(); p != d.second->pollmap.end(); ++p )
{
for( auto r = p->second->begin(); r!=p->second->end(); ++r )
{
if( ModbusRTU::isReadFunction(r->second->mbfunc) )
{
checkFunc = r->second->mbfunc;
checkReg = r->second->mbreg;
break;
}
}
if( checkFunc != ModbusRTU::fnUnknown )
break;
}
if( checkFunc != ModbusRTU::fnUnknown )
break;
}
if( checkFunc == ModbusRTU::fnUnknown )
{
ostringstream err;
err << myname << "(init): init check connection parameters: ERROR: "
<< " NOT FOUND read-registers for check connection!"
<< endl;
mbcrit << err.str() << endl;
throw SystemError(err.str());
}
mbinfo << myname << "(init): init check connection parameters: "
<< " mbfunc=" << checkFunc
<< " mbaddr=" << ModbusRTU::addr2str(checkAddr)
<< " mbreg=" << (int)checkReg << "(" << ModbusRTU::dat2str(checkReg) << ")"
<< endl;
// инициализируем..
for( auto&& m: mblist )
{
m->checkFunc = checkFunc;
m->checkAddr = checkAddr;
m->checkReg = checkReg;
}
}
// -----------------------------------------------------------------------------
void MBTCPMultiMaster::help_print( int argc, const char* const* argv )
......@@ -520,6 +699,11 @@ void MBTCPMultiMaster::help_print( int argc, const char* const* argv )
cout << "--prefix-persistent-connection 0,1 - Не закрывать соединение на каждом цикле опроса" << endl;
cout << "--prefix-checktime msec - период проверки связи по каналам (<GateList>)" << endl;
cout << "--prefix-ignore-timeout msec - Timeout на повторную попытку использования канала после 'reopen-timeout'. По умолчанию: reopen-timeout * 3" << endl;
cout << "--prefix-check-func [1,2,3,4] - Номер функции для проверки соединения" << endl;
cout << "--prefix-check-addr [1..255 ] - Адрес устройства для проверки соединения" << endl;
cout << "--prefix-check-reg [1..65535] - Регистр для проверки соединения" << endl;
cout << endl;
cout << " ВНИМАНИЕ! '--prefix-reopen-timeout' для MBTCPMultiMaster НЕ ДЕЙСТВУЕТ! " << endl;
cout << " Смена канала происходит по --prefix-timeout. " << endl;
......@@ -581,7 +765,7 @@ UniSetTypes::SimpleInfo* MBTCPMultiMaster::getInfo( CORBA::Long userparam )
inf << "Gates: " << (checktime <= 0 ? "/ check connections DISABLED /" : "") << endl;
for( const auto& m : mblist )
inf << " " << m.getShortInfo() << endl;
inf << " " << m->getShortInfo() << endl;
inf << endl;
......
......@@ -31,6 +31,7 @@
- \ref sec_MBTCPM_Conf
- \ref sec_MBTCPM_ConfList
- \ref sec_MBTCPM_ExchangeMode
- \ref sec_MBTCPM_CheckConnection
\section sec_MBTCPM_Comm Общее описание ModbusTCPMultiMaster
Класс реализует процесс обмена (опрос/запись) с RTU-устройствами,
......@@ -85,6 +86,9 @@
- \b respond_invert - инвертировать датчик связи (DI)
- \b force [1,0] - "1" - обновлять значение датчика связи в SM принудительно на каждом цикле проверки ("0" - только по изменению).
- \b timeout - таймаут на определение отсутсвия связи для данного канала. По умолчанию берётся глобальный.
- \b checkFunc - Номер функции для проверки соединения
- \b checkAddr - Адрес устройства для проверки соединения
- \b checkReg - Регистр для проверки соединения
\par Параметры запуска
......@@ -143,6 +147,11 @@
\b --xxx-activate-timeout msec . По умолчанию 2000. - время ожидания готовности SharedMemory к работе.
\b --xxx-check-func [1,2,3,4] - Номер функции для проверки соединения
\b --xxx-check-addr [1..255 ] - Адрес устройства для проверки соединения
\b --xxx-check-reg [1..65535] - Регистр для проверки соединения
\b --xxx-check-init-from-regmap - Взять адрес, функцию и регистр для проверки связи из списка опроса
\section sec_MBTCPM_ConfList Конфигурирование списка регистров для ModbusTCP master
Конфигурационные параметры задаются в секции <sensors> конфигурационного файла.
Список обрабатываемых регистров задаётся при помощи двух параметров командной строки
......@@ -207,8 +216,6 @@
регистры в устройство писатся не будут. Чтобы отключить это поведение, можно указать параметр
- \b tcp_sm_initOK - [0|1] Игнорировать начальную инициализацию из SM (сразу писать в устройство)
При этом будет записывыться значение "default".
\warning Регистр должен быть уникальным. И может повторятся только если указан параметр \a nbit или \a nbyte.
......@@ -228,10 +235,43 @@
Режимы переключаются при помощи датчика, который можно задать либо аргументом командной строки
\b --prefix-exchange-mode-id либо в конф. файле параметром \b exchangeModeID="". Константы определяющие режимы объявлены в MBTCPMultiMaster::ExchangeMode.
\section sec_MBTCPM_CheckConnection Проверка соединения
Для контроля состояния связи по "резервным" каналам создаётся специальный поток (check_thread), в котором
происходит периодическая проверка связи по всем "пассивным"(резервным) в данный момент каналам. Это используется
как для общей диагностики в системе, так и при выборе на какой канал переключаться в случае пропажи связи в основном канале.
Т.е. будет выбран ближайший приоритетный канал у которого выставлен признак что есть связь.
Период проверки связи по "резервным" каналам задаётся при помощи --prefix-checktime или параметром checktime="" в конфигурационном файле.
В MBTCPMultiMaster реализовано два механизма проверки связи.
- По умолчанию используется простая установка соединения и тут же его разрыв. Т.е. данные никакие не посылаются,
но проверяется что host и port доступны для подключения.
- Второй способ: это проверка соединения с посылкой modbus-запроса. Для этого имеется два способа
указать адрес устройства, регистр и функция опроса для проверки.
Либо в секции <GateList> для каждого канала можно указать:
- адрес устройства \b checkAddr=""
- функцию проверки \b checkFunc="" - функция может быть только [01,02,03,04] (т.е. функции чтения).
- регистр \b checkReg
Либо в командной строке \b задать параметры --prefix-check-addr, --prefix-check-func, --prefix-check-reg,
которые будут одинаковыми для \b ВСЕХ \b КАНАЛОВ.
Помимо этого если указать в командной строке аргумент --prefix-check-init-from-regmap, то для тестирования
соединения будет взят первый попавшийся регистр из списка обмена.
\warning Способ проверки при помощи "modbus-запроса" имеет ряд проблем: Если фактически производится
обмен с несколькими устройствами (несколько mbaddr) через TCP-шлюз, то может быть "ложное" срабатвание,
т.к. фактически состояние канала будет определяться только под связи с каким-то одним конкретным устройством.
И получается, что если обмен ведётся например с тремя устройствами, но
проверка канала происходит только по связи с первым, то если оно перестанет отвечать, это будет считаться
сбоем всего канала и этот канал будет исключён из обмена (!). Если ведётся обмен только с одним устройством,
такой проблеммы не возникает.
Но к плюсам данного способа проверки связи ("modbus-запросом") является то, что соедиенение поддерживается
постоянным, в отличие от "первого способа" при котором оно создаётся и сразу рвётся и если проверка
настроена достаточно часто ( < TIME_WAIT для сокетов), то при длительной работе могут закончится дескрипторы
на создание сокетов.
*/
// -----------------------------------------------------------------------------
/*!
\par Реализация Modbus TCP Multi Master для обмена с многими ModbusRTU устройствами
\par Реализация Modbus TCP MultiMaster для обмена с многими ModbusRTU устройствами
через один modbus tcp шлюз, доступный по нескольким ip-адресам.
\par Чтобы не зависеть от таймаутов TCP соединений, которые могут неопределённо зависать
......@@ -263,6 +303,7 @@ class MBTCPMultiMaster:
virtual std::shared_ptr<ModbusClient> initMB( bool reopen = false ) override;
virtual void sigterm( int signo ) override;
virtual bool deactivateObject() override;
void initCheckConnectionParameters();
void poll_thread();
void check_thread();
......@@ -288,6 +329,11 @@ class MBTCPMultiMaster:
std::shared_ptr<ModbusTCPMaster> mbtcp;
int priority;
// параметры для проверки соединения..
ModbusRTU::SlaveFunctionCode checkFunc = { ModbusRTU::fnUnknown };
ModbusRTU::ModbusAddr checkAddr = { 0x00 };
ModbusRTU::ModbusData checkReg = { 0 };
bool respond;
UniSetTypes::ObjectId respond_id;
IOController::IOStateList::iterator respond_it;
......@@ -297,18 +343,14 @@ class MBTCPMultiMaster:
DelayTimer respondDelay;
timeout_t channel_timeout = { 0 };
inline bool operator < ( const MBSlaveInfo& mbs ) const
inline bool operator < ( const MBSlaveInfo& mbs ) const noexcept
{
return priority < mbs.priority;
}
bool init( std::shared_ptr<DebugStream>& mblog );
bool check() const;
inline void setUse( bool st )
{
respond_init = !( st && !use );
use = st;
}
bool check();
void setUse( bool st );
timeout_t recv_timeout;
timeout_t aftersend_pause;
......@@ -323,9 +365,11 @@ class MBTCPMultiMaster:
PassiveTimer ptIgnoreTimeout;
const std::string getShortInfo() const;
std::mutex mutInit;
};
typedef std::list<MBSlaveInfo> MBGateList;
typedef std::list<std::shared_ptr<MBSlaveInfo>> MBGateList;
MBGateList mblist;
MBGateList::reverse_iterator mbi;
......
......@@ -4,7 +4,7 @@ MBPARAM=
for N in `seq 1 100`; do
MBPARAM="$MBPARAM --mbtcp${N}-name MBTCP${N} --mbtcp${N}-confnode MBPerfTestMaster --mbtcp${N}-filter-field mbperf
--mbtcp${N}-filter-value $N --mbtcp${N}-persistent-connection 1 --mbtcp${N}-log-add-levels crit,warn"
--mbtcp${N}-filter-value $N --mbtcp${N}-persistent-connection 1 --mbtcp${N}-check-init-from-regmap --mbtcp${N}-log-add-levels warn,crit"
done
#echo "$MBPARAM"
......
......@@ -14,6 +14,10 @@
--mbtcp-log-add-levels level4,warn,crit \
--mbtcp-persistent-connection 1 \
--mbtcp-run-logserver \
--mbtcpX-check-init-from-regmap \
--mbtcpX-check-addr 1 \
--mbtcpX-check-reg 66 \
--mbtcpX-check-func 1 \
$*
#--dlog-add-levels info,crit,warn,level4,level3,level9 \
......
......@@ -124,6 +124,47 @@ TEST_CASE("MBTCPMaster: reconnect", "[modbus][mbmaster][mbtcpmaster]")
REQUIRE_FALSE(mb.isConnection());
}
// -----------------------------------------------------------------------------
TEST_CASE("MBTCPMaster: forceDisconnect", "[modbus][mbmaster][mbtcpmaster][forceDisconnect]")
{
InitTest();
ModbusTCPMaster mb;
mb.setTimeout(500);
for( size_t i=0; i<1000; i++ )
{
// подключение к несуществующему адресу
REQUIRE_FALSE(mb.connect(iaddr, 2048));
try
{
mb.read03(slaveADDR,10,1);
}
catch(...){}
REQUIRE_FALSE(mb.isConnection());
mb.forceDisconnect();
}
}
// -----------------------------------------------------------------------------
TEST_CASE("MBTCPMaster: disconnect", "[modbus][mbmaster][mbtcpmaster][disconnect]")
{
InitTest();
ModbusTCPMaster mb;
mb.setTimeout(500);
mb.setForceDisconnect(true);
for( size_t i=0; i<1000; i++ )
{
// подключение к несуществующему адресу
REQUIRE_FALSE(mb.connect(iaddr, 2048));
try
{
mb.read03(slaveADDR,10,1);
}
catch(...){}
REQUIRE_FALSE(mb.isConnection());
mb.disconnect();
}
}
// -----------------------------------------------------------------------------
TEST_CASE("MBTCPMaster: 0x01 (read coil status)", "[modbus][0x01][mbmaster][mbtcpmaster]")
{
InitTest();
......
......@@ -337,7 +337,6 @@ class MBSlave:
VTypes::VType vtype; /*!< type of value */
size_t wnum; /*!< номер слова (для типов с размеров больше 2х байт */
size_t nbyte; /*!< номер байта, который надо "сохранить" из "пришедщего в запросе" слова. [1-2] */
bool rawdata; /*!< флаг, что в SM просто сохраняются 4-байта (актуально для типа F4)*/
std::shared_ptr<BitRegProperty> bitreg; /*!< указатель, как признак является ли данный регистр "сборным" из битовых */
ModbusRTU::RegID regID;
......@@ -347,7 +346,6 @@ class MBSlave:
vtype(VTypes::vtUnknown),
wnum(0),
nbyte(0),
rawdata(false),
regID(0)
{}
......
......@@ -54,6 +54,17 @@ RRDServer::RRDServer(UniSetTypes::ObjectId objId, xmlNode* cnode, UniSetTypes::O
for( ; it1.getCurrent(); it1++, ++tmID )
initRRD(it1, tmID);
if( smTestID == DefaultObjectId && !rrdlist.empty() )
{
// берём первый датчик из списка
const auto& lst = rrdlist.begin()->dslist;
if( !lst.empty() )
{
const auto& dsi = *(lst.begin());
smTestID = dsi->sid;
}
}
}
// -----------------------------------------------------------------------------
RRDServer::~RRDServer()
......@@ -268,6 +279,8 @@ void RRDServer::help_print( int argc, const char* const* argv )
cout << " set-levels ... " << endl;
cout << " logfile filanme " << endl;
cout << " no-debug " << endl;
cout << " Base oprtions: " << endl;
// cout << UObject_SK::help() << endl;
cout << " LogServer: " << endl;
cout << "--prefix-run-logserver - run logserver. Default: localhost:id" << endl;
cout << "--prefix-logserver-host ip - listen ip. Default: localhost" << endl;
......@@ -315,6 +328,9 @@ void RRDServer::askSensors( UniversalIO::UIOCommand cmd )
{
UObject_SK::askSensors(cmd);
// прежде чем заказывать датчики, надо убедиться что SM доступна
waitSM(smReadyTimeout);
for( auto& it : rrdlist )
{
for( auto& s : it.dsmap )
......
......@@ -69,8 +69,6 @@ SharedMemory::SharedMemory( ObjectId id, const std::string& datafile, const std:
msecPulsar(0),
confnode(0)
{
mutex_start.setName(myname + "_mutex_start");
auto conf = uniset_conf();
string cname(confname);
......@@ -155,7 +153,7 @@ SharedMemory::SharedMemory( ObjectId id, const std::string& datafile, const std:
evntPause = conf->getArgPInt("--e-startup-pause", 5000);
activateTimeout = conf->getArgPInt("--activate-timeout", 30000);
activateTimeout = conf->getArgPInt("--activate-timeout", 60000);
sidPulsar = DefaultObjectId;
string p = conf->getArgParam("--pulsar-id", it.getProp("pulsar_id"));
......@@ -197,17 +195,21 @@ SharedMemory::~SharedMemory()
void SharedMemory::timerInfo( const TimerMessage* tm )
{
if( tm->id == tmHeartBeatCheck )
{
checkHeartBeat();
}
else if( tm->id == tmEvent )
{
workready = 1;
workready = true;
// рассылаем уведомление, о том, чтобы стартанули
SystemMessage sm1(SystemMessage::WatchDog);
sendEvent(sm1);
askTimer(tm->id, 0);
}
else if( tm->id == tmHistory )
{
saveToHistory();
}
else if( tm->id == tmPulsar )
{
if( sidPulsar != DefaultObjectId )
......@@ -241,11 +243,14 @@ void SharedMemory::sysCommand( const SystemMessage* sm )
}
if( !activated )
smcrit << myname << "(sysCommand): ************* don`t activate?! ************" << endl;
{
smcrit << myname << "(sysCommand): Don`t activate! TERMINATE.." << endl;
std::terminate();
}
// подождать пока пройдёт инициализация
// см. activateObject()
UniSetTypes::uniset_rwmutex_rlock l(mutex_start);
std::unique_lock<std::mutex> lock(mutexStart);
askTimer(tmHeartBeatCheck, heartbeatCheckTime);
askTimer(tmEvent, evntPause, 1);
......@@ -294,7 +299,7 @@ bool SharedMemory::activateObject()
{
activated = false;
UniSetTypes::uniset_rwmutex_wrlock l(mutex_start);
std::unique_lock<std::mutex> lock(mutexStart);
res = IONotifyController::activateObject();
// инициализируем указатели
......@@ -328,6 +333,7 @@ bool SharedMemory::activateObject()
}
cout << myname << ": ********** activate: " << pt.getCurrent() << " msec " << endl;
sminfo << myname << ": ********** activate: " << pt.getCurrent() << " msec " << endl;
return res;
}
// ------------------------------------------------------------------------------------------
......
......@@ -201,7 +201,7 @@
<item default="1" id="104104" iotype="DI" name="_41_04_S">
<MessagesList>
<msg mtype="1" text="КСЭС: отключился ввод\вывод" value="0"/>
<msg mtype="1" text="КСЭС: отключился ввод/вывод" value="0"/>
</MessagesList>
</item>
\endcode
......@@ -417,7 +417,7 @@ class SharedMemory:
void buildEventList( xmlNode* cnode );
void readEventList( const std::string& oname );
UniSetTypes::uniset_rwmutex mutex_start;
std::mutex mutexStart;
class HeartBeatInfo
{
......
......@@ -99,9 +99,6 @@ int main( int argc, const char** argv )
ThreadCreator<IOControl>* io_thr = new ThreadCreator<IOControl>(ic.get(), &IOControl::execute);
if( io_thr == NULL )
return 1;
act->add(ic);
lst_iothr.push_back( io_thr );
}
......
......@@ -39,12 +39,12 @@ UNetSender::UNetSender(const std::string& _host, const int _port, const std::sha
sendpause(150),
packsendpause(5),
activated(false),
items(100),
packetnum(1),
lastcrc(0),
maxAData(maxACount),
maxDData(maxDCount)
{
items.reserve(100);
{
ostringstream s;
......
......@@ -77,8 +77,8 @@ class Calibration
{
public:
Calibration();
Calibration( const std::string& name, const std::string& confile = "calibration.xml" );
Calibration( xmlNode* node );
Calibration( const std::string& name, const std::string& confile = "calibration.xml", size_t reserv=50 );
Calibration( xmlNode* node, size_t reserv=50 );
~Calibration();
/*! Тип для хранения значения */
......@@ -96,26 +96,26 @@ class Calibration
\param crop_raw - обрезать переданное значение по крайним точкам
\return Возвращает калиброванное или outOfRange
*/
long getValue( long raw, bool crop_raw = false );
long getValue( const long raw, bool crop_raw = false );
/*! Возвращает минимальное значение 'x' встретившееся в диаграмме */
inline long getMinValue()
inline long getMinValue() const noexcept
{
return minVal;
}
/*! Возвращает максимальное значение 'x' втретившееся в диаграмме */
inline long getMaxValue()
inline long getMaxValue() const noexcept
{
return maxVal;
}
/*! Возвращает крайнее левое значение 'x' встретившееся в диаграмме (ПОСЛЕ СОРТИРОВКИ ПО ВОЗРАСТАНИЮ 'x'!) */
inline long getLeftValue()
inline long getLeftValue() const noexcept
{
return leftVal;
}
/*! Возвращает крайнее правое значение 'x' встретившееся в диаграмме (ПОСЛЕ СОРТИРОВКИ ПО ВОЗРАСТАНИЮ 'x'!) */
inline long getRightValue()
inline long getRightValue() const noexcept
{
return rightVal;
}
......@@ -127,26 +127,26 @@ class Calibration
Если range=false, то может быть возвращено значение outOfRange.
*/
long getRawValue( long cal, bool range = false );
long getRawValue( const long cal, bool range = false );
/*! Возвращает минимальное значение 'y' встретившееся в диаграмме */
inline long getMinRaw()
inline long getMinRaw() const noexcept
{
return minRaw;
}
/*! Возвращает максимальное значение 'y' встретившееся в диаграмме */
inline long getMaxRaw()
inline long getMaxRaw() const noexcept
{
return maxRaw;
}
/*! Возвращает крайнее левое значение 'y' встретившееся в диаграмме (ПОСЛЕ СОРТИРОВКИ ПО ВОЗРАСТАНИЮ 'x'!) */
inline long getLeftRaw()
inline long getLeftRaw() const noexcept
{
return leftRaw;
}
/*! Возвращает крайнее правое значение 'y' встретившееся в диаграмме (ПОСЛЕ СОРТИРОВКИ ПО ВОЗРАСТАНИЮ 'x'!) */
inline long getRightRaw()
inline long getRightRaw() const noexcept
{
return rightRaw;
}
......@@ -166,14 +166,15 @@ class Calibration
return lround(val);
}
void setCacheSize( unsigned int sz );
inline unsigned int getCacheSize()
void setCacheSize( size_t sz );
inline size_t getCacheSize() const
{
return cache.size();
}
void setCacheResortCycle( unsigned int n );
inline unsigned int getCacheResotrCycle()
void setCacheResortCycle( size_t n );
inline size_t getCacheResotrCycle() const noexcept
{
return numCacheResort;
}
......@@ -204,56 +205,56 @@ class Calibration
class Part
{
public:
Part();
Part( const Point& pleft, const Point& pright );
Part() noexcept;
Part( const Point& pleft, const Point& pright ) noexcept;
~Part() {};
/*! находится ли точка на данном участке */
bool check( const Point& p ) const;
bool check( const Point& p ) const noexcept;
/*! находится ли точка на данном участке по X */
bool checkX( const TypeOfValue& x ) const;
bool checkX( const TypeOfValue& x ) const noexcept;
/*! находится ли точка на данном участке по Y */
bool checkY( const TypeOfValue& y ) const;
bool checkY( const TypeOfValue& y ) const noexcept;
// функции могут вернуть OutOfRange
TypeOfValue getY( const TypeOfValue& x ) const; /*!< получить значение Y */
TypeOfValue getX( const TypeOfValue& y ) const; /*!< получить значение X */
TypeOfValue getY( const TypeOfValue& x ) const noexcept; /*!< получить значение Y */
TypeOfValue getX( const TypeOfValue& y ) const noexcept; /*!< получить значение X */
TypeOfValue calcY( const TypeOfValue& x ) const; /*!< расчитать значение для x */
TypeOfValue calcX( const TypeOfValue& y ) const; /*!< расчитать значение для y */
TypeOfValue calcY( const TypeOfValue& x ) const noexcept; /*!< расчитать значение для x */
TypeOfValue calcX( const TypeOfValue& y ) const noexcept; /*!< расчитать значение для y */
inline bool operator < ( const Part& p ) const
inline bool operator < ( const Part& p ) const noexcept
{
return (p_right < p.p_right);
}
inline Point leftPoint() const
inline Point leftPoint() const noexcept
{
return p_left;
}
inline Point rightPoint() const
inline Point rightPoint() const noexcept
{
return p_right;
}
inline TypeOfValue getK() const
inline TypeOfValue getK() const noexcept
{
return k; /*!< получить коэффициент наклона */
}
inline TypeOfValue left_x() const
inline TypeOfValue left_x() const noexcept
{
return p_left.x;
}
inline TypeOfValue left_y() const
inline TypeOfValue left_y() const noexcept
{
return p_left.y;
}
inline TypeOfValue right_x() const
inline TypeOfValue right_x() const noexcept
{
return p_right.x;
}
inline TypeOfValue right_y() const
inline TypeOfValue right_y() const noexcept
{
return p_right.y;
}
......@@ -283,19 +284,19 @@ class Calibration
std::string myname;
// Cache
unsigned int szCache;
size_t szCache;
struct CacheInfo
{
CacheInfo(): val(0), raw(outOfRange), cnt(0) {}
CacheInfo( const long r, const long v ): val(v), raw(r), cnt(0) {}
CacheInfo() noexcept: val(0), raw(outOfRange), cnt(0) {}
CacheInfo( const long r, const long v ) noexcept: val(v), raw(r), cnt(0) {}
long val;
long raw;
unsigned long cnt; // счётчик обращений
size_t cnt; // счётчик обращений
// сортируем в порядке убывания(!) обращений
// т.е. наиболее часто используемые (впереди)
inline bool operator<( const CacheInfo& r ) const
inline bool operator<( const CacheInfo& r ) const noexcept
{
if( r.raw == outOfRange )
return true;
......@@ -310,8 +311,8 @@ class Calibration
typedef std::deque<CacheInfo> ValueCache;
ValueCache cache;
unsigned long numCacheResort; // количество обращений, при которых происходит перестроение (сортировка) кэша..
unsigned long numCallToCache; // текущий счётчик обращений к кэшу
size_t numCacheResort; // количество обращений, при которых происходит перестроение (сортировка) кэша..
size_t numCallToCache; // текущий счётчик обращений к кэшу
};
// -----------------------------------------------------------------------------
#endif // Calibration_H_
......
......@@ -717,8 +717,8 @@ namespace MTR
return val;
}
unsigned short val;
float fval;
unsigned short val = { 0 };
float fval = { 0.0 };
};
std::ostream& operator<<(std::ostream& os, T16& t );
// --------------------------------------------------------------------------
......@@ -765,8 +765,8 @@ namespace MTR
return val;
}
signed short val;
float fval;
signed short val = { 0 };
float fval = { 0 };
};
std::ostream& operator<<(std::ostream& os, T17& t );
// --------------------------------------------------------------------------
......
......@@ -8,7 +8,7 @@
ВСЕ ВАШИ ИЗМЕНЕНИЯ БУДУТ ПОТЕРЯНЫ.
*/
// --------------------------------------------------------------------------
// generate timestamp: 2016-08-25+03:00
// generate timestamp: 2016-09-30+03:00
// -----------------------------------------------------------------------------
#ifndef UObject_SK_H_
#define UObject_SK_H_
......@@ -29,7 +29,7 @@ class UObject_SK:
public UniSetObject
{
public:
UObject_SK( UniSetTypes::ObjectId id, xmlNode* node = UniSetTypes::uniset_conf()->getNode("UObject"), const std::string& argprefix = "" );
UObject_SK( UniSetTypes::ObjectId id, xmlNode* node=UniSetTypes::uniset_conf()->getNode("UObject"), const std::string& argprefix="" );
UObject_SK();
virtual ~UObject_SK();
......@@ -41,62 +41,56 @@ class UObject_SK:
virtual UniSetTypes::SimpleInfo* getInfo( CORBA::Long userparam = 0 ) override;
virtual bool setMsg( UniSetTypes::ObjectId code, bool state = true );
virtual bool setMsg( UniSetTypes::ObjectId code, bool state = true ) noexcept;
inline std::shared_ptr<DebugStream> log()
{
return mylog;
}
inline std::shared_ptr<LogAgregator> logAgregator()
{
return loga;
}
inline std::shared_ptr<DebugStream> log() noexcept { return mylog; }
inline std::shared_ptr<LogAgregator> logAgregator() noexcept { return loga; }
void init_dlog( std::shared_ptr<DebugStream> d );
void init_dlog( std::shared_ptr<DebugStream> d ) noexcept;
// "синтаксический сахар"..для логов
#ifndef myinfo
#define myinfo if( log()->debugging(Debug::INFO) ) log()->info()
#endif
#ifndef mywarn
#define mywarn if( log()->debugging(Debug::WARN) ) log()->warn()
#endif
#ifndef mycrit
#define mycrit if( log()->debugging(Debug::CRIT) ) log()->crit()
#endif
#ifndef mylog1
#define mylog1 if( log()->debugging(Debug::LEVEL1) ) log()->level1()
#endif
#ifndef mylog2
#define mylog2 if( log()->debugging(Debug::LEVEL2) ) log()->level2()
#endif
#ifndef mylog3
#define mylog3 if( log()->debugging(Debug::LEVEL3) ) log()->level3()
#endif
#ifndef mylog4
#define mylog4 if( log()->debugging(Debug::LEVEL4) ) log()->level4()
#endif
#ifndef mylog5
#define mylog5 if( log()->debugging(Debug::LEVEL5) ) log()->level5()
#endif
#ifndef mylog6
#define mylog6 if( log()->debugging(Debug::LEVEL6) ) log()->level6()
#endif
#ifndef mylog7
#define mylog7 if( log()->debugging(Debug::LEVEL7) ) log()->level7()
#endif
#ifndef mylog8
#define mylog8 if( log()->debugging(Debug::LEVEL8) ) log()->level8()
#endif
#ifndef mylog9
#define mylog9 if( log()->debugging(Debug::LEVEL9) ) log()->level9()
#endif
#ifndef mylogany
#define mylogany log()->any()
#endif
#ifndef vmonit
#define vmonit( var ) vmon.add( #var, var )
#endif
#ifndef myinfo
#define myinfo if( log()->debugging(Debug::INFO) ) log()->info()
#endif
#ifndef mywarn
#define mywarn if( log()->debugging(Debug::WARN) ) log()->warn()
#endif
#ifndef mycrit
#define mycrit if( log()->debugging(Debug::CRIT) ) log()->crit()
#endif
#ifndef mylog1
#define mylog1 if( log()->debugging(Debug::LEVEL1) ) log()->level1()
#endif
#ifndef mylog2
#define mylog2 if( log()->debugging(Debug::LEVEL2) ) log()->level2()
#endif
#ifndef mylog3
#define mylog3 if( log()->debugging(Debug::LEVEL3) ) log()->level3()
#endif
#ifndef mylog4
#define mylog4 if( log()->debugging(Debug::LEVEL4) ) log()->level4()
#endif
#ifndef mylog5
#define mylog5 if( log()->debugging(Debug::LEVEL5) ) log()->level5()
#endif
#ifndef mylog6
#define mylog6 if( log()->debugging(Debug::LEVEL6) ) log()->level6()
#endif
#ifndef mylog7
#define mylog7 if( log()->debugging(Debug::LEVEL7) ) log()->level7()
#endif
#ifndef mylog8
#define mylog8 if( log()->debugging(Debug::LEVEL8) ) log()->level8()
#endif
#ifndef mylog9
#define mylog9 if( log()->debugging(Debug::LEVEL9) ) log()->level9()
#endif
#ifndef mylogany
#define mylogany log()->any()
#endif
#ifndef vmonit
#define vmonit( var ) vmon.add( #var, var )
#endif
// Вспомогательные функции для удобства логирования
// ------------------------------------------------------------
......@@ -113,21 +107,18 @@ class UObject_SK:
\param id - идентификатор датчика
\param showLinkName - TRUE - выводить SensorName, FALSE - не выводить
*/
std::string str( UniSetTypes::ObjectId id, bool showLinkName = true ) const;
std::string str( UniSetTypes::ObjectId id, bool showLinkName=true ) const;
/*! Вывод значения входа/выхода в формате: in_xxx(SensorName)=val
\param id - идентификатор датчика
\param showLinkName - TRUE - выводить SensorName, FALSE - не выводить
*/
std::string strval( UniSetTypes::ObjectId id, bool showLinkName = true ) const;
std::string strval( UniSetTypes::ObjectId id, bool showLinkName=true ) const;
/*! Вывод состояния внутренних переменных */
inline std::string dumpVars()
{
return std::move(vmon.pretty_str());
}
inline std::string dumpVars(){ return std::move(vmon.pretty_str()); }
// ------------------------------------------------------------
std::string help();
std::string help() noexcept;
......@@ -152,21 +143,21 @@ class UObject_SK:
// ---- end of protected variables ----
virtual void callback() override;
virtual void callback() noexcept override;
virtual void processingMessage( const UniSetTypes::VoidMessage* msg ) override;
virtual void sysCommand( const UniSetTypes::SystemMessage* sm ) {};
virtual void askSensors( UniversalIO::UIOCommand cmd ) {}
virtual void sensorInfo( const UniSetTypes::SensorMessage* sm ) override {}
virtual void timerInfo( const UniSetTypes::TimerMessage* tm ) override {}
virtual void sysCommand( const UniSetTypes::SystemMessage* sm ){};
virtual void askSensors( UniversalIO::UIOCommand cmd ){}
virtual void sensorInfo( const UniSetTypes::SensorMessage* sm ) override{}
virtual void timerInfo( const UniSetTypes::TimerMessage* tm ) override{}
virtual void sigterm( int signo ) override;
virtual bool activateObject() override;
virtual std::string getMonitInfo()
{
return ""; /*!< пользовательская информация выводимая в getInfo() */
}
virtual std::string getMonitInfo(){ return ""; } /*!< пользовательская информация выводимая в getInfo() */
// Выполнение очередного шага программы
virtual void step() {}
virtual void step(){}
void preAskSensors( UniversalIO::UIOCommand cmd );
void preSysCommand( const UniSetTypes::SystemMessage* sm );
virtual void testMode( bool state );
void updateOutputs( bool force );
......@@ -192,15 +183,9 @@ class UObject_SK:
xmlNode* confnode;
/*! получить числовое свойство из конф. файла по привязанной confnode */
int getIntProp(const std::string& name)
{
return UniSetTypes::uniset_conf()->getIntProp(confnode, name);
}
int getIntProp(const std::string& name) { return UniSetTypes::uniset_conf()->getIntProp(confnode, name); }
/*! получить текстовое свойство из конф. файла по привязанной confnode */
inline const std::string getProp(const std::string& name)
{
return UniSetTypes::uniset_conf()->getProp(confnode, name);
}
inline const std::string getProp(const std::string& name) { return UniSetTypes::uniset_conf()->getProp(confnode, name); }
timeout_t smReadyTimeout; /*!< время ожидания готовности SM */
std::atomic_bool activated;
......@@ -235,11 +220,9 @@ class UObject_SK:
// Используемые идентификаторы сообщений
// ------------ private функции ---------------
void updatePreviousValues();
void preAskSensors( UniversalIO::UIOCommand cmd );
void updatePreviousValues() noexcept;
void preSensorInfo( const UniSetTypes::SensorMessage* sm );
void preTimerInfo( const UniSetTypes::TimerMessage* tm );
void preSysCommand( const UniSetTypes::SystemMessage* sm );
void initFromSM();
void checkSensors();
// --------------------------------------------
......
......@@ -114,7 +114,7 @@ namespace VTypes
// ------------------------------------------
// конструкторы на разные случаи...
F2r() noexcept {}
F2r() noexcept { raw_backorder.val = 0; }
F2r( const float& f ) noexcept: F2(f)
{
......@@ -383,7 +383,7 @@ namespace VTypes
public I2
{
public:
I2r() noexcept {}
I2r() noexcept { raw_backorder.val = 0; }
I2r( const int v ) noexcept: I2(v)
{
......@@ -457,7 +457,7 @@ namespace VTypes
public U2
{
public:
U2r() noexcept {}
U2r() noexcept { raw_backorder.val = 0; }
U2r( int v ) noexcept: U2(v)
{
......
......@@ -29,23 +29,19 @@ using namespace UniSetTypes;
const Calibration::TypeOfValue Calibration::ValueOutOfRange = std::numeric_limits<Calibration::TypeOfValue>::max();
const long Calibration::outOfRange = std::numeric_limits<long>::max();
// ----------------------------------------------------------------------------
Calibration::Part::Part():
Calibration::Part::Part() noexcept:
k(0)
{
}
Calibration::Part::Part( const Point& pleft, const Point& pright ):
Calibration::Part::Part( const Point& pleft, const Point& pright ) noexcept:
p_left(pleft),
p_right(pright),
k(0)
{
if( p_right.x < p_left.x )
{
Point t(p_right);
p_right = p_left;
p_left = t;
}
std::swap(p_right,p_left);
// вычисление коэффициента наклона (один раз в конструкторе)
// k = (y2-y1)/(x2-x1)
......@@ -55,29 +51,28 @@ Calibration::Part::Part( const Point& pleft, const Point& pright ):
k = ( p_right.y - p_left.y ) / ( p_right.x - p_left.x );
}
// ----------------------------------------------------------------------------
bool Calibration::Part::check( const Point& p ) const
bool Calibration::Part::check( const Point& p ) const noexcept
{
return ( checkX(p.x) && checkY(p.y) );
}
bool Calibration::Part::checkX( const TypeOfValue& x ) const
// ----------------------------------------------------------------------------
bool Calibration::Part::checkX( const TypeOfValue& x ) const noexcept
{
if( x < p_left.x || x > p_right.x )
return false;
return true;
}
bool Calibration::Part::checkY( const TypeOfValue& y ) const
// ----------------------------------------------------------------------------
bool Calibration::Part::checkY( const TypeOfValue& y ) const noexcept
{
if( y < p_left.y || y > p_right.y )
return false;
return true;
}
// ----------------------------------------------------------------------------
Calibration::TypeOfValue Calibration::Part::getY( const TypeOfValue& x ) const
Calibration::TypeOfValue Calibration::Part::getY( const TypeOfValue& x ) const noexcept
{
if( !checkX(x) )
return Calibration::ValueOutOfRange;
......@@ -91,7 +86,7 @@ Calibration::TypeOfValue Calibration::Part::getY( const TypeOfValue& x ) const
return calcY(x);
}
// ----------------------------------------------------------------------------
Calibration::TypeOfValue Calibration::Part::getX( const TypeOfValue& y ) const
Calibration::TypeOfValue Calibration::Part::getX( const TypeOfValue& y ) const noexcept
{
if( !checkY(y) )
return Calibration::ValueOutOfRange;
......@@ -105,13 +100,13 @@ Calibration::TypeOfValue Calibration::Part::getX( const TypeOfValue& y ) const
return calcX(y);
}
// ----------------------------------------------------------------------------
Calibration::TypeOfValue Calibration::Part::calcY( const TypeOfValue& x ) const
Calibration::TypeOfValue Calibration::Part::calcY( const TypeOfValue& x ) const noexcept
{
// y = y0 + kx
return k * (x - p_left.x) + p_left.y;
}
// ----------------------------------------------------------------------------
Calibration::TypeOfValue Calibration::Part::calcX( const TypeOfValue& y ) const
Calibration::TypeOfValue Calibration::Part::calcX( const TypeOfValue& y ) const noexcept
{
// x = (y - y0) / k
if( k == 0 )
......@@ -123,7 +118,6 @@ Calibration::TypeOfValue Calibration::Part::calcX( const TypeOfValue& y ) const
Calibration::Calibration():
minRaw(0), maxRaw(0), minVal(0), maxVal(0), rightVal(0), leftVal(0), rightRaw(0), leftRaw(0),
pvec(50),
myname(""),
szCache(5),
numCacheResort(20),
......@@ -134,25 +128,26 @@ Calibration::Calibration():
// ----------------------------------------------------------------------------
Calibration::Calibration( const string& name, const string& confile ):
Calibration::Calibration( const string& name, const string& confile, size_t reserv ):
minRaw(0), maxRaw(0), minVal(0), maxVal(0), rightVal(0), leftVal(0), rightRaw(0), leftRaw(0),
pvec(50),
myname(name),
szCache(5),
numCacheResort(20),
numCallToCache(5)
{
pvec.reserve(reserv);
cache.assign(szCache, CacheInfo());
build(name, confile, 0);
}
// ----------------------------------------------------------------------------
Calibration::Calibration( xmlNode* node ):
minRaw(0), maxRaw(0), minVal(0), maxVal(0), rightVal(0), leftVal(0), rightRaw(0), leftRaw(0), pvec(100),
Calibration::Calibration(xmlNode* node , size_t reserv ):
minRaw(0), maxRaw(0), minVal(0), maxVal(0), rightVal(0), leftVal(0), rightRaw(0), leftRaw(0),
szCache(5),
numCacheResort(20),
numCallToCache(5)
{
pvec.reserve(reserv);
cache.assign(szCache, CacheInfo());
UniXML::iterator it(node);
myname = it.getProp("name");
......@@ -199,14 +194,13 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo
}
bool prev = false;
Point prev_point(0, 0);
unsigned int i = 0;
Point prev_point;
for(; it; it.goNext())
for(; it; it++ )
{
Point p(prev_point);
p.x = atof(it.getProp("x").c_str());
p.y = atof(it.getProp("y").c_str());
p.x = std::atof(it.getProp("x").c_str());
p.y = std::atof(it.getProp("y").c_str());
if( p.x == 0 || p.y == 0 )
{
......@@ -225,36 +219,28 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo
minVal = p.y;
if( prev )
{
Part pt(prev_point, p);
pvec[i++] = pt;
if( i >= pvec.size() )
pvec.resize(pvec.size() + 20);
}
pvec.emplace_back(prev_point, p);
else
prev = true;
prev_point = p;
}
pvec.resize(i); // приводим размер к фактическому..
pvec.shrink_to_fit();
std::sort(pvec.begin(), pvec.end());
if( !pvec.empty() )
{
auto beg = pvec.begin();
auto end = pvec.end();
auto end = --pvec.end();
if( pvec.size() > 0 )
{
leftRaw = beg->left_x();
leftVal = beg->left_y();
--end;
rightRaw = end->right_x();
rightVal = end->right_y();
}
}
catch( const Exception& ex )
catch( const UniSetTypes::Exception& ex )
{
dcrit << myname << "(Calibration::build): Failed open " << confile << endl;
throw;
......@@ -262,7 +248,7 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo
}
// ----------------------------------------------------------------------------
// рекурсивная функция поиска методом "половинного деления"
static Calibration::PartsVec::iterator find_range( long raw, Calibration::PartsVec::iterator beg,
static Calibration::PartsVec::iterator find_range( const long raw, Calibration::PartsVec::iterator beg,
Calibration::PartsVec::iterator end )
{
if( beg->checkX(raw) )
......@@ -282,7 +268,7 @@ static Calibration::PartsVec::iterator find_range( long raw, Calibration::PartsV
return it;
}
// ----------------------------------------------------------------------------
long Calibration::getValue( long raw, bool crop_raw )
long Calibration::getValue( const long raw, bool crop_raw )
{
// если x левее первого отрезка то берём первую точку...
if( raw < leftRaw )
......@@ -312,7 +298,7 @@ long Calibration::getValue( long raw, bool crop_raw )
}
}
auto fit = find_range(raw, pvec.begin(), pvec.end());
auto fit = find_range(raw, pvec.begin(), --pvec.end() );
if( fit == pvec.end() )
{
......@@ -338,13 +324,13 @@ long Calibration::getValue( long raw, bool crop_raw )
return outOfRange;
}
// ----------------------------------------------------------------------------
void Calibration::setCacheResortCycle( unsigned int n )
void Calibration::setCacheResortCycle( size_t n )
{
numCacheResort = n;
numCallToCache = n;
}
// ----------------------------------------------------------------------------
void Calibration::setCacheSize( unsigned int sz )
void Calibration::setCacheSize( size_t sz )
{
sort(cache.begin(), cache.end()); // в порядке уменьшения обращений (см. CacheInfo::operator< )
cache.resize(sz);
......@@ -358,7 +344,7 @@ void Calibration::insertToCache( const long raw, const long val )
sort(cache.begin(), cache.end()); // пересортируем в порядке уменьшения обращений (см. CacheInfo::operator< )
}
// ----------------------------------------------------------------------------
long Calibration::getRawValue( long cal, bool range )
long Calibration::getRawValue( const long cal, bool range )
{
for( auto& it : pvec )
{
......
......@@ -33,7 +33,6 @@ DigitalFilter::DigitalFilter( unsigned int bufsize, double T, double lsq,
S(0),
tmr(UniSetTimer::WaitUpTime),
maxsize(bufsize),
mvec(bufsize),
mvec_sorted(false),
w(bufsize),
lsparam(lsq),
......
......@@ -192,7 +192,9 @@ bool IOBase::check_front( bool val )
void IOBase::processingAsAI( IOBase* it, long val, const std::shared_ptr<SMInterface>& shm, bool force )
{
if( it->stype == UniversalIO::DI || it->stype == UniversalIO::DO )
val = (val ? 1.0 : 0.0);
{
val = (val ? 1 : 0);
}
else
{
// проверка на обрыв
......@@ -270,7 +272,7 @@ void IOBase::processingFasAI( IOBase* it, float fval, const std::shared_ptr<SMIn
long val = lroundf(fval);
if( it->stype == UniversalIO::DI || it->stype == UniversalIO::DO )
val = (fval != 0 ? 1.0 : 0.0);
val = (fval != 0 ? 1 : 0);
else
{
if( it->rawdata )
......
......@@ -74,7 +74,7 @@ using namespace UniSetTypes;
{ \
uwarn << "(" << __STRING(fname) << "): " << ex.err << endl; \
} \
catch( const Exception& ex ) \
catch( const UniSetTypes::Exception& ex ) \
{ \
uwarn << "(" << __STRING(fname) << "): " << ex << endl; \
} \
......
......@@ -11,7 +11,7 @@
ВСЕ ВАШИ ИЗМЕНЕНИЯ БУДУТ ПОТЕРЯНЫ.
*/
// --------------------------------------------------------------------------
// generate timestamp: 2016-08-25+03:00
// generate timestamp: 2016-09-30+03:00
// -----------------------------------------------------------------------------
#include <memory>
#include <iomanip>
......@@ -32,28 +32,28 @@ using namespace UniSetTypes;
// -----------------------------------------------------------------------------
UObject_SK::UObject_SK():
// Инициализация идентификаторов (имена берутся из конф. файла)
// Инициализация идентификаторов (имена берутся из конф. файла)
// Используемые идентификаторы сообщений (имена берутся из конф. файла)
// Используемые идентификаторы сообщений (имена берутся из конф. файла)
// variables (public and proteced)
// variables (public and proteced)
// ------------------
active(false),
// ------------------
active(false),
idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(0),
smReadyTimeout(0),
activated(false),
askPause(2000),
forceOut(false),
// private variables
idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(0),
smReadyTimeout(0),
activated(false),
askPause(2000),
forceOut(false),
// private variables
end_private(false)
end_private(false)
{
mycrit << "UObject: init failed!!!!!!!!!!!!!!!" << endl;
throw Exception( string(myname + ": init failed!!!") );
throw Exception( string(myname+": init failed!!!") );
}
// -----------------------------------------------------------------------------
// ( val, confval, default val )
......@@ -61,7 +61,6 @@ static const std::string init3_str( const std::string& s1, const std::string& s2
{
if( !s1.empty() )
return s1;
if( !s2.empty() )
return s2;
......@@ -75,41 +74,41 @@ static UniSetTypes::ObjectId init_node( xmlNode* cnode, const std::string& prop
auto conf = uniset_conf();
if( conf->getProp(cnode, prop).empty() )
if( conf->getProp(cnode,prop).empty() )
return conf->getLocalNode();
return conf->getNodeID(conf->getProp(cnode, prop));
return conf->getNodeID(conf->getProp(cnode,prop));
}
// -----------------------------------------------------------------------------
UObject_SK::UObject_SK( ObjectId id, xmlNode* cnode, const std::string& _argprefix ):
UniSetObject(id),
// Инициализация идентификаторов (имена берутся из конф. файла)
UniSetObject(id),
// Инициализация идентификаторов (имена берутся из конф. файла)
// Используемые идентификаторы сообщений (имена берутся из конф. файла)
// Используемые идентификаторы сообщений (имена берутся из конф. файла)
// variables
// variables
sleep_msec(150),
active(true),
argprefix( (_argprefix.empty() ? myname + "-" : _argprefix) ),
sleep_msec(150),
active(true),
argprefix( (_argprefix.empty() ? myname+"-" : _argprefix) ),
idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(cnode),
smReadyTimeout(0),
activated(false),
askPause(uniset_conf()->getPIntProp(cnode, "askPause", 2000)),
forceOut(false),
idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(cnode),
smReadyTimeout(0),
activated(false),
askPause(uniset_conf()->getPIntProp(cnode,"askPause",2000)),
forceOut(false),
end_private(false)
end_private(false)
{
auto conf = uniset_conf();
if( UniSetTypes::findArgParam("--print-id-list", uniset_conf()->getArgc(), uniset_conf()->getArgv()) != -1 )
if( UniSetTypes::findArgParam("--print-id-list",uniset_conf()->getArgc(),uniset_conf()->getArgv()) != -1 )
{
// abort();
// abort();
}
......@@ -125,10 +124,10 @@ UObject_SK::UObject_SK( ObjectId id, xmlNode* cnode, const std::string& _argpref
{
ostringstream s;
s << argprefix << "log";
conf->initLogStream(mylog, s.str());
conf->initLogStream(mylog,s.str());
}
loga = make_shared<LogAgregator>(myname + "-loga");
loga = make_shared<LogAgregator>(myname+"-loga");
loga->add(mylog);
loga->add(ulog());
......@@ -146,14 +145,12 @@ UObject_SK::UObject_SK( ObjectId id, xmlNode* cnode, const std::string& _argpref
logserv_port = conf->getArgPInt("--" + argprefix + "logserver-port", it.getProp("logserverPort"), getId());
}
forceOut = conf->getArgPInt("--" + argprefix + "force-out", it.getProp("forceOut"), false);
string heart = conf->getArgParam("--" + argprefix + "heartbeat-id", it.getProp("heartbeat_id"));
forceOut = conf->getArgPInt("--" + argprefix + "force-out",it.getProp("forceOut"),false);
string heart = conf->getArgParam("--" + argprefix + "heartbeat-id",it.getProp("heartbeat_id"));
if( !heart.empty() )
{
idHeartBeat = conf->getSensorID(heart);
if( idHeartBeat == DefaultObjectId )
{
ostringstream err;
......@@ -161,14 +158,13 @@ UObject_SK::UObject_SK( ObjectId id, xmlNode* cnode, const std::string& _argpref
throw SystemError(err.str());
}
int heartbeatTime = conf->getArgPInt("--" + argprefix + "heartbeat-time", it.getProp("heartbeatTime"), conf->getHeartBeatTime());
if( heartbeatTime > 0 )
int heartbeatTime = conf->getArgPInt("--" + argprefix + "heartbeat-time",it.getProp("heartbeatTime"),conf->getHeartBeatTime());
if( heartbeatTime>0 )
ptHeartBeat.setTiming(heartbeatTime);
else
ptHeartBeat.setTiming(UniSetTimer::WaitUpTime);
maxHeartBeat = conf->getArgPInt("--" + argprefix + "heartbeat-max", it.getProp("heartbeat_max"), 10);
maxHeartBeat = conf->getArgPInt("--" + argprefix + "heartbeat-max",it.getProp("heartbeat_max"), 10);
}
// Инициализация значений
......@@ -177,18 +173,16 @@ UObject_SK::UObject_SK( ObjectId id, xmlNode* cnode, const std::string& _argpref
si.id = UniSetTypes::DefaultObjectId;
si.node = conf->getLocalNode();
sleep_msec = conf->getArgPInt("--" + argprefix + "sleep-msec", "150", 150);
sleep_msec = conf->getArgPInt("--" + argprefix + "sleep-msec","150", 150);
string s_resetTime("");
if( s_resetTime.empty() )
s_resetTime = "500";
resetMsgTime = uni_atoi(init3_str(conf->getArgParam("--" + argprefix + "resetMsgTime"), conf->getProp(cnode, "resetMsgTime"), s_resetTime));
resetMsgTime = uni_atoi(init3_str(conf->getArgParam("--" + argprefix + "resetMsgTime"),conf->getProp(cnode,"resetMsgTime"),s_resetTime));
ptResetMsg.setTiming(resetMsgTime);
int sm_tout = conf->getArgInt("--" + argprefix + "sm-ready-timeout", "");
int sm_tout = conf->getArgInt("--" + argprefix + "sm-ready-timeout","");
if( sm_tout == 0 )
smReadyTimeout = 60000;
else if( sm_tout < 0 )
......@@ -196,7 +190,7 @@ UObject_SK::UObject_SK( ObjectId id, xmlNode* cnode, const std::string& _argpref
else
smReadyTimeout = sm_tout;
smTestID = conf->getSensorID(init3_str(conf->getArgParam("--" + argprefix + "sm-test-id"), conf->getProp(cnode, "smTestID"), ""));
smTestID = conf->getSensorID(init3_str(conf->getArgParam("--" + argprefix + "sm-test-id"),conf->getProp(cnode,"smTestID"),""));
if( smTestID == DefaultObjectId )
......@@ -219,6 +213,11 @@ UObject_SK::UObject_SK( ObjectId id, xmlNode* cnode, const std::string& _argpref
vmonit(maxHeartBeat);
vmonit(activateTimeout);
vmonit(smReadyTimeout);
// help надо выводить в конце, когда уже все переменные инициализированы по умолчанию
if( UniSetTypes::findArgParam("--" + argprefix + "help",uniset_conf()->getArgc(),uniset_conf()->getArgv()) != -1 )
cout << help() << endl;
}
// -----------------------------------------------------------------------------
......@@ -233,7 +232,7 @@ void UObject_SK::updateValues()
}
// -----------------------------------------------------------------------------
void UObject_SK::updatePreviousValues()
void UObject_SK::updatePreviousValues() noexcept
{
}
......@@ -243,7 +242,7 @@ void UObject_SK::checkSensors()
}
// -----------------------------------------------------------------------------
bool UObject_SK::setMsg( UniSetTypes::ObjectId _code, bool _state )
bool UObject_SK::setMsg( UniSetTypes::ObjectId _code, bool _state ) noexcept
{
if( _code == UniSetTypes::DefaultObjectId )
{
......@@ -269,7 +268,7 @@ bool UObject_SK::setMsg( UniSetTypes::ObjectId _code, bool _state )
void UObject_SK::resetMsg()
{
mylog8 << myname << "(resetMsg): reset messages.." << endl;
// reset messages
// reset messages
}
// -----------------------------------------------------------------------------
......@@ -307,23 +306,19 @@ std::string UObject_SK::dumpIO()
s << endl;
int n = 0;
for( const auto& e : v_in )
for( const auto& e: v_in )
{
s << e;
if( (n++) % 2 )
if( (n++)%2 )
s << std::endl;
}
s << endl;
n = 0;
for( const auto& e : v_out )
for( const auto& e: v_out )
{
s << e;
if( (n++) % 2 )
if( (n++)%2 )
s << std::endl;
}
......@@ -348,7 +343,7 @@ std::string UObject_SK::strval( UniSetTypes::ObjectId id, bool showLinkName ) c
// --------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------
void UObject_SK::init_dlog( std::shared_ptr<DebugStream> d )
void UObject_SK::init_dlog( std::shared_ptr<DebugStream> d ) noexcept
{
UObject_SK::mylog = d;
}
......@@ -375,9 +370,9 @@ void UObject_SK::processingMessage( const UniSetTypes::VoidMessage* _msg )
break;
}
}
catch( const Exception& ex )
catch( const std::exception& ex )
{
mycrit << myname << "(processingMessage): " << ex << endl;
mycrit << myname << "(processingMessage): " << ex.what() << endl;
}
}
// -----------------------------------------------------------------------------
......@@ -387,13 +382,11 @@ void UObject_SK::preSysCommand( const SystemMessage* _sm )
{
case SystemMessage::WatchDog:
myinfo << myname << "(preSysCommand): WatchDog" << endl;
if( !active || !ptStartUpTimeout.checkTime() )
{
mywarn << myname << "(preSysCommand): игнорируем WatchDog, потому-что только-что стартанули" << endl;
break;
}
case SystemMessage::StartUp:
{
if( !logserv_host.empty() && logserv_port != 0 && !logserv->isRunning() )
......@@ -426,12 +419,14 @@ void UObject_SK::preSysCommand( const SystemMessage* _sm )
// переоткрываем логи
mylogany << myname << "(preSysCommand): logRotate" << endl;
string fname( log()->getLogFile() );
if( !fname.empty() )
{
mylog->logFile(fname.c_str(), true);
mylog->logFile(fname.c_str(),true);
mylogany << myname << "(preSysCommand): ***************** mylog LOG ROTATE *****************" << endl;
}
if( logserv && !logserv_host.empty() && logserv_port != 0 )
logserv->check(true);
}
break;
......@@ -450,21 +445,28 @@ UniSetTypes::SimpleInfo* UObject_SK::getInfo( CORBA::Long userparam )
ostringstream inf;
inf << i->info << endl;
inf << "LogServer: " << logserv_host << ":" << logserv_port << endl;
if( logserv /* && userparam < 0 */ )
{
inf << "LogServer: " << logserv_host << ":" << logserv_port
<< ( logserv->isRunning() ? " [RUNNIG]" : " [FAILED]" ) << endl;
inf << " " << logserv->getShortInfo() << endl;
}
else
inf << "LogServer: NONE" << endl;
inf << dumpIO() << endl;
inf << endl;
auto timers = getTimersList();
inf << "Timers[" << timers.size() << "]:" << endl;
for( const auto& t : timers )
for( const auto& t: timers )
{
inf << " " << setw(15) << getTimerName(t.id) << "[" << t.id << "]: msec="
<< setw(6) << t.tmr.getInterval()
<< " timeleft=" << setw(6) << t.curTimeMS
<< " tick=" << setw(3) << ( t.curTick >= 0 ? t.curTick : -1 )
<< " tick=" << setw(3) << ( t.curTick>=0 ? t.curTick : -1 )
<< endl;
}
inf << endl;
inf << vmon.pretty_str() << endl;
inf << endl;
......@@ -518,7 +520,7 @@ void UObject_SK::waitSM( int wait_msec, ObjectId _testID )
<< " testID=" << _testID << endl;
// waitReady можно использовать т.к. датчик это по сути IONotifyController
if( !ui->waitReady(_testID, wait_msec) )
if( !ui->waitReady(_testID,wait_msec) )
{
ostringstream err;
err << myname
......@@ -526,14 +528,14 @@ void UObject_SK::waitSM( int wait_msec, ObjectId _testID )
<< wait_msec << " мсек";
mycrit << err.str() << endl;
// terminate();
// abort();
// terminate();
// abort();
raise(SIGTERM);
terminate();
// throw SystemError(err.str());
// throw SystemError(err.str());
}
if( !ui->waitWorking(_testID, wait_msec) )
if( !ui->waitWorking(_testID,wait_msec) )
{
ostringstream err;
err << myname
......@@ -541,16 +543,34 @@ void UObject_SK::waitSM( int wait_msec, ObjectId _testID )
<< wait_msec << " мсек";
mycrit << err.str() << endl;
// terminate();
// abort();
// terminate();
// abort();
raise(SIGTERM);
// throw SystemError(err.str());
// throw SystemError(err.str());
}
}
// ----------------------------------------------------------------------------
std::string UObject_SK::help()
std::string UObject_SK::help() noexcept
{
ostringstream s;
s << " ************* " << myname << " HELP:" << " ************* " << endl;
s << "Init default values: " << endl;
s << endl;
s << "--" << argprefix << "sm-ready-timeout msec - wait SM ready for ask sensors. Now: " << smReadyTimeout << endl;
s << "--" << argprefix << "sm-test-id msec sensor - sensor for test SM ready. Now: " << smTestID << endl;
s << "--" << argprefix << "sleep-msec msec - step period. Now: " << sleep_msec << endl;
s << "--" << argprefix << "activate-timeout msec - activate process timeout. Now: " << activateTimeout << endl;
s << "--" << argprefix << "startup-timeout msec - wait startup timeout. Now: " << ptStartUpTimeout.getInterval() << endl;
s << "--" << argprefix << "force-out [0|1] - 1 - save out-values in SM at each step. Now: " << forceOut << endl;
s << "--" << argprefix << "heartbeat-max num - max value for heartbeat counter. Now: " << maxHeartBeat << endl;
s << "--" << argprefix << "heartbeat-time msec - heartbeat periond. Now: " << ptHeartBeat.getInterval() << endl;
s << endl;
s << "--print-id-list - print ID list" << endl;
s << endl;
s << " ****************************************************************************************** " << endl;
return std::move(s.str());
......@@ -558,46 +578,43 @@ std::string UObject_SK::help()
// ----------------------------------------------------------------------------
// --------------------------------------------------------------------------
void UObject_SK::callback()
void UObject_SK::callback() noexcept
{
if( !active )
return;
try
{
// проверка таймеров
checkTimers(this);
if( resetMsgTime > 0 && trResetMsg.hi(ptResetMsg.checkTime()) )
if( resetMsgTime>0 && trResetMsg.hi(ptResetMsg.checkTime()) )
{
// cout << myname << ": ********* reset messages *********" << endl;
// cout << myname << ": ********* reset messages *********" << endl;
resetMsg();
}
// обработка сообщений (таймеров и т.п.)
for( unsigned int i = 0; i < 20; i++ )
for( unsigned int i=0; i<20; i++ )
{
auto m = receiveMessage();
if( !m )
break;
processingMessage(m.get());
updateOutputs(forceOut);
// updatePreviousValues();
// updatePreviousValues();
}
// Выполнение шага программы
step();
// "сердцебиение"
if( idHeartBeat != DefaultObjectId && ptHeartBeat.checkTime() )
if( idHeartBeat!=DefaultObjectId && ptHeartBeat.checkTime() )
{
try
{
ui->setValue(idHeartBeat, maxHeartBeat);
ui->setValue(idHeartBeat,maxHeartBeat);
ptHeartBeat.reset();
}
catch( const Exception& ex )
......@@ -619,7 +636,7 @@ void UObject_SK::callback()
mycrit << myname << "(execute): СORBA::SystemException: "
<< ex.NP_minorString() << endl;
}
catch( const std::exception& ex )
catch( const std::exception&ex )
{
mycrit << myname << "(execute): catch " << ex.what() << endl;
}
......@@ -637,7 +654,7 @@ void UObject_SK::setValue( UniSetTypes::ObjectId _sid, long _val )
ui->setValue(_sid, _val);
ui->setValue(_sid,_val);
}
// -----------------------------------------------------------------------------
void UObject_SK::updateOutputs( bool _force )
......@@ -659,7 +676,7 @@ void UObject_SK::initFromSM()
// -----------------------------------------------------------------------------
void UObject_SK::askSensor( UniSetTypes::ObjectId _sid, UniversalIO::UIOCommand _cmd, UniSetTypes::ObjectId _node )
{
ui->askRemoteSensor(_sid, _cmd, _node, getId());
ui->askRemoteSensor(_sid,_cmd,_node,getId());
}
// -----------------------------------------------------------------------------
long UObject_SK::getValue( UniSetTypes::ObjectId _sid )
......@@ -681,12 +698,10 @@ long UObject_SK::getValue( UniSetTypes::ObjectId _sid )
void UObject_SK::preAskSensors( UniversalIO::UIOCommand _cmd )
{
PassiveTimer ptAct(activateTimeout);
while( !activated && !ptAct.checkTime() )
{
cout << myname << "(preAskSensors): wait activate..." << endl;
msleep(300);
if( activated )
break;
}
......@@ -706,7 +721,7 @@ void UObject_SK::preAskSensors( UniversalIO::UIOCommand _cmd )
{
mycrit << myname << "(preAskSensors): " << ex << endl;
}
catch( const std::exception& ex )
catch( const std::exception&ex )
{
mycrit << myname << "(execute): catch " << ex.what() << endl;
}
......
......@@ -53,8 +53,8 @@ void TestProc::sysCommand( const UniSetTypes::SystemMessage* sm )
// -----------------------------------------------------------------------------
string TestProc::getMonitInfo()
{
int* p = 0;
(*p) = 10;
// int* p = 0;
// (*p) = 10;
return "";
}
......
......@@ -17,7 +17,7 @@
#ifndef LogServer_H_
#define LogServer_H_
// -------------------------------------------------------------------------
#include <list>
#include <vector>
#include <string>
#include <memory>
#include <unordered_map>
......@@ -87,8 +87,8 @@ class LogServer:
{
public:
LogServer( std::shared_ptr<DebugStream> log ) noexcept;
LogServer( std::shared_ptr<LogAgregator> log ) noexcept;
LogServer( std::shared_ptr<DebugStream> log );
LogServer( std::shared_ptr<LogAgregator> log );
virtual ~LogServer() noexcept;
inline void setCmdTimeout( timeout_t msec ) noexcept
......@@ -113,6 +113,8 @@ class LogServer:
return isrunning;
}
bool check( bool restart_if_fail = true );
void init( const std::string& prefix, xmlNode* cnode = 0 );
static std::string help_print( const std::string& prefix );
......@@ -120,7 +122,7 @@ class LogServer:
std::string getShortInfo();
protected:
LogServer() noexcept;
LogServer();
virtual void evprepare( const ev::loop_ref& loop ) override;
virtual void evfinish( const ev::loop_ref& loop ) override;
......@@ -136,16 +138,16 @@ class LogServer:
std::string onCommand( LogSession* s, LogServerTypes::Command cmd, const std::string& logname );
private:
typedef std::list< std::shared_ptr<LogSession> > SessionList;
SessionList slist;
size_t scount = { 0 };
UniSetTypes::uniset_rwmutex mutSList;
timeout_t timeout = { UniSetTimer::WaitUpTime };
timeout_t cmdTimeout = { 2000 };
Debug::type sessLogLevel = { Debug::NONE };
size_t sessMaxCount = { 10 };
typedef std::vector< std::shared_ptr<LogSession> > SessionList;
SessionList slist;
UniSetTypes::uniset_rwmutex mutSList;
DebugStream mylog;
ev::io io;
......
......@@ -77,6 +77,8 @@ class LogSession
std::string getShortInfo() noexcept;
std::string name() const noexcept;
protected:
// LogSession( ost::TCPSocket& server );
......
......@@ -180,8 +180,6 @@ class NCRestorer_XML:
std::string s_filterField;
std::string s_filterValue;
std::string c_filterField;
std::string c_filterValue;
std::string t_filterField;
std::string t_filterValue;
......
......@@ -93,7 +93,7 @@ class ThreadCreator:
typedef void(ThreadMaster::* Action)(void);
ThreadCreator( ThreadMaster* m, Action a );
~ThreadCreator();
virtual ~ThreadCreator();
inline Poco::Thread::TID getTID() const
{
......
......@@ -44,6 +44,7 @@ class UTCPStream:
bool isSetLinger() const;
void forceDisconnect(); // disconnect() без ожидания (с отключением SO_LINGER)
void disconnect();
// --------------------------------------------------------------------
int getSocket() const;
......
......@@ -178,7 +178,7 @@ class ModbusClient
/*! функция запрос-ответ */
virtual ModbusRTU::mbErrCode query( ModbusRTU::ModbusAddr addr, ModbusRTU::ModbusMessage& msg,
ModbusRTU::ModbusMessage& reply, timeout_t timeout ) = 0;
ModbusRTU::ModbusMessage& qreply, timeout_t timeout ) = 0;
// -------------------------------------
/*! посылка запроса */
......@@ -191,11 +191,6 @@ class ModbusClient
virtual ModbusRTU::mbErrCode recv_pdu( ModbusRTU::ModbusByte qfunc,
ModbusRTU::ModbusMessage& rbuf, timeout_t timeout );
ModbusRTU::ModbusMessage reply; /*!< буфер для приёма сообщений */
ModbusRTU::ModbusMessage qbuf; /*!< буфер для посылки сообщений */
timeout_t replyTimeOut_ms; /*!< таймаут на ожидание ответа */
timeout_t aftersend_msec; /*!< пауза после посылки запроса */
timeout_t sleepPause_usec; /*!< пауза между попытками чтения символа из канала */
......@@ -209,6 +204,9 @@ class ModbusClient
PassiveTimer tmProcessing;
private:
ModbusRTU::ModbusMessage qreply; /*!< буфер для приёма сообщений */
ModbusRTU::ModbusMessage qbuf; /*!< буфер для посылки сообщений */
};
// -------------------------------------------------------------------------
#endif // ModbusClient_H_
......
......@@ -150,6 +150,7 @@ namespace ModbusRTU
float dat2f( const ModbusData dat1, const ModbusData dat2 );
// -------------------------------------------------------------------------
bool isWriteFunction( SlaveFunctionCode c );
bool isReadFunction( SlaveFunctionCode c );
// -------------------------------------------------------------------------
/*! Заголовок сообщений */
struct ModbusHeader
......
......@@ -24,7 +24,7 @@
//---------------------------------------------------------------------------
using namespace std;
//---------------------------------------------------------------------------
static UInterface* ui = 0;
static UInterface* uInterface = 0;
//---------------------------------------------------------------------------
void pyUInterface::uniset_init_params( UTypes::Params* p, const std::string& xmlfile )throw(UException)
{
......@@ -37,7 +37,7 @@ void pyUInterface::uniset_init( int argc, char* argv[], const std::string& xmlfi
try
{
UniSetTypes::uniset_init(argc, argv, xmlfile);
ui = new UInterface();
uInterface = new UInterface();
return;
}
catch( UniSetTypes::Exception& ex )
......@@ -54,7 +54,7 @@ long pyUInterface::getValue( long id )throw(UException)
{
auto conf = UniSetTypes::uniset_conf();
if( !conf || !ui )
if( !conf || !uInterface )
throw USysError();
UniversalIO::IOType t = conf->getIOType(id);
......@@ -67,7 +67,7 @@ long pyUInterface::getValue( long id )throw(UException)
case UniversalIO::DO:
case UniversalIO::AI:
case UniversalIO::AO:
return ui->getValue(id);
return uInterface->getValue(id);
break;
default:
......@@ -96,7 +96,7 @@ void pyUInterface::setValue( long id, long val, long supplier )throw(UException)
{
auto conf = UniSetTypes::uniset_conf();
if( !conf || !ui )
if( !conf || !uInterface )
throw USysError();
UniversalIO::IOType t = conf->getIOType(id);
......@@ -109,7 +109,7 @@ void pyUInterface::setValue( long id, long val, long supplier )throw(UException)
case UniversalIO::DO:
case UniversalIO::AI:
case UniversalIO::AO:
ui->setValue(id, val, supplier);
uInterface->setValue(id, val, supplier);
break;
default:
......
......@@ -60,10 +60,10 @@ throw(ModbusRTU::mbException)
{
ReadCoilMessage msg(addr, start, count);
qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, reply, replyTimeOut_ms);
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError )
return ReadCoilRetMessage(reply);
return ReadCoilRetMessage(qreply);
throw mbException(res);
}
......@@ -74,10 +74,10 @@ throw(ModbusRTU::mbException)
{
ReadInputStatusMessage msg(addr, start, count);
qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, reply, replyTimeOut_ms);
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError )
return ReadInputStatusRetMessage(reply);
return ReadInputStatusRetMessage(qreply);
throw mbException(res);
}
......@@ -90,10 +90,10 @@ throw(ModbusRTU::mbException)
ReadOutputMessage msg(addr, start, count);
qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, reply, replyTimeOut_ms);
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError )
return ReadOutputRetMessage(reply);
return ReadOutputRetMessage(qreply);
throw mbException(res);
}
......@@ -104,10 +104,10 @@ throw(ModbusRTU::mbException)
{
ReadInputMessage msg(addr, start, count);
qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, reply, replyTimeOut_ms);
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError )
return ReadInputRetMessage(reply);
return ReadInputRetMessage(qreply);
throw mbException(res);
}
......@@ -119,10 +119,10 @@ throw(ModbusRTU::mbException)
ForceSingleCoilMessage msg(addr, start, cmd);
qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, reply, replyTimeOut_ms);
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError )
return ForceSingleCoilRetMessage(reply);
return ForceSingleCoilRetMessage(qreply);
throw mbException(res);
}
......@@ -135,10 +135,10 @@ throw(ModbusRTU::mbException)
WriteSingleOutputMessage msg(addr, start, data);
qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, reply, replyTimeOut_ms);
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError )
return WriteSingleOutputRetMessage(reply);
return WriteSingleOutputRetMessage(qreply);
throw mbException(res);
}
......@@ -147,10 +147,10 @@ ForceCoilsRetMessage ModbusClient::write0F( ForceCoilsMessage& msg )
throw(ModbusRTU::mbException)
{
qbuf = msg.transport_msg();
mbErrCode res = query(msg.addr, qbuf, reply, replyTimeOut_ms);
mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError )
return ForceCoilsRetMessage(reply);
return ForceCoilsRetMessage(qreply);
throw mbException(res);
}
......@@ -160,10 +160,10 @@ WriteOutputRetMessage ModbusClient::write10( WriteOutputMessage& msg )
throw(ModbusRTU::mbException)
{
qbuf = msg.transport_msg();
mbErrCode res = query(msg.addr, qbuf, reply, replyTimeOut_ms);
mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError )
return WriteOutputRetMessage(reply);
return WriteOutputRetMessage(qreply);
throw mbException(res);
}
......@@ -175,10 +175,10 @@ throw(ModbusRTU::mbException)
{
DiagnosticMessage msg(addr, subfunc, dat);
qbuf = msg.transport_msg();
mbErrCode res = query(msg.addr, qbuf, reply, replyTimeOut_ms);
mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError )
return DiagnosticRetMessage(reply);
return DiagnosticRetMessage(qreply);
throw mbException(res);
}
......@@ -190,10 +190,10 @@ throw(ModbusRTU::mbException)
{
MEIMessageRDI msg(addr, devID, objID);
qbuf = msg.transport_msg();
mbErrCode res = query(msg.addr, qbuf, reply, replyTimeOut_ms);
mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError )
return MEIMessageRetRDI(reply);
return MEIMessageRetRDI(qreply);
throw mbException(res);
}
......@@ -213,10 +213,10 @@ throw(ModbusRTU::mbException)
msg.century = century;
qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, reply, replyTimeOut_ms);
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError )
return SetDateTimeRetMessage(reply);
return SetDateTimeRetMessage(qreply);
throw mbException(res);
}
......@@ -320,10 +320,10 @@ throw(ModbusRTU::mbException)
FileTransferMessage msg(addr, idFile, numpack);
qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, reply, part_timeout_msec);
mbErrCode res = query(addr, qbuf, qreply, part_timeout_msec);
if( res == erNoError )
return FileTransferRetMessage(reply);
return FileTransferRetMessage(qreply);
throw mbException(res);
}
......
......@@ -39,9 +39,6 @@ size_t ModbusTCPCore::readNextData(UTCPStream* tcp,
char* buf = new char[max];
if( buf == 0 )
return 0;
try
{
ssize_t l = tcp->receiveBytes(buf, max);
......@@ -114,11 +111,19 @@ size_t ModbusTCPCore::getNextData(UTCPStream* tcp,
if( len <= 0 )
len = 7;
try
{
size_t ret = ModbusTCPCore::readNextData(tcp, qrecv, len);
if( ret == 0 )
return 0;
}
catch( UniSetTypes::CommFailed& ex )
{
if( qrecv.empty() )
return 0;
}
}
size_t i = 0;
......@@ -141,9 +146,6 @@ size_t ModbusTCPCore::readDataFD( int fd, std::queue<unsigned char>& qrecv, size
char* buf = new char[max];
if( buf == 0 )
return 0;
ssize_t l = 0;
size_t cnt = 0;
......@@ -209,11 +211,19 @@ size_t ModbusTCPCore::getDataFD( int fd, std::queue<unsigned char>& qrecv,
if( len == 0 )
len = 7;
try
{
size_t ret = ModbusTCPCore::readDataFD(fd, qrecv, len, attempts);
if( ret == 0 && qrecv.empty() )
return 0;
}
catch( UniSetTypes::CommFailed& ex )
{
if( qrecv.empty() )
return 0;
}
}
size_t i = 0;
......
......@@ -59,7 +59,7 @@ void ModbusTCPMaster::setChannelTimeout( timeout_t msec )
Poco::Timespan tm = UniSetTimer::millisecToPoco(msec);
Poco::Timespan old = tcp->getReceiveTimeout();;
if( old.microseconds() == tm.microseconds() )
if( old.totalMicroseconds() == tm.totalMicroseconds() )
return;
tcp->setReceiveTimeout(tm);
......@@ -201,6 +201,7 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
}
cleanInputStream();
if( tcp )
tcp->forceDisconnect();
return erTimeOut; // return erHardwareError;
}
......@@ -247,12 +248,13 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
if( force_disconnect )
{
if( dlog->is_info() )
dlog->info() << "(query): force disconnect.." << endl;
dlog->info() << "(query): disconnect.." << endl;
// при штатном обмене..лучше дождаться конца "посылки"..
// поэтому применяем disconnect(), а не forceDisconnect()
// (с учётом выставленной опции setLinger(true))
tcp->close();
if( tcp )
tcp->disconnect();
}
return res;
......@@ -267,6 +269,7 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
dlog->info() << "(query): force disconnect.." << endl;
// cleanInputStream();
if( tcp )
tcp->forceDisconnect();
}
......@@ -303,7 +306,7 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
catch( const std::exception& e )
{
if( dlog->is_warn() )
dlog->crit() << "(query): " << e.what() << std::endl;
dlog->warn() << "(query): " << e.what() << std::endl;
}
return erTimeOut; // erHardwareError
......@@ -385,7 +388,7 @@ bool ModbusTCPMaster::connect( const std::string& addr, int _port, bool closeOld
{
ostringstream s;
s << "(ModbusTCPMaster): connect " << iaddr << ":" << port << " error: " << e.what();
dlog->crit() << iaddr << std::endl;
dlog->crit() << s.str() << std::endl;
}
}
......@@ -426,13 +429,22 @@ bool ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port,
tcp->setNoDelay(true);
return true;
}
catch( Poco::TimeoutException& ex)
{
if( dlog->debugging(Debug::CRIT) )
{
ostringstream s;
s << "(ModbusTCPMaster): create connection " << iaddr << ":" << port << " timeout exception";
dlog->crit() << s.str() << std::endl;
}
}
catch( Poco::Net::NetException& ex)
{
if( dlog->debugging(Debug::CRIT) )
{
ostringstream s;
s << "(ModbusTCPMaster): create connection " << iaddr << ":" << port << " error: " << ex.displayText();
dlog->crit() << iaddr << std::endl;
dlog->crit() << s.str() << std::endl;
}
}
catch( const std::exception& e )
......@@ -441,7 +453,7 @@ bool ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port,
{
ostringstream s;
s << "(ModbusTCPMaster): connection " << iaddr << ":" << port << " error: " << e.what();
dlog->crit() << iaddr << std::endl;
dlog->crit() << s.str() << std::endl;
}
}
catch( ... )
......@@ -466,7 +478,7 @@ void ModbusTCPMaster::disconnect()
if( !tcp )
return;
tcp->close();
tcp->disconnect(); // close();
tcp = nullptr;
}
// -------------------------------------------------------------------------
......
......@@ -194,6 +194,18 @@ bool ModbusRTU::isWriteFunction( SlaveFunctionCode c )
return false;
}
// -------------------------------------------------------------------------
bool ModbusRTU::isReadFunction( SlaveFunctionCode c )
{
if( c == fnReadCoilStatus ||
c == fnReadInputStatus ||
c == fnReadOutputRegisters ||
c == fnReadInputRegisters )
return true;
return false;
}
// -------------------------------------------------------------------------
std::ostream& ModbusRTU::mbPrintMessage( std::ostream& os, ModbusByte* m, size_t len )
{
// Чтобы не менять настройки 'os'
......
......@@ -14,10 +14,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// -----------------------------------------------------------------------------
#include <functional>
#include <sstream>
#include <cstdlib>
#include "UniSetTypes.h"
#include "PassiveTimer.h"
#include "ThreadCreator.h"
#include "TCPCheck.h"
#include "UTCPStream.h"
// -----------------------------------------------------------------------------
......@@ -76,11 +78,38 @@ void TCPCheck::check_thread()
t.create(ip, port, tout_msec);
t.setKeepAliveParams( (tout_msec > 1000 ? tout_msec / 1000 : 1) );
setResult(true);
t.close();
t.disconnect();
}
catch( ... ) {}
}
// -----------------------------------------------------------------------------
template<typename T>
class TGuard
{
public:
TGuard( T* m, typename ThreadCreator<T>::Action a ):
t(m,a)
{
t.start();
}
~TGuard()
{
if( t.isRunning() )
t.stop();
}
inline bool isRunning()
{
return t.isRunning();
}
protected:
ThreadCreator<T> t;
};
// -----------------------------------------------------------------------------
bool TCPCheck::ping( const std::string& _ip, timeout_t tout, timeout_t sleep_msec, const std::string& _ping_args )
{
ip = _ip;
......@@ -89,17 +118,13 @@ bool TCPCheck::ping( const std::string& _ip, timeout_t tout, timeout_t sleep_mse
setResult(false);
ThreadCreator<TCPCheck> t(this, &TCPCheck::ping_thread);
t.start();
TGuard<TCPCheck> t(this, &TCPCheck::ping_thread);
PassiveTimer pt(tout);
while( !pt.checkTime() && t.isRunning() )
msleep(sleep_msec);
if( t.isRunning() ) // !getResult() )
t.stop();
return result;
}
// -----------------------------------------------------------------------------
......
......@@ -5,7 +5,11 @@ using namespace std;
// -------------------------------------------------------------------------
USocket::~USocket()
{
try
{
close();
}
catch(...){}
}
// -------------------------------------------------------------------------
USocket::USocket( int sock )
......
......@@ -12,7 +12,11 @@ using namespace std;
// -------------------------------------------------------------------------
UTCPSocket::~UTCPSocket()
{
try
{
Poco::Net::ServerSocket::close();
}
catch(...){}
}
// -------------------------------------------------------------------------
UTCPSocket::UTCPSocket()
......
......@@ -57,20 +57,40 @@ bool UTCPStream::isSetLinger() const
// -------------------------------------------------------------------------
void UTCPStream::forceDisconnect()
{
if( !isConnected() )
return;
try
{
bool on;
int sec;
Poco::Net::StreamSocket::getLinger(on, sec);
setLinger(false, 0);
}
// catch( Poco::Net::NetException& ex ){}
catch( std::exception& ex ){}
try
{
close();
//shutdown();
Poco::Net::StreamSocket::setLinger(on, sec);
}
catch( Poco::Net::NetException& )
// catch( Poco::Net::NetException& ex ){}
catch( std::exception& ex ){}
}
// -------------------------------------------------------------------------
void UTCPStream::disconnect()
{
try
{
shutdown();
}
// catch( Poco::Net::NetException& ex ){}
catch( std::exception& ex ){}
try
{
close();
}
// catch( Poco::Net::NetException& ex ){}
catch( std::exception& ex ){}
}
// -------------------------------------------------------------------------
int UTCPStream::getSocket() const
......@@ -81,13 +101,13 @@ int UTCPStream::getSocket() const
timeout_t UTCPStream::getTimeout() const
{
auto tm = Poco::Net::StreamSocket::getReceiveTimeout();
return tm.microseconds();
return tm.totalMicroseconds();
}
// -------------------------------------------------------------------------
void UTCPStream::create(const std::string& hname, int port, timeout_t tout_msec )
void UTCPStream::create( const std::string& hname, int port, timeout_t tout_msec )
{
Poco::Net::SocketAddress sa(hname, port);
connect(sa, tout_msec * 1000);
Poco::Net::SocketAddress saddr(hname, port);
connect(saddr, UniSetTimer::millisecToPoco(tout_msec));
setKeepAlive(true);
Poco::Net::StreamSocket::setLinger(true, 1);
setKeepAliveParams();
......@@ -95,7 +115,7 @@ void UTCPStream::create(const std::string& hname, int port, timeout_t tout_msec
// -------------------------------------------------------------------------
bool UTCPStream::isConnected() noexcept
{
return ( Poco::Net::StreamSocket::sockfd() > 0 );
return ( Poco::Net::StreamSocket::sockfd() != POCO_INVALID_SOCKET );
/*
try
{
......
......@@ -920,8 +920,8 @@ throw(ResolveNameError, UniSetTypes::TimeOut )
catch(const CosNaming::NamingContext::NotFound& nf) {}
catch(const CosNaming::NamingContext::InvalidName& nf) {}
catch(const CosNaming::NamingContext::CannotProceed& cp) {}
catch( const Exception ) {}
catch( const CORBA::OBJECT_NOT_EXIST )
catch( const UniSetTypes::Exception& ex ) {}
catch( const CORBA::OBJECT_NOT_EXIST& ex )
{
throw UniSetTypes::ResolveNameError("ObjectNOTExist");
}
......
......@@ -59,8 +59,8 @@ static const int numErrorTags = sizeof(errorTags) / sizeof(error_item);
Debug::type const Debug::ANY = Debug::type(
Debug::INFO | Debug::INIT | Debug::WARN | Debug::CRIT |
Debug::LEVEL1 | Debug::LEVEL2 | Debug::LEVEL3 | Debug::LEVEL4 |
Debug::LEVEL5 | Debug::LEVEL5 | Debug::LEVEL6 | Debug::LEVEL7 |
Debug::LEVEL8 | Debug::LEVEL9 | Debug::REPOSITORY | Debug::SYSTEM |
Debug::LEVEL5 | Debug::LEVEL6 | Debug::LEVEL7 | Debug::LEVEL8 |
Debug::LEVEL9 | Debug::REPOSITORY | Debug::SYSTEM |
Debug::EXCEPTION );
......@@ -124,7 +124,11 @@ void Debug::showTags(ostream& os) noexcept
<< setw(10) << errorTags[i].name
<< " " << errorTags[i].desc << '\n';
try
{
os.flush();
}
catch(...){}
}
std::ostream& operator<<(std::ostream& os, Debug::type level ) noexcept
......@@ -166,7 +170,13 @@ std::string Debug::str( Debug::type level ) noexcept
}
}
try
{
return s.str();
}
catch(...){}
return "";
}
......
......@@ -132,8 +132,7 @@ void LogReader::disconnect()
try
{
//tcp->shutdown();
tcp->close();
tcp->disconnect();
}
catch( const Poco::Net::NetException& e )
{
......@@ -181,7 +180,7 @@ void LogReader::sendCommand(const std::string& _addr, int _port, std::vector<Com
msg.data = c.data;
msg.setLogName(c.logfilter);
unsigned int n = 2; // две попытки на посылку
size_t n = 2; // две попытки на посылку
while( n > 0 )
{
......@@ -245,7 +244,7 @@ void LogReader::sendCommand(const std::string& _addr, int _port, std::vector<Com
// теперь ждём ответ..
try
{
int a = 2;
size_t a = 2;
while( a > 0 && tcp->poll(UniSetTimer::millisecToPoco(reply_timeout), Poco::Net::Socket::SELECT_READ) )
{
......
......@@ -39,28 +39,41 @@ LogServer::~LogServer() noexcept
catch(...){}
}
// -------------------------------------------------------------------------
LogServer::LogServer( std::shared_ptr<LogAgregator> log ) noexcept:
LogServer(static_pointer_cast<DebugStream>(log))
LogServer::LogServer( std::shared_ptr<LogAgregator> log ):
LogServer()
{
elog = dynamic_pointer_cast<DebugStream>(log);
if( !elog )
{
ostringstream err;
err << myname << "(LogServer): dynamic_pointer_cast FAILED! ";
if( mylog.is_info() )
mylog.info() << myname << "(evfinish): terminate..." << endl;
if( mylog.is_crit() )
mylog.crit() << err.str() << endl;
cerr << err.str() << endl;
throw SystemError(err.str());
}
}
// -------------------------------------------------------------------------
LogServer::LogServer( std::shared_ptr<DebugStream> log ) noexcept:
timeout(UniSetTimer::WaitUpTime),
cmdTimeout(2000),
sessLogLevel(Debug::NONE),
sock(0),
elog(log)
LogServer::LogServer( std::shared_ptr<DebugStream> log ):
LogServer()
{
elog = log;
}
// -------------------------------------------------------------------------
LogServer::LogServer() noexcept:
LogServer::LogServer():
timeout(UniSetTimer::WaitUpTime),
cmdTimeout(2000),
sessLogLevel(Debug::NONE),
sock(0),
elog(nullptr)
{
slist.reserve(sessMaxCount);
}
// -------------------------------------------------------------------------
void LogServer::evfinish( const ev::loop_ref& loop )
......@@ -115,6 +128,45 @@ void LogServer::terminate()
loop.evstop(this);
}
// -------------------------------------------------------------------------
bool LogServer::check( bool restart_if_fail )
{
try
{
// для проверки пробуем открыть соединение..
UTCPSocket s(addr, port);
s.close();
return true;
}
catch(...){}
if( !restart_if_fail )
return false;
if( !sock )
return false;
io.stop();
io.set<LogServer, &LogServer::ioAccept>(this);
io.start(sock->getSocket(), ev::READ);
try
{
UTCPSocket s(addr, port);
s.close();
return true;
}
catch( Poco::Net::NetException& ex )
{
ostringstream err;
err << myname << "(check): socket error:" << ex.message();
if( mylog.is_crit() )
mylog.crit() << err.str() << endl;
}
return false;
}
// -------------------------------------------------------------------------
void LogServer::evprepare( const ev::loop_ref& eloop )
{
if( sock )
......@@ -146,8 +198,8 @@ void LogServer::evprepare( const ev::loop_ref& eloop )
sock->setBlocking(false);
io.set<LogServer, &LogServer::ioAccept>(this);
io.set( eloop );
io.set<LogServer, &LogServer::ioAccept>(this);
io.start(sock->getSocket(), ev::READ);
isrunning = true;
}
......@@ -172,9 +224,9 @@ void LogServer::ioAccept( ev::io& watcher, int revents )
}
{
uniset_rwmutex_wrlock l(mutSList);
uniset_rwmutex_rlock l(mutSList);
if( scount >= sessMaxCount )
if( slist.size() >= sessMaxCount )
{
if( mylog.is_crit() )
mylog.crit() << myname << "(LogServer::ioAccept): session limit(" << sessMaxCount << ")" << endl;
......@@ -194,13 +246,10 @@ void LogServer::ioAccept( ev::io& watcher, int revents )
s->signal_logsession_command().connect( sigc::mem_fun(this, &LogServer::onCommand) );
{
uniset_rwmutex_wrlock l(mutSList);
scount++;
slist.push_back(s);
// на первой сессии запоминаем состояние логов
if( scount == 1 )
if( slist.size() == 1 )
saveDefaultLogLevels("ALL");
slist.push_back(s);
}
s->run(watcher.loop);
......@@ -220,14 +269,12 @@ void LogServer::sessionFinished( LogSession* s )
if( i->get() == s )
{
slist.erase(i);
scount--;
break;
}
}
if( slist.empty() )
{
scount = 0;
// восстанавливаем уровни логов по умолчанию
restoreDefaultLogLevels("ALL");
}
......@@ -255,9 +302,14 @@ string LogServer::getShortInfo()
{
ostringstream inf;
inf << "LogServer: " << myname << endl;
inf << "LogServer: " << myname
<< " ["
<< " sessMaxCount=" << sessMaxCount
<< " ]"
<< endl;
{
uniset_rwmutex_wrlock l(mutSList);
uniset_rwmutex_rlock l(mutSList);
for( const auto& s : slist )
inf << " " << s->getShortInfo() << endl;
......
......@@ -74,7 +74,7 @@ LogSession::LogSession( const Poco::Net::StreamSocket& s, std::shared_ptr<DebugS
if( iaddr.host().toString().empty() )
{
ostringstream err;
err << "(ModbusTCPSession): unknonwn ip(0.0.0.0) client disconnected?!";
err << "(LogSession): unknonwn ip(0.0.0.0) client disconnected?!";
if( mylog.is_crit() )
mylog.crit() << err.str() << endl;
......@@ -107,7 +107,7 @@ LogSession::LogSession( const Poco::Net::StreamSocket& s, std::shared_ptr<DebugS
if( log )
conn = log->signal_stream_event().connect( sigc::mem_fun(this, &LogSession::logOnEvent) );
else
mylog.crit() << "LOG NULL!!" << endl;
mylog.crit() << "(LogSession): LOG NULL!!" << endl;
}
// -------------------------------------------------------------------------
void LogSession::logOnEvent( const std::string& s ) noexcept
......@@ -137,11 +137,19 @@ void LogSession::logOnEvent( const std::string& s ) noexcept
if( logbuf.size() >= maxRecordsNum )
{
numLostMsg++;
if( numLostMsg > maxRecordsNum )
{
// видимо клиент отвалился или совсем не успевает читать
// разрываем сессию..
if( mylog.is_info() )
mylog.info() << peername << "(LogSession::onEvent): too many lost messages. Close session.." << endl;
cancelled = true;
}
if( !lostMsg )
{
ostringstream err;
err << "The buffer is full. Message is lost...(size of buffer " << maxRecordsNum << ")" << endl;
err << "(LogSession): The buffer is full. Message is lost...(size of buffer " << maxRecordsNum << ")" << endl;
logbuf.emplace(new UTCPCore::Buffer(std::move(err.str())));
lostMsg = true;
}
......@@ -163,7 +171,7 @@ void LogSession::run( const ev::loop_ref& loop ) noexcept
setSessionLogLevel(Debug::ANY);
if( mylog.is_info() )
mylog.info() << peername << "(run): run session.." << endl;
mylog.info() << peername << "(LogSession::run): run session.." << endl;
asyncEvent.set(loop);
cmdTimer.set(loop);
......@@ -178,7 +186,7 @@ void LogSession::run( const ev::loop_ref& loop ) noexcept
void LogSession::terminate()
{
if( mylog.is_info() )
mylog.info() << peername << "(terminate)..." << endl;
mylog.info() << peername << "(LogSession::terminate)..." << endl;
cancelled = true;
......@@ -196,6 +204,7 @@ void LogSession::terminate()
logbuf.pop();
}
sock->disconnect();
sock->close();
final();
}
......@@ -205,7 +214,7 @@ void LogSession::event( ev::async& watcher, int revents ) noexcept
if( EV_ERROR & revents )
{
if( mylog.is_crit() )
mylog.crit() << peername << "(event): EVENT ERROR.." << endl;
mylog.crit() << peername << "(LogSession::event): EVENT ERROR.." << endl;
return;
}
......@@ -218,7 +227,7 @@ void LogSession::callback( ev::io& watcher, int revents ) noexcept
if( EV_ERROR & revents )
{
if( mylog.is_crit() )
mylog.crit() << peername << "(callback): EVENT ERROR.." << endl;
mylog.crit() << peername << "(LogSession::callback): EVENT ERROR.." << endl;
return;
}
......@@ -241,10 +250,10 @@ void LogSession::callback( ev::io& watcher, int revents ) noexcept
catch(...){}
}
if( cancelled )
if( cancelled.load() )
{
if( mylog.is_info() )
mylog.info() << peername << ": stop session... disconnect.." << endl;
mylog.info() << peername << "LogSession: stop session... disconnect.." << endl;
io.stop();
cmdTimer.stop();
......@@ -262,7 +271,7 @@ void LogSession::callback( ev::io& watcher, int revents ) noexcept
// -------------------------------------------------------------------------
void LogSession::writeEvent( ev::io& watcher )
{
if( cancelled )
if( cancelled.load() )
return;
UTCPCore::Buffer* buffer = 0;
......@@ -283,17 +292,17 @@ void LogSession::writeEvent( ev::io& watcher )
if( !buffer )
return;
ssize_t ret = write(watcher.fd, buffer->dpos(), buffer->nbytes());
ssize_t ret = ::write(watcher.fd, buffer->dpos(), buffer->nbytes());
if( ret < 0 )
{
if( mylog.is_warn() )
mylog.warn() << peername << "(writeEvent): write to socket error(" << errno << "): " << strerror(errno) << endl;
mylog.warn() << peername << "(LogSession::writeEvent): write to socket error(" << errno << "): " << strerror(errno) << endl;
if( errno == EPIPE )
if( errno == EPIPE || errno == EBADF )
{
if( mylog.is_warn() )
mylog.warn() << peername << "(writeEvent): write error.. terminate session.." << endl;
mylog.warn() << peername << "(LogSession::writeEvent): write error.. terminate session.." << endl;
cancelled = true;
}
......@@ -344,7 +353,7 @@ size_t LogSession::readData( unsigned char* buf, int len )
if( res < 0 )
{
if( errno != EAGAIN && mylog.is_warn() )
mylog.warn() << peername << "(readData): read from socket error(" << errno << "): " << strerror(errno) << endl;
mylog.warn() << peername << "(LogSession::readData): read from socket error(" << errno << "): " << strerror(errno) << endl;
return 0;
}
......@@ -362,7 +371,7 @@ size_t LogSession::readData( unsigned char* buf, int len )
}
mylog.info() << peername << "(readData): client disconnected.." << endl;
mylog.info() << peername << "(LogSession::readData): client disconnected.." << endl;
cancelled = true;
return 0;
}
......@@ -382,13 +391,13 @@ void LogSession::readEvent( ev::io& watcher ) noexcept
if( ret != sizeof(msg) || msg.magic != LogServerTypes::MAGICNUM )
{
if( mylog.is_warn() )
mylog.warn() << peername << "(readEvent): BAD MESSAGE..." << endl;
mylog.warn() << peername << "(LogSession::readEvent): BAD MESSAGE..." << endl;
return;
}
if( mylog.is_info() )
mylog.info() << peername << "(readEvent): receive command: '" << msg.cmd << "'" << endl;
mylog.info() << peername << "(LogSession::readEvent): receive command: '" << msg.cmd << "'" << endl;
string cmdLogName(msg.logname);
......@@ -399,7 +408,7 @@ void LogSession::readEvent( ev::io& watcher ) noexcept
catch( std::exception& ex )
{
if( mylog.is_warn() )
mylog.warn() << peername << "(readEvent): " << ex.what() << endl;
mylog.warn() << peername << "(LogSession::readEvent): " << ex.what() << endl;
}
catch(...){}
......@@ -550,7 +559,7 @@ void LogSession::cmdProcessing( const string& cmdLogName, const LogServerTypes::
catch( std::exception& ex )
{
if( mylog.is_warn() )
mylog.warn() << peername << "(cmdProcessing): " << ex.what() << endl;
mylog.warn() << peername << "(LogSession::cmdProcessing): " << ex.what() << endl;
}
}
// -------------------------------------------------------------------------
......@@ -559,7 +568,7 @@ void LogSession::onCmdTimeout( ev::timer& watcher, int revents ) noexcept
if( EV_ERROR & revents )
{
if( mylog.is_crit() )
mylog.crit() << peername << "(onCmdTimeout): EVENT ERROR.." << endl;
mylog.crit() << peername << "(LogSession::onCmdTimeout): EVENT ERROR.." << endl;
return;
}
......@@ -573,7 +582,7 @@ void LogSession::onCheckConnectionTimer( ev::timer& watcher, int revents ) noexc
if( EV_ERROR & revents )
{
if( mylog.is_crit() )
mylog.crit() << peername << "(onCheckConnectionTimer): EVENT ERROR.." << endl;
mylog.crit() << peername << "(LogSession::onCheckConnectionTimer): EVENT ERROR.." << endl;
return;
}
......@@ -588,10 +597,12 @@ void LogSession::onCheckConnectionTimer( ev::timer& watcher, int revents ) noexc
// если клиент уже отвалился.. то при попытке write.. сессия будет закрыта.
// длинное сообщение ("keep alive message") забивает логи, что потом неудобно смотреть, поэтому пишем "пустоту"
// длинное сообщение ("keep alive message") забивает логи, что потом неудобно смотреть
// поэтому используем "пробел и возврат на один символ"
try
{
logbuf.emplace(new UTCPCore::Buffer(""));
//
logbuf.emplace(new UTCPCore::Buffer(" \b"));
}
catch(...){}
......@@ -649,7 +660,7 @@ string LogSession::getShortInfo() noexcept
ostringstream inf;
inf << "client: " << caddr << endl
inf << "client: " << caddr << " :"
<< " buffer[" << maxRecordsNum << "]: size=" << sz
<< " maxCount=" << maxCount
<< " minSizeMsg=" << minSizeMsg
......@@ -660,3 +671,8 @@ string LogSession::getShortInfo() noexcept
return std::move(inf.str());
}
// ---------------------------------------------------------------------
string LogSession::name() const noexcept
{
return caddr;
}
// ---------------------------------------------------------------------
......@@ -24,9 +24,10 @@
using namespace UniSetTypes;
using namespace std;
// -----------------------------------------------------------------------------------------
ObjectIndex_XML::ObjectIndex_XML(const string& xmlfile, size_t minSize ):
omap(minSize)
ObjectIndex_XML::ObjectIndex_XML(const string& xmlfile, size_t minSize )
{
omap.reserve(minSize);
shared_ptr<UniXML> xml = make_shared<UniXML>();
// try
// {
......@@ -36,9 +37,9 @@ ObjectIndex_XML::ObjectIndex_XML(const string& xmlfile, size_t minSize ):
// catch(...){}
}
// -----------------------------------------------------------------------------------------
ObjectIndex_XML::ObjectIndex_XML(const std::shared_ptr<UniXML>& xml, size_t minSize ):
omap(minSize)
ObjectIndex_XML::ObjectIndex_XML(const std::shared_ptr<UniXML>& xml, size_t minSize )
{
omap.reserve(minSize);
build(xml);
}
// -----------------------------------------------------------------------------------------
......@@ -111,6 +112,7 @@ void ObjectIndex_XML::build( const std::shared_ptr<UniXML>& xml )
//
omap.resize(ind);
omap.shrink_to_fit();
// omap[ind].repName=NULL;
// omap[ind].textName=NULL;
// omap[ind].id = ind;
......@@ -199,7 +201,7 @@ size_t ObjectIndex_XML::read_section( const std::shared_ptr<UniXML>& xml, const
// cout << "read: " << "(" << ind << ") " << omap[ind].repName << "\t" << omap[ind].textName << endl;
ind++;
if( (unsigned)ind >= omap.size() )
if( ind >= omap.size() )
{
uinfo << "(ObjectIndex_XML::build): не хватило размера массива maxSize=" << omap.size()
<< "... Делаем resize + 100" << endl;
......
......@@ -343,6 +343,8 @@ void UniSetManager::objects(OManagerCommand cmd)
{
ucrit << myname << "(objects): " << ex << endl;
ucrit << myname << "(objects): не смог зарегистрировать (разрегистрировать) объект -->" << li->getName() << endl;
if( cmd == activ )
std::terminate();
}
catch( const CORBA::SystemException& ex )
{
......@@ -360,6 +362,9 @@ void UniSetManager::objects(OManagerCommand cmd)
ucrit << myname << "(objects): file: " << fe.file()
<< " line: " << fe.line()
<< " mesg: " << fe.errmsg() << endl;
if( cmd == activ )
std::terminate();
}
}
} // unlock
......
......@@ -32,8 +32,6 @@ using namespace UniSetTypes;
NCRestorer_XML::NCRestorer_XML( const string& fname ):
s_filterField(""),
s_filterValue(""),
c_filterField(""),
c_filterValue(""),
t_filterField(""),
t_filterValue(""),
fname(fname),
......@@ -47,8 +45,6 @@ NCRestorer_XML::NCRestorer_XML(const string& fname,
const std::string& f_value):
s_filterField(f_field),
s_filterValue(f_value),
c_filterField(""),
c_filterValue(""),
t_filterField(""),
t_filterValue(""),
fname(fname),
......
......@@ -3,6 +3,7 @@
#include <memory>
#include <sstream>
#include <thread>
#include <future>
#include "Mutex.h"
#include "UniSetTypes.h"
......@@ -47,8 +48,10 @@ void la_logOnEvent( const std::string& s )
la_msg << s;
}
// --------------------------------------------------------------------------
void readlog_thread1()
bool readlog_thread1()
{
try
{
LogReader lr;
lr.setinTimeout(readTimeout);
lr.signal_stream_event().connect( sigc::ptr_fun(rlog1OnEvent) );
......@@ -57,10 +60,20 @@ void readlog_thread1()
while( !g_read_cancel )
lr.readlogs(ip, port); // ,LogServerTypes::cmdNOP,0,"",true);
return true;
}
catch( std::exception& ex )
{
}
return false;
}
// --------------------------------------------------------------------------
void readlog_thread2()
bool readlog_thread2()
{
try
{
LogReader lr;
lr.setinTimeout(readTimeout);
lr.signal_stream_event().connect( sigc::ptr_fun(rlog2OnEvent) );
......@@ -69,6 +82,13 @@ void readlog_thread2()
while( !g_read_cancel )
lr.readlogs(ip, port); // ,LogServerTypes::cmdNOP,0,"",true);
return true;
}
catch( std::exception& ex )
{
}
return false;
}
// --------------------------------------------------------------------------
TEST_CASE("LogAgregator", "[LogServer][LogAgregator]" )
......@@ -133,7 +153,7 @@ TEST_CASE("LogServer", "[LogServer]" )
REQUIRE( ls.isRunning() );
msg.str("");
auto r_thr = make_shared<std::thread>(readlog_thread1);
auto ret = std::async(std::launch::async, readlog_thread1); // make_shared<std::thread>(readlog_thread1);
msleep(100); // небольшая пауза на создание потока и т.п.
......@@ -168,10 +188,7 @@ TEST_CASE("LogServer", "[LogServer]" )
}
g_read_cancel = true;
msleep(readTimeout);
if( r_thr->joinable() )
r_thr->join();
ret.get();
}
// --------------------------------------------------------------------------
TEST_CASE("MaxSessions", "[LogServer]" )
......@@ -205,11 +222,11 @@ TEST_CASE("MaxSessions", "[LogServer]" )
msg.str("");
msg2.str("");
auto r1_thr = make_shared<std::thread>(readlog_thread1);
auto ret1 = std::async(std::launch::async, readlog_thread1); // make_shared<std::thread>(readlog_thread1);
msleep(500); // пауза чтобы первый заведомо успел подключиться раньше второго..
auto r2_thr = make_shared<std::thread>(readlog_thread2);
auto ret2 = std::async(std::launch::async, readlog_thread1); // make_shared<std::thread>(readlog_thread2);
msleep(100); // небольшая пауза на создание потока и т.п.
......@@ -240,13 +257,8 @@ TEST_CASE("MaxSessions", "[LogServer]" )
}
g_read_cancel = true;
msleep(readTimeout);
if( r1_thr->joinable() )
r1_thr->join();
if( r2_thr->joinable() )
r2_thr->join();
ret1.get();
ret2.get();
}
// --------------------------------------------------------------------------
TEST_CASE("LogAgregator regexp", "[LogAgregator]" )
......
......@@ -16,6 +16,8 @@ static atomic_bool cancel = {false};
// --------------------------------------------------------
bool run_test_server()
{
try
{
UTCPSocket sock(host, port);
while( !cancel )
......@@ -27,6 +29,10 @@ bool run_test_server()
}
return true;
}
catch(...){}
return false;
}
// --------------------------------------------------------
// вспомогательный класс для гарантированного завершения потока..
......
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