diff --git a/MAC/APL/CURTDBDaemons/configure.in b/MAC/APL/CURTDBDaemons/configure.in index 8198e766261ab6f52671d8d2626ed0f548042cf3..cc2de7502754ea2c58927298629cb2f4653ae13e 100644 --- a/MAC/APL/CURTDBDaemons/configure.in +++ b/MAC/APL/CURTDBDaemons/configure.in @@ -61,8 +61,7 @@ lofar_INTERNAL(MAC/GCF/GCFCommon, gcfcommon, , 1, GCF/GCF_Defines.h,,) lofar_INTERNAL(MAC/GCF/TM, gcftm, , 1, GCF/TM/GCF_Task.h,,) lofar_INTERNAL(MAC/APL/APLCommon, aplcommon, , 1, APL/APLCommon/APL_Defines.h,,) lofar_INTERNAL(MAC/GCF/RTDB, rtdb, , 1, GCF/RTDB/RTDB_PropertySet.h,,) -lofar_INTERNAL(MAC/APL/CUDaemons, log_protocol, , 1, APL/CUDaemons/Log_Protocol.ph,,) -lofar_INTERNAL(MAC/APL/RTCCommon, rtccommon, , 1, APL/RTCCommon/Marshalling.h,,) +lofar_INTERNAL(MAC/APL/APLProtocol, , , 1, APL/APLProtocol/LOG_Protocol.ph,,) dnl dnl Output Makefiles @@ -71,6 +70,7 @@ AC_OUTPUT( src/Makefile test/Makefile src/LoggingProcessor/Makefile +src/KeyValueLogger/Makefile Makefile CURTDBDaemons.spec ) diff --git a/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLogger.cc b/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLogger.cc new file mode 100644 index 0000000000000000000000000000000000000000..d38a624585ee9bd50f4ac5c12489e03982d1409a --- /dev/null +++ b/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLogger.cc @@ -0,0 +1,305 @@ +//# KeyValueLogger.cc: Filters and stores logmessages in PVSS +//# +//# Copyright (C) 2007 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#include <lofar_config.h> +#include <Common/LofarLogger.h> +#include <APS/ParameterSet.h> +#include <GCF/GCF_PVTypes.h> +#include <GCF/GCF_ServiceInfo.h> +#include <GCF/PVSS/PVSSresult.h> +#include <GCF/RTDB/DP_Protocol.ph> +#include <APL/APLProtocol/KVT_Protocol.ph> +#include "KeyValueLogger.h" + +namespace LOFAR { + namespace GCF { + using namespace Common; + using namespace TM; + using namespace RTDB; + namespace RTDBDaemons { + +// +// CodeloggingProcessor() +// +KeyValueLogger::KeyValueLogger(const string& myName) : + GCFTask((State)&KeyValueLogger::initial, myName), + itsListener (0), + itsDPservice(0), + itsTimerPort(0) +{ + LOG_DEBUG_STR("KeyValueLogger(" << myName << ")"); + + registerProtocol(F_FSM_PROTOCOL, F_FSM_PROTOCOL_STRINGS); + registerProtocol(DP_PROTOCOL, DP_PROTOCOL_STRINGS); + registerProtocol(KVT_PROTOCOL, KVT_PROTOCOL_STRINGS); + + // initialize the ports + itsListener = new GCFTCPPort(*this, MAC_SVCMASK_KVTLOGGER, GCFPortInterface::MSPP, KVT_PROTOCOL); + ASSERTSTR(itsListener, "Can't allocate a listener port"); + + itsDPservice = new DPservice(this); + ASSERTSTR(itsDPservice, "Can't allocate DataPoint service"); + + itsTimerPort = new GCFTimerPort(*this, "timerPort"); + ASSERTSTR(itsTimerPort, "Can't allocate timer"); +} + +// +// ~CodeloggingProcessor() +// +KeyValueLogger::~KeyValueLogger() +{ + LOG_DEBUG_STR("~KeyValueLogger()"); + + if (itsTimerPort) { + delete itsTimerPort; + } + if (itsDPservice) { + delete itsDPservice; + } + if (itsListener) { + delete itsListener; + } +} + +// +// initial(event, port) +// +// Try to open our listener socket +// +GCFEvent::TResult KeyValueLogger::initial(GCFEvent& event, GCFPortInterface& port) +{ + GCFEvent::TResult status = GCFEvent::HANDLED; + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: + case F_TIMER: + if (!itsListener->isConnected()) { + itsListener->open(); + } + break; + + case F_CONNECTED: + // Listener is opened, go to operational state. + TRAN(KeyValueLogger::operational); + break; + + case F_DISCONNECTED: + port.setTimer(5.0); // try again after 5 second + break; + + default: + status = GCFEvent::NOT_HANDLED; + break; + } + + return (status); +} + +// +// operational(event, port) +// +GCFEvent::TResult KeyValueLogger::operational(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR("operational:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + static unsigned long garbageTimerID = 0; + + switch (event.signal) { + case F_ENTRY: + garbageTimerID = itsTimerPort->setTimer(1.0, 5.0); + break; + + // Catch incoming connections of new clients + case F_ACCEPT_REQ: { + GCFTCPPort* client(new GCFTCPPort); + if (!client) { + LOG_ERROR("Can't allocate new socket for new client"); + return (status); + } + if (&port == itsListener) { + client->init(*this, "application", GCFPortInterface::SPP, KVT_PROTOCOL); + itsListener->accept(*client); + } + } + break; + + case F_CONNECTED: + break; + + case F_DISCONNECTED: { + ASSERTSTR(itsListener != &port, "Lost listener-port, bailing out"); + LogClientMap::iterator iter = itsClients.find(&port); + if (iter == itsClients.end()) { + LOG_INFO("Connection lost to a not-registered LofarLogger client."); + } + else { + if (iter->second.valid) { + LOG_INFO_STR("Closing log-stream to " << iter->second.name << ", passed " + << iter->second.msgCnt << " messages to the database"); + } + else if (!iter->second.name.empty()) { + LOG_INFO_STR("Closing log-stream to " << iter->second.name); + } + else { + LOG_INFO("Closing unknown log-stream"); + } + } + port.close(); + } + break; + + case F_CLOSED: + itsClients.erase(&port); + itsClientsGarbage.push_back(&port); + break; + + case F_TIMER: { + // cleanup the garbage of closed ports to master clients + GCFPortInterface* pPort; + for (TClients::iterator iter = itsClientsGarbage.begin(); + iter != itsClientsGarbage.end(); ++iter) { + pPort = *iter; + delete pPort; + } + itsClientsGarbage.clear(); + } + break; + + case KVT_REGISTER: { + KVTRegisterEvent registerEvent(event); + _registerClient(port, registerEvent.name, registerEvent.obsID); + + KVTRegisterAckEvent answer; + answer.obsID = registerEvent.obsID; + answer.name = registerEvent.name; + port.send(answer); + } + break; + + case KVT_SEND_MSG: { + KVTSendMsgEvent logEvent(event); + KVTSendMsgAckEvent answer; + answer.seqnr = logEvent.seqnr; + answer.result = PVSS::SA_NO_ERROR; + + int32 timeStamp = ACC::APS::indexValue(logEvent.key, "{}"); + rtrim (logEvent.key, "{}01234565789"); // cut off timestamp + replace(logEvent.key.begin(), logEvent.key.end(), '.', '_'); + PVSSresult result = itsDPservice->setValue(logEvent.key, + GCFPVString(logEvent.value), + 1.0 * timeStamp); + itsClients[&port].msgCnt++; + + switch (result) { + case PVSS::SA_NO_ERROR: + break; + case PVSS::SA_SCADA_NOT_AVAILABLE: + answer.result = result; + break; + default: + // _registerFailure(port); + answer.result = result; + } + port.send(answer); + } + break; + + case KVT_SEND_MSG_POOL: { + KVTSendMsgPoolEvent logEvent(event); + KVTSendMsgPoolAckEvent answer; + answer.seqnr = logEvent.seqnr; + answer.result = PVSS::SA_NO_ERROR; + for (uint32 i = 0; i < logEvent.msgCount; i++) { + PVSSresult result; +// = itsDPservice->setValue(logEvent.keys.theVector[i], +// GCFPVString(logEvent.values.theVector[i])); + switch (result) { + case PVSS::SA_NO_ERROR: + break; + case PVSS::SA_SCADA_NOT_AVAILABLE: + answer.result = result; + i = logEvent.msgCount; // don't try the others. + break; + default: + // _registerFailure(port); + answer.result |= result; + } // switch + } // for + port.send(answer); + } + break; + + default: + status = GCFEvent::NOT_HANDLED; + break; + } + + return (status); +} + +// +// _registerClient(port, name) +// +void KeyValueLogger::_registerClient(GCFPortInterface& port, + const string& name, + uint32 obsID) +{ + LogClientMap::iterator iter = itsClients.find(&port); + if (iter != itsClients.end()) { + LOG_WARN_STR("Client " << name << "is already registered"); + return; + } + + itsClients[&port] = LogClient(name, obsID); + itsClients[&port].obsID = obsID; + itsClients[&port].msgCnt = 0; + itsClients[&port].valid = true; + LOG_INFO_STR("Starting KVT stream for " << name); + + return; +} + +// +// _registerFailure(port) +// +void KeyValueLogger::_registerFailure(GCFPortInterface& port) +{ + LogClientMap::iterator iter = itsClients.find(&port); + if (iter == itsClients.end()) { + return; + } + + if (++(iter->second.errCnt) > 10) { + iter->second.valid = false; + LOG_INFO_STR("Log-stream to " << iter->second.name << " keeps reporting errors, ignoring stream"); + } +} + + + } // namespace RTDBDaemons + } // namespace GCF +} // namespace LOFAR diff --git a/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLogger.conf b/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLogger.conf new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLogger.h b/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLogger.h new file mode 100644 index 0000000000000000000000000000000000000000..a634ce432695fe4932e707c6d1ab8ad5179ec66c --- /dev/null +++ b/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLogger.h @@ -0,0 +1,88 @@ +//# KeyValueLogger.h: +//# +//# Copyright (C) 2007 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#ifndef KEYVALUELOGGER_H +#define KEYVALUELOGGER_H + +// \file KeyValueLogger.h +// one_line_description + +//# Never #include <config.h> or #include <lofar_config.h> in a header file! +//# Includes +#include <Common/LofarLogger.h> +#include <Common/lofar_map.h> +#include <Common/lofar_list.h> +#include <GCF/TM/GCF_Control.h> +#include <GCF/RTDB/DPservice.h> +#include <log4cplus/helpers/socketbuffer.h> + +// Avoid 'using namespace' in headerfiles + +namespace LOFAR { + namespace GCF { + namespace RTDBDaemons { + +class KeyValueLogger : public TM::GCFTask +{ +public: + explicit KeyValueLogger (const string& name); + ~KeyValueLogger (); + +private: + struct LogClient { + string name; + int32 obsID; + int32 msgCnt; + int32 errCnt; + bool valid; + LogClient() : obsID(0),msgCnt(-10),errCnt(0),valid(false) {}; + LogClient(const string& name, int32 obsID) : name(name),obsID(obsID),msgCnt(-10),errCnt(0),valid(false) {}; + }; + + // state methods + TM::GCFEvent::TResult initial (TM::GCFEvent& e, TM::GCFPortInterface& p); + TM::GCFEvent::TResult operational (TM::GCFEvent& e, TM::GCFPortInterface& p); + + // helper methods + void _registerClient(GCFPortInterface& port, + const string& name, uint32 obsID); + void _registerFailure(GCFPortInterface& port); + + // data members + TM::GCFTCPPort* itsListener; // application inpt + RTDB::DPservice* itsDPservice; // connection to PVSS + TM::GCFTimerPort* itsTimerPort; // timer + + typedef map<TM::GCFPortInterface*, LogClient> LogClientMap; + LogClientMap itsClients; + + // admin members + typedef list<TM::GCFPortInterface*> TClients; + TClients itsClientsGarbage; + +}; + + } // namespace RTDBDaemons + } // namespace GCF +} // namespace LOFAR + +#endif diff --git a/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLogger.log_prop b/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLogger.log_prop new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLoggerMain.cc b/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLoggerMain.cc new file mode 100644 index 0000000000000000000000000000000000000000..5a32c9d3a5f8980a6824eac38e16106e9c5d3656 --- /dev/null +++ b/MAC/APL/CURTDBDaemons/src/KeyValueLogger/KeyValueLoggerMain.cc @@ -0,0 +1,41 @@ +//# KeyValueLoggerMain.cc +//# +//# Copyright (C) 2008 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#include <lofar_config.h> + +#include <GCF/TM/GCF_Control.h> +#include "KeyValueLogger.h" + +using namespace LOFAR::GCF::TM; +using namespace LOFAR::GCF::RTDBDaemons; + +int main(int argc, char *argv[]) +{ + GCFTask::init(argc, argv, "KeyValueLogger"); + + KeyValueLogger kvl("KeyValueLogger"); + kvl.start(); // make initial transition + + GCFTask::run(); + + return (0); +} diff --git a/MAC/APL/CURTDBDaemons/src/KeyValueLogger/Makefile.am b/MAC/APL/CURTDBDaemons/src/KeyValueLogger/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..576a60c9f4d0908b211e4b0d2ef3f7663c625b53 --- /dev/null +++ b/MAC/APL/CURTDBDaemons/src/KeyValueLogger/Makefile.am @@ -0,0 +1,35 @@ +# Executables +bin_PROGRAMS = KeyValueLogger + +#KeyValueLogger_CPPFLAGS = -DBOOST_DISABLE_THREADS \ +# -Wno-deprecated \ +# -fmessage-length=0 \ +# -fdiagnostics-show-location=once + +KeyValueLogger_SOURCES = KeyValueLogger.cc \ + KeyValueLoggerMain.cc +KeyValueLogger_LDADD = $(LOFAR_DEPEND) $(libdir)/libkvt_protocol.a +KeyValueLogger_DEPENDENCIES = $(LOFAR_DEPEND) + +bin_SCRIPTS = + +NOINSTHDRS = KeyValueLogger.h + +INSTHDRS = + +BUILT_SOURCES = $(ph_HEADERS) + +pkginclude_HEADERS = $(NOINSTHDRS) $(INSTHDRS) + +DOCHDRS = $(pkginclude_HEADERS) $(BUILT_SOURCES) + +EXTRA_DIST = $(configfiles_DATA) $(sysconf_DATA) + +#in case of make install these files will be copied to the bindir beside the test apps +configfilesdir = $(bindir) +configfiles_DATA = + +sysconf_DATA = KeyValueLogger.conf \ + KeyValueLogger.log_prop + +include $(top_srcdir)/Makefile.common diff --git a/MAC/APL/CURTDBDaemons/src/LoggingProcessor/LoggingProcessor.cc b/MAC/APL/CURTDBDaemons/src/LoggingProcessor/LoggingProcessor.cc index 9ad655c01965068b64502b23e690664314eeaf8a..7bc7a98456a5b538ea13f77c63a32dd36ad080cf 100644 --- a/MAC/APL/CURTDBDaemons/src/LoggingProcessor/LoggingProcessor.cc +++ b/MAC/APL/CURTDBDaemons/src/LoggingProcessor/LoggingProcessor.cc @@ -25,7 +25,7 @@ #include <GCF/GCF_PVTypes.h> #include <GCF/GCF_ServiceInfo.h> #include <GCF/PVSS/PVSSresult.h> -#include <APL/CUDaemons/Log_Protocol.ph> +#include <APL/APLProtocol/LOG_Protocol.ph> #include <GCF/RTDB/DP_Protocol.ph> #include <log4cplus/socketappender.h> #include "LoggingProcessor.h" diff --git a/MAC/APL/CURTDBDaemons/src/LoggingProcessor/Makefile.am b/MAC/APL/CURTDBDaemons/src/LoggingProcessor/Makefile.am index 26f9eea5915b2427d0dac31bf9d2df5c2c3562ad..fa6954082e8b1c0cf90908567ec9776840a3b3b8 100644 --- a/MAC/APL/CURTDBDaemons/src/LoggingProcessor/Makefile.am +++ b/MAC/APL/CURTDBDaemons/src/LoggingProcessor/Makefile.am @@ -8,7 +8,7 @@ bin_PROGRAMS = LoggingProcessor LoggingProcessor_SOURCES = LoggingProcessor.cc \ LoggingProcessorMain.cc -LoggingProcessor_LDADD = $(LOFAR_DEPEND) +LoggingProcessor_LDADD = $(LOFAR_DEPEND) $(libdir)/liblog_protocol.a LoggingProcessor_DEPENDENCIES=$(LOFAR_DEPEND) bin_SCRIPTS = diff --git a/MAC/APL/CURTDBDaemons/src/Makefile.am b/MAC/APL/CURTDBDaemons/src/Makefile.am index fd6c8d127bf1669d4add1d883d5125a880c4c0b4..38720225bc2b00b2a2b276ef4b4aff5fa021d5bb 100644 --- a/MAC/APL/CURTDBDaemons/src/Makefile.am +++ b/MAC/APL/CURTDBDaemons/src/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = LoggingProcessor +SUBDIRS = LoggingProcessor KeyValueLogger include $(top_srcdir)/Makefile.common diff --git a/MAC/APL/CURTDBDaemons/test/Makefile.am b/MAC/APL/CURTDBDaemons/test/Makefile.am index 84b9190415368b4845f1cd2d8c719aebc6acec16..271ce493f777929446c2516f874bd0eb51aca413 100644 --- a/MAC/APL/CURTDBDaemons/test/Makefile.am +++ b/MAC/APL/CURTDBDaemons/test/Makefile.am @@ -1,8 +1,13 @@ AM_CPPFLAGS = -I$(top_builddir)/include -bin_PROGRAMS = tLoggingProcessor +bin_PROGRAMS = tLoggingProcessor tKeyValueLogger tLoggingProcessor_SOURCES = tLoggingProcessor.cc -tLoggingProcessor_DEPENDENCIES = $(LOFAR_DEPEND) +tLoggingProcessor_LDADD = $(libdir)/liblog_protocol.a +tLoggingProcessor_DEPENDENCIES = $(LOFAR_DEPEND) $(libdir)/liblog_protocol.a + +tKeyValueLogger_SOURCES = tKeyValueLogger.cc +tKeyValueLogger_LDADD = $(libdir)/libkvt_protocol.a $(libdir)/libeventport.a +tKeyValueLogger_DEPENDENCIES = $(LOFAR_DEPEND) $(libdir)/libkvt_protocol.a $(libdir)/libeventport.a include $(top_srcdir)/Makefile.common diff --git a/MAC/APL/CURTDBDaemons/test/tKeyValueLogger.cc b/MAC/APL/CURTDBDaemons/test/tKeyValueLogger.cc new file mode 100644 index 0000000000000000000000000000000000000000..6ba74327879423710335bcc1cc6b59382c8c89c9 --- /dev/null +++ b/MAC/APL/CURTDBDaemons/test/tKeyValueLogger.cc @@ -0,0 +1,61 @@ +//# tKeyValueLogger.cc: one_line_description +//# +//# Copyright (C) 2002-2004 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +//# Always #include <lofar_config.h> first! +#include <lofar_config.h> + +//# Includes +#include <Common/LofarLogger.h> +#include <Common/lofar_string.h> +#include <GCF/GCF_ServiceInfo.h> +#include <GCF/TM/EventPort.h> +#include <APL/APLProtocol/KVT_Protocol.ph> + +using namespace LOFAR; +using namespace LOFAR::GCF::TM; + +int main (int argc, char* argv[]) +{ + INIT_LOGGER(basename(argv[0])); + + EventPort thePort(MAC_SVCMASK_KVTLOGGER, false, KVT_PROTOCOL); // false = client + + KVTRegisterEvent registerEvent; + registerEvent.obsID = 5; + registerEvent.name = argv[0]; + thePort.send(®isterEvent); + KVTRegisterAckEvent registerAck(thePort.receive()); + + sleep(2); + + KVTSendMsgEvent msgEvent; + msgEvent.seqnr = 1; + msgEvent.key = "LOFAR.ObsSW.ObsCtrl.OnlineCtrl.OLAP.InputAppl.packageLoss{1198368555}"; + msgEvent.value = toString(25); + thePort.send(&msgEvent); + KVTSendMsgAckEvent msgAck(thePort.receive()); + + sleep(2); + + return (0); +} +