From 210c512c58af6f4d0aa6eaa2781cf04709fade43 Mon Sep 17 00:00:00 2001 From: Ruud Overeem <overeem@astron.nl> Date: Fri, 28 Apr 2006 11:58:09 +0000 Subject: [PATCH] BugID: 679 Redesign of Main Control Unit software. --- MAC/APL/MainCU/MainCU.spec.in | 169 ++++ MAC/APL/MainCU/Makefile.am | 8 + MAC/APL/MainCU/bootstrap | 3 + MAC/APL/MainCU/configure.in | 77 ++ .../src/MACScheduler/APLMACScheduler.dpl | 9 + .../src/MACScheduler/LogicalDeviceState.cc | 87 ++ .../src/MACScheduler/LogicalDeviceState.h | 107 +++ .../MainCU/src/MACScheduler/MACScheduler.cc | 787 ++++++++++++++++++ .../src/MACScheduler/MACScheduler.conf.in | 53 ++ .../MainCU/src/MACScheduler/MACScheduler.h | 181 ++++ .../src/MACScheduler/MACScheduler.log_prop.in | 44 + .../src/MACScheduler/MACSchedulerDefines.h | 47 ++ .../src/MACScheduler/MACSchedulerMain.cc | 38 + MAC/APL/MainCU/src/MACScheduler/Makefile.am | 44 + .../src/MACScheduler/customPrepPVSSDB.ctl.in | 17 + MAC/APL/MainCU/src/Makefile.am | 4 + .../StationControl/customPrepPVSSDB.ctl.in | 17 + 17 files changed, 1692 insertions(+) create mode 100644 MAC/APL/MainCU/MainCU.spec.in create mode 100644 MAC/APL/MainCU/Makefile.am create mode 100755 MAC/APL/MainCU/bootstrap create mode 100644 MAC/APL/MainCU/configure.in create mode 100644 MAC/APL/MainCU/src/MACScheduler/APLMACScheduler.dpl create mode 100644 MAC/APL/MainCU/src/MACScheduler/LogicalDeviceState.cc create mode 100644 MAC/APL/MainCU/src/MACScheduler/LogicalDeviceState.h create mode 100644 MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc create mode 100644 MAC/APL/MainCU/src/MACScheduler/MACScheduler.conf.in create mode 100644 MAC/APL/MainCU/src/MACScheduler/MACScheduler.h create mode 100644 MAC/APL/MainCU/src/MACScheduler/MACScheduler.log_prop.in create mode 100644 MAC/APL/MainCU/src/MACScheduler/MACSchedulerDefines.h create mode 100644 MAC/APL/MainCU/src/MACScheduler/MACSchedulerMain.cc create mode 100644 MAC/APL/MainCU/src/MACScheduler/Makefile.am create mode 100644 MAC/APL/MainCU/src/MACScheduler/customPrepPVSSDB.ctl.in create mode 100644 MAC/APL/MainCU/src/Makefile.am create mode 100644 MAC/APL/StationCU/src/StationControl/customPrepPVSSDB.ctl.in diff --git a/MAC/APL/MainCU/MainCU.spec.in b/MAC/APL/MainCU/MainCU.spec.in new file mode 100644 index 00000000000..f68a74235b7 --- /dev/null +++ b/MAC/APL/MainCU/MainCU.spec.in @@ -0,0 +1,169 @@ +# -*- Mode:rpm-spec -*- +# MCU.spec.in +# + +############################################################################## +# +# Preamble +# +############################################################################## + +Summary: The MCU contains all controller for the MainCU. + +%define release @RPM_RELEASE@ +%define version @VERSION@ +%define pkgname @PACKAGE@ +%define pkgdir %{pkgname}-%{version}-%{release} +%define prefix /opt/lofar +%define configure_args @RPM_CONFIGURE_ARGS@ +##define build_kernel_version @BUILD_KERNEL_VERSION@ + +Name: %{pkgname} +Version: %{version} +Release: %{release} +Copyright: LGPL +Group: Application/System +Source: %{pkgname}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{pkgdir}-root +URL: http://www.astron.nl +Prefix: %{prefix} +BuildArchitectures: i386 # Target platforms, i.e., i586 +Requires: Common = 2.3 +Requires: APS = 2.0 +Requires: OTDB = 1.0 +Requires: GCFTM = 6.0 +Requires: GCFCommon = 6.0 +Requires: GCFPAL = 6.0 +Requires: APLCommon = 3.1 +Packager: %{packager} +Distribution: The LOFAR project +Vendor: ASTRON + +AutoReqProv: no + +%description + +The MCU contains all controller for the MainCU: +MacScheduler that scans the SAS database for new observations. +ObservationCtrl that is the maincontroller for each observation. +BeamDirection that makes sure that all station point in the same direction. + +############################################################################## +# +# prep +# +############################################################################## +%prep +echo $prefix + +# create the build directory, untar the source +%setup + +############################################################################## +# +# build +# +############################################################################## +%build +./configure %{configure_args} --prefix=%{prefix} && make + +############################################################################## +# +# install +# +############################################################################## +%install +# To make things work with BUILDROOT +if [ "$RPM_BUILD_ROOT" != "%{_tmppath}/%{pkgdir}-root" ] +then + echo + echo @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + echo @ @ + echo @ RPM_BUILD_ROOT is not what I expected. Please clean it yourself. @ + echo @ @ + echo @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + echo +else + echo Cleaning RPM_BUILD_ROOT: "$RPM_BUILD_ROOT" + rm -rf "$RPM_BUILD_ROOT" +fi +mkdir -p $RPM_BUILD_ROOT%{prefix} +make DESTDIR="$RPM_BUILD_ROOT" install + +#uninstall + +############################################################################## +# +# verify +# +############################################################################## +#verify + +############################################################################## +# +# clean +# +############################################################################## +%clean +# Call me paranoid, but I do not want to be responsible for nuking +# someone's harddrive! +if [ "$RPM_BUILD_ROOT" != "%{_tmppath}/%{pkgdir}-root" ] +then + echo + echo @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + echo @ @ + echo @ RPM_BUILD_ROOT is not what I expected. Please clean it yourself. @ + echo @ @ + echo @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + echo +else + echo Cleaning RPM_BUILD_ROOT: "$RPM_BUILD_ROOT" + rm -rf "$RPM_BUILD_ROOT" +fi + +############################################################################## +# +# files +# +############################################################################## + +# empty 'files' means all distributed files +%files +%defattr(-, root, root) +%{prefix} + +# Your application file list goes here +# %{prefix}/lib/lib*.so* + +# Documentation +# doc COPYING ChangeLog README AUTHORS NEWS +# doc doc/* + +# link the module to the correct path +%post + +# before uninstall +%preun + +# after uninstall +%postun + +############################################################################## +# +# package devel +# +############################################################################## + +#package devel +#Summary: Development files for %{pkgname} +#Group: Applications/System +#description devel +#Development files for %{pkgname}. + +#files devel + +# Your development files go here +# Programmers documentation goes here +#doc doc + +# end of file diff --git a/MAC/APL/MainCU/Makefile.am b/MAC/APL/MainCU/Makefile.am new file mode 100644 index 00000000000..9f9e52186c1 --- /dev/null +++ b/MAC/APL/MainCU/Makefile.am @@ -0,0 +1,8 @@ +SUBDIRS=src + +EXTRA_DIST = \ + Makefile.common \ + MainCU.spec \ + autoconf_share/compiletool + +include $(top_srcdir)/Makefile.common diff --git a/MAC/APL/MainCU/bootstrap b/MAC/APL/MainCU/bootstrap new file mode 100755 index 00000000000..06f18cde1db --- /dev/null +++ b/MAC/APL/MainCU/bootstrap @@ -0,0 +1,3 @@ +#!/bin/sh + +../../../autoconf_share/bootstrap ../../../autoconf_share diff --git a/MAC/APL/MainCU/configure.in b/MAC/APL/MainCU/configure.in new file mode 100644 index 00000000000..ee57a399b4e --- /dev/null +++ b/MAC/APL/MainCU/configure.in @@ -0,0 +1,77 @@ +dnl +dnl Process this file with autoconf to produce a configure script. +dnl +AC_INIT +dnl AC_CONFIG_AUX_DIR(config) +dnl AM_CONFIG_HEADER(config/config.h) +AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE(MainCU, 1.0, no-define) + +dnl +dnl Initialize for LOFAR (may set compilers) +dnl +lofar_INIT + +dnl Checks for programs. +AC_PROG_AWK +AC_PROG_CC +AC_PROG_CXX +AC_PROG_INSTALL +AC_PROG_LN_S +AC_DISABLE_SHARED +AC_PROG_LIBTOOL +AC_PROG_YACC +AM_PROG_LEX + +dnl Checks for libraries. + +dnl dnl Replace `main' with a function in -lfl: +dnl AC_CHECK_LIB(fl, main) +dnl dnl Replace `main' with a function in -lcosev_r: +dnl AC_CHECK_LIB(cosev_r, main) +dnl dnl Replace `main' with a function in -lcosnm_r: +dnl AC_CHECK_LIB(cosnm_r, main) +dnl dnl Replace `main' with a function in -lorb_r: +dnl AC_CHECK_LIB(orb_r, main) +dnl dnl Replace `main' with a function in -lpthread: +dnl AC_CHECK_LIB(pthread, main) +dnl dnl Replace `main' with a function in -lvport_r: +dnl AC_CHECK_LIB(vport_r, main) + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(unistd.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +dnl Checks for library functions. +AC_FUNC_VPRINTF + +dnl +dnl Check for LOFAR specific things +dnl +lofar_GENERAL +lofar_COMPILETOOLS +lofar_PVSS(1) +lofar_INTERNAL(LCS/Common, common, LCS-Common-2_3, 1, Common/LofarTypes.h,,) +lofar_INTERNAL(LCS/ACC/APS, aps, LCS-ACC-2_0, 1, APS/ParameterSet.h,,) +lofar_INTERNAL(SAS/OTDB, otdb, HEAD, 1, OTDB/OTDBconnection.h,,) +lofar_INTERNAL(MAC/GCF/GCFCommon, gcfcommon, MAC-GCF-6_0, 1, GCF/GCF_Defines.h,,) +lofar_INTERNAL(MAC/GCF/TM, gcftm, MAC-GCF-6_0, 1, GCF/TM/GCF_Task.h,,) +lofar_INTERNAL(MAC/GCF/PAL, gcfpal, MAC-GCF-6_0, 1, GCF/PAL/GCF_PVSSInfo.h,,) +lofar_INTERNAL(MAC/APL/APLCommon, aplcommon, MAC-APL-3_1, 1, APL/APLCommon/APL_Defines.h,,) +lofar_EXTERNAL(boost,1.32,boost/date_time/date.hpp, boost_date_time-gcc) +lofar_EXTERNAL(pqxx,2.5.5,pqxx/pqxx, pqxx) +lofar_EXTERNAL(pq,,libpq-fe.h, pq, /usr/local/pgsql) + +dnl +dnl Output Makefiles +dnl +AC_OUTPUT( +src/Makefile +src/MACScheduler/Makefile +Makefile +MainCU.spec +) diff --git a/MAC/APL/MainCU/src/MACScheduler/APLMACScheduler.dpl b/MAC/APL/MainCU/src/MACScheduler/APLMACScheduler.dpl new file mode 100644 index 00000000000..18503e5533f --- /dev/null +++ b/MAC/APL/MainCU/src/MACScheduler/APLMACScheduler.dpl @@ -0,0 +1,9 @@ +# ascii dump of database + +# DpType +TypeName +TAplMacScheduler.TAplMacScheduler 1#1 + state 25#2 + error 25#3 + + diff --git a/MAC/APL/MainCU/src/MACScheduler/LogicalDeviceState.cc b/MAC/APL/MainCU/src/MACScheduler/LogicalDeviceState.cc new file mode 100644 index 00000000000..527192bca73 --- /dev/null +++ b/MAC/APL/MainCU/src/MACScheduler/LogicalDeviceState.cc @@ -0,0 +1,87 @@ +//# LogicalDeviceState.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 <LogicalDeviceState.h> + +namespace LOFAR { + namespace APLCommon { + +// +// LogicalDeviceState() +// +LogicalDeviceState::LogicalDeviceState() +{ + itsStates.resize(LAST_STATE); + itsStates[UNKNOWN] = "Unknown"; + itsStates[CONNECT] = "Connecting"; + itsStates[CONNECTED] = "Connected"; + itsStates[SCHEDULE] = "Scheduling"; + itsStates[SCHEDULED] = "Scheduled"; + itsStates[CANCEL_SCHEDULE] = "Canceling Schedule"; + itsStates[SCHEDULE_CANCELLED] = "Schedule Cancelled"; + itsStates[CLAIM] = "Claiming"; + itsStates[CLAIMED] = "Claimed"; + itsStates[PREPARE] = "Preparing"; + itsStates[PREPARED] = "Prepared"; + itsStates[RESUME] = "Resuming"; + itsStates[RESUMED] = "Resumed"; + itsStates[SUSPEND] = "Suspending"; + itsStates[SUSPENDED] = "Suspended"; + itsStates[RELEASE] = "Releasing"; + itsStates[RELEASED] = "Released"; + itsStates[FINISH] = "Finishing"; + itsStates[FINISHED] = "Finished"; +} + +// +// ~LogicalDeviceState() +// +LogicalDeviceState::~LogicalDeviceState() +{ +} + +string LogicalDeviceState::name(uint16 aStateNr) +{ + return (((aStateNr >= UNKNOWN) && (aStateNr < LAST_STATE)) ? + itsStates[aStateNr] : ""); +} + +uint16 LogicalDeviceState::value(const string& aStateName) +{ + uint16 i = UNKNOWN; + while (i < LAST_STATE) { + if (itsStates[i] == aStateName) { + return (i); + } + i++; + } + + ASSERTSTR(false, aStateName << " is not a valid LogicalDeviceState"); +} + + } // namespace APL +} // namespace LOFAR diff --git a/MAC/APL/MainCU/src/MACScheduler/LogicalDeviceState.h b/MAC/APL/MainCU/src/MACScheduler/LogicalDeviceState.h new file mode 100644 index 00000000000..69c55120a8a --- /dev/null +++ b/MAC/APL/MainCU/src/MACScheduler/LogicalDeviceState.h @@ -0,0 +1,107 @@ +//# LogicalDeviceState.h: 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$ + +#ifndef APL_LOGICALDEVICESTATE_H +#define APL_LOGICALDEVICESTATE_H + +// \file LogicalDeviceState.h +// one_line_description + +//# Never #include <config.h> or #include <lofar_config.h> in a header file! +//# Includes +#include <Common/lofar_map.h> + +// Avoid 'using namespace' in headerfiles + +namespace LOFAR { + namespace APLCommon { + +// \addtogroup package +// @{ + + +// class_description +// ... +class LogicalDeviceState +{ +public: + LogicalDeviceState(); + ~LogicalDeviceState(); + + // define enumeration for all states of an LogicalDevice. + typedef enum { + UNKNOWN = 0, + CONNECT, + CONNECTED, + SCHEDULE, + SCHEDULED, + CANCEL_SCHEDULE, + SCHEDULE_CANCELLED, + CLAIM, + CLAIMED, + PREPARE, + PREPARED, + RESUME, + RESUMED, + SUSPEND, + SUSPENDED, + RELEASE, + RELEASED, + FINISH, + FINISHED, + LAST_STATE + } LDstateNr; + + // conversion routines + string name(uint16 aStateNr); + uint16 value(const string& aStateName); + + // ... example + ostream& print (ostream& os) const + { return (os); } + +private: + // Copying is not allowed + LogicalDeviceState(const LogicalDeviceState& that); + LogicalDeviceState& operator=(const LogicalDeviceState& that); + + //# --- Datamembers --- + vector<string> itsStates; +}; + +//# --- Inline functions --- + +// ... example +//# +//# operator<< +//# +inline ostream& operator<< (ostream& os, const LogicalDeviceState& aLogicalDeviceState) +{ + return (aLogicalDeviceState.print(os)); +} + + +// @} + } // namespace APLCommon +} // namespace LOFAR + +#endif diff --git a/MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc new file mode 100644 index 00000000000..510e7468952 --- /dev/null +++ b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc @@ -0,0 +1,787 @@ +//# MACScheduler.cc: Implementation of the MAC Scheduler task +//# +//# 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$ +#include <lofar_config.h> +#include <Common/LofarLogger.h> + +#include <boost/shared_array.hpp> +#include <APS/ParameterSet.h> +#include <GCF/GCF_PVString.h> +#include <GCF/GCF_PVDouble.h> +#include <GCF/GCF_PVInteger.h> +#include <GCF/PAL/GCF_PVSSInfo.h> + +#include "APL/APLCommon/APLUtilities.h" +#include "APL/APLCommon/APLCommonExceptions.h" +#include <LogicalDeviceState.h> +#include "MACSchedulerDefines.h" +#include "MACScheduler.h" + +using namespace LOFAR::GCF::Common; +using namespace LOFAR::GCF::TM; +using namespace LOFAR::GCF::PAL; +using namespace LOFAR::OTDB; +using namespace std; + +namespace LOFAR { + using namespace APLCommon; + using namespace ACC::APS; + namespace MCU { + +// +// MACScheduler() +// +MACScheduler::MACScheduler() : + GCFTask ((State)&MACScheduler::initial_state,string(MS_TASKNAME)), + PropertySetAnswerHandlerInterface(), + itsPropertySetAnswer(*this), + itsPropertySet (), +// itsVISDclientPorts (), +// itsVIparentPortName (string("VIparent_server")), +// itsVIparentPort (*this, m_VIparentPortName, GCFPortInterface::MSPP, LOGICALDEVICE_PROTOCOL), +// itsVIclientPorts (), +// itsconnectedVIclientPorts(), + + itsObsCntlrMap (), + itsSDclientPort (0), + itsLDserverPort (0), + itsSecondTimer (0), + itsSDretryTimer (0), + itsQueuePeriod (0), + itsClaimPeriod (0), + itsOTDBconnection (0), + itsOTDBpollInterval (0), + itsNextOTDBpolltime (0) +{ + LOG_TRACE_OBJ ("MACscheduler construction"); + +#ifndef USE_PVSSPORT + LOG_WARN("Using GCFTCPPort in stead of GCFPVSSPort"); +#endif + + // Log the protocols I use. + registerProtocol(LOGICALDEVICE_PROTOCOL, LOGICALDEVICE_PROTOCOL_signalnames); + registerProtocol(STARTDAEMON_PROTOCOL, STARTDAEMON_PROTOCOL_signalnames); + + // Readin some parameters from the ParameterSet. + itsOTDBpollInterval = globalParameterSet()->getTime("OTDBpollInterval"); + itsQueuePeriod = globalParameterSet()->getTime("QueuePeriod"); + itsClaimPeriod = globalParameterSet()->getTime("ClaimPeriod"); +} + + +// +// ~MACScheduler() +// +MACScheduler::~MACScheduler() +{ + LOG_TRACE_OBJ ("~MACscheduler"); + + if (itsPropertySet) { + itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("down")); + itsPropertySet->disable(); + } + + if (itsOTDBconnection) { + delete itsOTDBconnection; + } + if (itsSDclientPort) { + itsSDclientPort->close(); + delete itsSDclientPort; + } +} + + +// +// handlePropertySetAnswer(answer) +// +void MACScheduler::handlePropertySetAnswer(GCFEvent& answer) +{ + switch(answer.signal) { + case F_MYPS_ENABLED: { + GCFPropSetAnswerEvent* pPropAnswer=static_cast<GCFPropSetAnswerEvent*>(&answer); + if(pPropAnswer->result != GCF_NO_ERROR) { + LOG_ERROR(formatString("%s : PropertySet %s NOT ENABLED", + getName().c_str(), pPropAnswer->pScope)); + } + break; + } + + case F_PS_CONFIGURED: + { + GCFConfAnswerEvent* pConfAnswer=static_cast<GCFConfAnswerEvent*>(&answer); + if(pConfAnswer->result == GCF_NO_ERROR) { + LOG_DEBUG(formatString("%s : apc %s Loaded", + getName().c_str(), pConfAnswer->pApcName)); + //apcLoaded(); + } + else { + LOG_ERROR(formatString("%s : apc %s NOT LOADED", + getName().c_str(), pConfAnswer->pApcName)); + } + break; + } + + case F_VGETRESP: + case F_VCHANGEMSG: { + // check which property changed + GCFPropValueEvent* pPropAnswer=static_cast<GCFPropValueEvent*>(&answer); + + // TODO: implement something usefull. + // change of queueTime + if ((strstr(pPropAnswer->pPropName, MS_PROPSET_NAME) != 0) && + (pPropAnswer->pValue->getType() == LPT_INTEGER)) { + uint32 newVal = (uint32) ((GCFPVInteger*)pPropAnswer->pValue)->getValue(); + if (strstr(pPropAnswer->pPropName, PVSSNAME_MS_QUEUEPERIOD) != 0) { + LOG_INFO_STR ("Changing QueuePeriod from " << itsQueuePeriod << + " to " << newVal); + itsQueuePeriod = newVal; + } + else if (strstr(pPropAnswer->pPropName, PVSSNAME_MS_CLAIMPERIOD) != 0) { + LOG_INFO_STR ("Changing ClaimPeriod from " << itsClaimPeriod << + " to " << newVal); + itsClaimPeriod = newVal; + } + } + break; + } + + default: + break; + } +} + + +// +// initial_state(event, port) +// +// Setup all connections. +// +GCFEvent::TResult MACScheduler::initial_state(GCFEvent& event, GCFPortInterface& /*port*/) +{ + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: { + // Get access to my own propertyset. + itsPropertySet = GCFMyPropertySetPtr(new GCFMyPropertySet(MS_PROPSET_NAME, + MS_PROPSET_TYPE, + PS_CAT_PERMANENT, + &itsPropertySetAnswer)); + itsPropertySet->enable(); + + // update PVSS. + itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("initial")); + itsPropertySet->setValue(string(PVSSNAME_FSM_ERROR),GCFPVString("")); + + // Try to connect to the SAS database. + ACC::APS::ParameterSet* pParamSet = ACC::APS::globalParameterSet(); + string username = pParamSet->getString("OTDBusername"); + string DBname = pParamSet->getString("OTDBdatabasename"); + string password = pParamSet->getString("OTDBpassword"); + + itsOTDBconnection= new OTDBconnection(username, DBname, password); + ASSERTSTR (itsOTDBconnection, "Memory allocation error (OTDB)"); + ASSERTSTR (itsOTDBconnection->connect(), + "Unable to connect to database " << DBname << " using " << + username << "," << password); + + // Connect to local startDaemon + itsSDclientPort = new GCFTCPPort(*this, + "StartDaemon", + GCFPortInterface::SAP, + STARTDAEMON_PROTOCOL); + ASSERTSTR(itsSDclientPort, "Unable to allocate a port for the StartDaemon"); + itsSDclientPort->open(); // may result in CONN or DISCONN event + } + break; + + case F_CONNECTED: // must be from SDclient port. + if (itsSDclientPort->isConnected()) { // connected with SD! + itsSDclientPort->cancelTimer(itsSDretryTimer); // cancel retry timer + TRAN(MACScheduler::recover_state); // go to next state. + } + break; + + case F_DISCONNECTED: // must be from SDclient port. + if (!itsSDclientPort->isConnected()) { // connection with SD failed + // tell PVSS what my problem is + itsPropertySet->setValue(string(PVSSNAME_FSM_ERROR), + GCFPVString("Waiting for StartDaemon")); + itsSDretryTimer = itsSDclientPort->setTimer(1.0); // retry in 1 second. + } + break; + + case F_TIMER: // must be from SDclient port. + if (!itsSDclientPort->isConnected()) { // really not connected? + itsSDclientPort->open(); // try again + } + break; + + default: + LOG_DEBUG_STR ("MACScheduler(" << getName() << ")::initial_state, default"); + status = GCFEvent::NOT_HANDLED; + break; + } + return (status); +} + + +// +// recover_state(event, port) +// +// Read last PVSS states, compare those to the SAS states and try to +// recover to the last situation. +// +GCFEvent::TResult MACScheduler::recover_state(GCFEvent& event, GCFPortInterface& port) +{ + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: { + // update PVSS + itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("recover")); + itsPropertySet->setValue(string(PVSSNAME_FSM_ERROR),GCFPVString("")); + + // open server port for ObservationControllers + itsLDserverPort = new GCFTCPPort(*this, + "ObsControllers", + GCFPortInterface::MSPP, + LOGICALDEVICE_PROTOCOL); + itsLDserverPort->open(); // LDprotocol server port + + // + // TODO: do recovery + + TRAN(MACScheduler::active_state); + + break; + } + + default: + LOG_DEBUG(formatString("MACScheduler(%s)::recover_state, default",getName().c_str())); + status = GCFEvent::NOT_HANDLED; + break; + } + return (status); +} + +// +// active_state(event, port) +// +// Normal operation state. Check OTDB every OTDBpollInterval seconds and control +// the running observations. +// +GCFEvent::TResult MACScheduler::active_state(GCFEvent& event, GCFPortInterface& port) +{ + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: { + // update PVSS + itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("active")); + itsPropertySet->setValue(string(PVSSNAME_FSM_ERROR),GCFPVString("")); + + // Timers must be connected to ports, so abuse serverPort for second timer. + itsSecondTimer = itsLDserverPort->setTimer(1L); + break; + } + + case F_ACCEPT_REQ: { + // Should be from a just started ObservationController. + ASSERTSTR(port.getProtocol() == LOGICALDEVICE_PROTOCOL, + "AcceptReq on port " << port.getName()); + + + // accept connection and add port to port-vector + GCFTCPPort* client(new GCFTCPPort); + // reminder: init (task, name, type, protocol [,raw]) + client->init(*this, "newObsCntlr", GCFPortInterface::SPP, + LOGICALDEVICE_PROTOCOL); + itsLDserverPort->accept(*client); + itsObsCntlrPorts.push_back(client); // save client port in stack + break; + } + + case F_CONNECTED: + // Should be from the (lost) connection with the SD + _connectedHandler(port); + break; + + case F_DISCONNECTED: + // Can be from StartDaemon or ObsController. + // StartDaemon: trouble! Try to reconnect asap. + // ObsController: ok when obs is finished, BIG TROUBLE when not! + _disconnectedHandler(port); + break; + + case F_TIMER: { // secondTimer or reconnectTimer. + GCFTimerEvent& timerEvent=static_cast<GCFTimerEvent&>(event); + if (timerEvent.id == itsSecondTimer) { + // time to poll the OTDB? + if (time(0) >= itsNextOTDBpolltime) { + _doOTDBcheck(); + // reinit polltime. + itsNextOTDBpolltime = time(0) + itsOTDBpollInterval; + } + itsSecondTimer = port.setTimer(1.0); + } + // a connection was lost and a timer was set to try to reconnect. +// else if (...) { + // TODO +// map timer to port +// port.open(); +// } + break; + } + + case LOGICALDEVICE_CONNECT: { + // An ObsCntlr has started and reports that it is started + LOGICALDEVICEConnectEvent connectEvent(event); + GCFTCPPort* portPtr(static_cast<GCFTCPPort*>(&port)); + + // copy name of controller to portname + // does not exist! portPtr->setName(connectEvent.nodeId); + + // construct a controller object. + ObsCntlr_t controller; + controller.treeID = atol(connectEvent.nodeId.c_str()); + controller.port = portPtr; + controller.state = LogicalDeviceState::CONNECTED; + + // add it to the map + // TODO: + + // report to ObsCntlr that he is registered. + LOGICALDEVICEConnectedEvent connectedEvent; + connectedEvent.result = LD_RESULT_NO_ERROR; + port.send(connectedEvent); + break; + } + + case LOGICALDEVICE_SCHEDULED: { + LOGICALDEVICEScheduledEvent scheduledEvent(event); + // ... + break; + } + + case LOGICALDEVICE_SCHEDULECANCELLED: { + LOGICALDEVICESchedulecancelledEvent schedulecancelledEvent(event); + // ... + break; + } + + case LOGICALDEVICE_CLAIMED: { + LOGICALDEVICEClaimedEvent claimedEvent(event); + // ... + break; + } + + case LOGICALDEVICE_PREPARED: { + LOGICALDEVICEPreparedEvent preparedEvent(event); + // ... + break; + } + + case LOGICALDEVICE_RESUMED: { + LOGICALDEVICEResumedEvent resumedEvent(event); + // ... + break; + } + + case LOGICALDEVICE_SUSPENDED: { + LOGICALDEVICESuspendedEvent suspendedEvent(event); + // ... + break; + } + + case LOGICALDEVICE_RELEASED: { + LOGICALDEVICEReleasedEvent releasedEvent(event); + // ... + break; + } + + case LOGICALDEVICE_FINISH: { + LOGICALDEVICEFinishEvent finishEvent(event); + // ... + break; + } + + case STARTDAEMON_SCHEDULED: + { + STARTDAEMONScheduledEvent scheduledEvent(event); + // ... + break; + } + + default: + LOG_DEBUG(formatString("MACScheduler(%s)::active_state, default", + getName().c_str())); + status = GCFEvent::NOT_HANDLED; + break; + } + + return (status); +} + +// +// _doOTDBcheck +// +// Check if a new action should be taken based on the contents of OTDB and our own +// administration. +// +void MACScheduler::_doOTDBcheck() +{ + +} + +// +// readObservationParameters(ObsTreeID) +// +// Ask the OTDB to create an ParameterSet of the given Tree. +// +boost::shared_ptr<ACC::APS::ParameterSet> + MACScheduler::readObservationParameters(OTDB::treeIDType ObsTreeID) +{ + // Convert treeId to nodeID of top node. + TreeMaintenance tm(itsOTDBconnection); + OTDBnode topNode = tm.getTopNode(ObsTreeID); + LOG_INFO_STR(topNode); + + // construct the filename + string tempFileName = string(LOFAR_SHARE_LOCATION) + "/Obs_" + toString(ObsTreeID); + + // read the parameterset from the database: + LOG_INFO(formatString("Exporting tree %d to '%s'", + ObsTreeID, tempFileName.c_str())); + if (!tm.exportTree(ObsTreeID, topNode.nodeID(), tempFileName)) { + THROW(APLCommon::OTDBException, string("Unable to export tree ") + + toString(ObsTreeID) + " to " + tempFileName); + } + + // read file into ParameterSet + boost::shared_ptr<ACC::APS::ParameterSet> ps; + ps.reset(new ACC::APS::ParameterSet(tempFileName)); + +// createChildsSections (tm, ObsTreeID, topNode.nodeID(), string(""), ps); + + return (ps); +} + +#if 0 + +// +// _schedule (rootID, port) +// +// One way or another they start an observation by creating and modifying a +// parameterSet, allocation beams?? and sending one startDaemon a schedule event. +// +void MACScheduler::_schedule(const string& VIrootID, GCFPortInterface* /*port*/) +{ + string shareLocation = _getShareLocation(); //REO + try { + boost::shared_ptr<ACC::APS::ParameterSet> ps = _readParameterSet(VIrootID); + + // replace the parent port (assigned by the ServiceBroker) + unsigned int parentPort = itsVIparentPort.getPortNumber(); + ACC::APS::KVpair kvPair(string("parentPort"),(int)parentPort); + ps->replace(kvPair); + + // get some parameters and write it to the allocated CCU + string allocatedCCU = ps->getString("allocatedCCU"); + string viName = ps->getString("name"); + string parameterFileName = viName + string(".param"); + + // make all relative times absolute +// _convertRelativeTimes(ps); + + string ldTypeString = ps->getString("logicalDeviceType"); + TLogicalDeviceTypes ldTypeRoot = APLUtilities::convertLogicalDeviceType(ldTypeString); + + bool allocationOk = true; + TSASResult sasResult(SAS_RESULT_NO_ERROR); + +#if 0 + // find the subbands allocations in VI sections + vector<string> childKeys = ps->getStringVector("childs"); + for(vector<string>::iterator childsIt=childKeys.begin(); + allocationOk && childsIt!=childKeys.end();++childsIt) { + string ldTypeString = ps->getString(*childsIt + ".logicalDeviceType"); + TLogicalDeviceTypes ldType = APLUtilities::convertLogicalDeviceType(ldTypeString); + if(ldType == LDTYPE_VIRTUALINSTRUMENT) { //REO + // allocate beamlets for VI's + allocationOk = _allocateBeamlets(VIrootID, ps, *childsIt); + if(!allocationOk) { + sasResult = SAS_RESULT_ERROR_BEAMLET_ALLOCATION_FAILED; + } + else { + allocationOk = _allocateLogicalSegments(VIrootID, ps, *childsIt); + if(!allocationOk) { + sasResult = SAS_RESULT_ERROR_LOGICALSEGMENT_ALLOCATION_FAILED; + } + } + } + } + if(!allocationOk) { + SASResponseEvent sasResponseEvent; + sasResponseEvent.result = sasResult; + itsPropertySet->setValue(string(MS_PROPNAME_STATUS),GCFPVInteger(sasResponseEvent.result)); + } + else +#endif + { + string tempFileName = APLUtilities::getTempFileName(); + ps->writeFile(tempFileName); + APLUtilities::remoteCopy(tempFileName,allocatedCCU,shareLocation+parameterFileName); + remove(tempFileName.c_str()); + + // send the schedule event to the VI-StartDaemon on the CCU + STARTDAEMONScheduleEvent sdScheduleEvent; + sdScheduleEvent.logicalDeviceType = ldTypeRoot; + sdScheduleEvent.taskName = viName; + sdScheduleEvent.fileName = parameterFileName; + + TStringRemotePortMap::iterator it = itsVISDclientPorts.find(allocatedCCU); + if(it != itsVISDclientPorts.end()) { + it->second->send(sdScheduleEvent); + } + else { + SASResponseEvent sasResponseEvent; + sasResponseEvent.result = SAS_RESULT_ERROR_VI_NOT_FOUND; + itsPropertySet->setValue(string(MS_PROPNAME_STATUS),GCFPVInteger(sasResponseEvent.result)); + } + } + } + catch(Exception& e) { + LOG_FATAL(formatString("Error reading schedule parameters: %s",e.message().c_str())); + SASResponseEvent sasResponseEvent; + sasResponseEvent.result = SAS_RESULT_ERROR_UNSPECIFIED; + itsPropertySet->setValue(string(MS_PROPNAME_STATUS),GCFPVInteger(sasResponseEvent.result)); + } + catch(exception& e) { + LOG_FATAL(formatString("Error reading schedule parameters: %s",e.what())); + SASResponseEvent sasResponseEvent; + sasResponseEvent.result = SAS_RESULT_ERROR_UNSPECIFIED; + itsPropertySet->setValue(string(MS_PROPNAME_STATUS),GCFPVInteger(sasResponseEvent.result)); + } +} + + +// +// _updateSchedule(rootVI, port) +// +void MACScheduler::_updateSchedule(const string& VIrootID, GCFPortInterface* port) +{ + string shareLocation = _getShareLocation(); + + // search the port of the VI + try + { + boost::shared_ptr<ACC::APS::ParameterSet> ps = _readParameterSet(VIrootID); + + // replace the parent port (assigned by the ServiceBroker) + unsigned int parentPort = itsVIparentPort.getPortNumber(); + ACC::APS::KVpair kvPair(string("parentPort"),(int)parentPort); + ps->replace(kvPair); + + string allocatedCCU = ps->getString("allocatedCCU"); + string viName = ps->getString("name"); + string parameterFileName = viName + string(".param"); + + // make all relative times absolute + _convertRelativeTimes(ps); + + string tempFileName = APLUtilities::getTempFileName(); + ps->writeFile(tempFileName); + APLUtilities::remoteCopy(tempFileName,allocatedCCU,shareLocation+parameterFileName); + remove(tempFileName.c_str()); + + // send a SCHEDULE message + TStringRemotePortMap::iterator it = itsconnectedVIclientPorts.find(viName); + if(it != itsconnectedVIclientPorts.end()) { + LOGICALDEVICEScheduleEvent scheduleEvent; + scheduleEvent.fileName = parameterFileName; + + it->second->send(scheduleEvent); + } + else { + SASResponseEvent sasResponseEvent; + sasResponseEvent.result = SAS_RESULT_ERROR_VI_NOT_FOUND; + itsPropertySet->setValue(string(MS_PROPNAME_STATUS),GCFPVInteger(sasResponseEvent.result)); + } + } + catch(Exception& e) { + LOG_FATAL(formatString("Error reading schedule parameters: %s",e.message().c_str())); + SASResponseEvent sasResponseEvent; + sasResponseEvent.result = SAS_RESULT_ERROR_UNSPECIFIED; + sasResponseEvent.VIrootID = VIrootID; + + if(port != 0) { + port->send(sasResponseEvent); + } + itsPropertySet->setValue(string(MS_PROPNAME_STATUS),GCFPVInteger(sasResponseEvent.result)); + } +} + + +// +// _cancelSchedule(rootVI, port) +// +void MACScheduler::_cancelSchedule(const string& VIrootID, GCFPortInterface* /*port*/) +{ + string shareLocation = _getShareLocation(); //REO + + // search the port of the VI + try { + boost::shared_ptr<ACC::APS::ParameterSet> ps = _readParameterSet(VIrootID); + + string viName = ps->getString("name"); + + // send a CANCELSCHEDULE message + TStringRemotePortMap::iterator it = itsconnectedVIclientPorts.find(viName); + if(it != itsconnectedVIclientPorts.end()) { + LOGICALDEVICECancelscheduleEvent cancelScheduleEvent; + it->second->send(cancelScheduleEvent); + } + else { + SASResponseEvent sasResponseEvent; + sasResponseEvent.result = SAS_RESULT_ERROR_VI_NOT_FOUND; + itsPropertySet->setValue(string(MS_PROPNAME_STATUS),GCFPVInteger(sasResponseEvent.result)); + } + + } + catch(Exception& e) + { + LOG_FATAL(formatString("Error reading schedule parameters: %s",e.message().c_str())); + SASResponseEvent sasResponseEvent; + sasResponseEvent.result = SAS_RESULT_ERROR_UNSPECIFIED; + itsPropertySet->setValue(string(MS_PROPNAME_STATUS),GCFPVInteger(sasResponseEvent.result)); + } +} + +// +// _isServerPort(server, port) +// +bool MACScheduler::_isServerPort(const GCFPortInterface& server, + const GCFPortInterface& port) const +{ + return (&port == &server); // comparing two pointers. yuck? +} + + +// +// _isVISDclientPort(port, visd) +// +bool MACScheduler::_isVISDclientPort(const GCFPortInterface& port, + string& visd) const +{ + bool found=false; + TStringRemotePortMap::const_iterator it=itsVISDclientPorts.begin(); + while(!found && it != itsVISDclientPorts.end()) { + found = (&port == it->second.get()); // comparing two pointers. yuck? + if(found) { + visd = it->first; + } + ++it; + } + return (found); +} + + +// +// _isVIclientPort(port) +// +bool MACScheduler::_isVIclientPort(const GCFPortInterface& port) const +{ + bool found=false; + TRemotePortVector::const_iterator it=itsVIclientPorts.begin(); + while(!found && it != itsVIclientPorts.end()) { + found = (&port == (*it).get()); // comparing two pointers. yuck? + ++it; + } + return (found); +} + + +// +// _getVInameFromPort(port) +// +string MACScheduler::_getVInameFromPort(const GCF::TM::GCFPortInterface& port) const +{ + string viName(""); + if(_isVIclientPort(port)) { + bool found = false; + TStringRemotePortMap::const_iterator it = itsconnectedVIclientPorts.begin(); + while(!found && it != itsconnectedVIclientPorts.end()) { + found = (&port == it->second.get()); + if(found) { + viName = it->first; + } + ++it; + } + } + return (viName); +} + +#endif + +// +// _connectedHandler(port) +// +void MACScheduler::_connectedHandler(GCFPortInterface& port) +{ +} + +// +// _disconnectedHandler(port) +// +void MACScheduler::_disconnectedHandler(GCFPortInterface& port) +{ + string visd; + port.close(); +#if 0 + if(_isServerPort(itsVIparentPort,port)) { + LOG_FATAL("VI parent server closed"); + itsVIparentPort.open(); // server closed? reopen it + } + else if(_isVISDclientPort(port,visd)) { + LOG_FATAL(formatString("VI Startdaemon port disconnected: %s",visd.c_str())); + port.setTimer(3L); + } + else if(_isVIclientPort(port)) { + LOG_FATAL("VI client port disconnected"); + // do something with the nodeId? + } +#endif +} + + +}; +}; diff --git a/MAC/APL/MainCU/src/MACScheduler/MACScheduler.conf.in b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.conf.in new file mode 100644 index 00000000000..a52cc088449 --- /dev/null +++ b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.conf.in @@ -0,0 +1,53 @@ +mac.ns.MACScheduler.SAS_server.type=TCP +mac.ns.MACScheduler.SAS_server.host=lofar27 +mac.ns.MACScheduler.SAS_server.port=27000 +mac.ns.MACScheduler.VIparent_server.type=TCP +mac.ns.MACScheduler.VIparent_server.host=lofar27 +mac.ns.MACScheduler.VIparent_server.port=27100 + +mac.ns.CCU1_VIC_VIStartDaemon.server.type=TCP +mac.ns.CCU1_VIC_VIStartDaemon.server.host=lofar27 +mac.ns.CCU1_VIC_VIStartDaemon.server.port=27010 +mac.top.MACScheduler.CCU1_VIC_VIStartDaemon.remoteservice=CCU1_VIC_VIStartDaemon:server +mac.ns.CCU2_VIC_VIStartDaemon.server.type=TCP +mac.ns.CCU2_VIC_VIStartDaemon.server.host=ccu2 +mac.ns.CCU2_VIC_VIStartDaemon.server.port=27010 +mac.top.MACScheduler.CCU2_VIC_VIStartDaemon.remoteservice=CCU2_VIC_VIStartDaemon:server +mac.ns.CCU3_VIC_VIStartDaemon.server.type=TCP +mac.ns.CCU3_VIC_VIStartDaemon.server.host=ccu3 +mac.ns.CCU3_VIC_VIStartDaemon.server.port=27010 +mac.top.MACScheduler.CCU3_VIC_VIStartDaemon.remoteservice=CCU3_VIC_VIStartDaemon:server +mac.ns.CCU4_VIC_VIStartDaemon.server.type=TCP +mac.ns.CCU4_VIC_VIStartDaemon.server.host=ccu4 +mac.ns.CCU4_VIC_VIStartDaemon.server.port=27010 +mac.top.MACScheduler.CCU4_VIC_VIStartDaemon.remoteservice=CCU4_VIC_VIStartDaemon:server +mac.ns.CCU5_VIC_VIStartDaemon.server.type=TCP +mac.ns.CCU5_VIC_VIStartDaemon.server.host=ccu5 +mac.ns.CCU5_VIC_VIStartDaemon.server.port=27010 +mac.top.MACScheduler.CCU5_VIC_VIStartDaemon.remoteservice=CCU5_VIC_VIStartDaemon:server +mac.ns.CCU6_VIC_VIStartDaemon.server.type=TCP +mac.ns.CCU6_VIC_VIStartDaemon.server.host=ccu6 +mac.ns.CCU6_VIC_VIStartDaemon.server.port=27010 +mac.top.MACScheduler.CCU6_VIC_VIStartDaemon.remoteservice=CCU6_VIC_VIStartDaemon:server + +# new setup +OTDBusername = paulus +OTDBdatabasename = boskabouter +OTDBpassword = overeem +OTDBpollInterval = 5s + +QueuePeriod = 15m +ClaimPeriod = 2m + + +# +# should be obsolete +# +shareLocation=/opt/lofar/MAC/parametersets/ + +# +# Obsolete +# +#mac.apl.ams.CCU2.startDaemonHost=earth +#mac.apl.ams.CCU2.startDaemonPort=server +#mac.apl.ams.CCU2.startDaemonTask=CCU2_VIC_VIStartDaemon diff --git a/MAC/APL/MainCU/src/MACScheduler/MACScheduler.h b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.h new file mode 100644 index 00000000000..61d88949cae --- /dev/null +++ b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.h @@ -0,0 +1,181 @@ +//# MACScheduler.h: Interface between MAC and SAS. +//# +//# 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$ + +#ifndef MACScheduler_H +#define MACScheduler_H + +//# Includes +#include <boost/shared_ptr.hpp> + +//# GCF Includes +#include <GCF/PAL/GCF_MyPropertySet.h> +#include <GCF/TM/GCF_Port.h> +#include <GCF/TM/GCF_TCPPort.h> +#include <GCF/TM/GCF_Task.h> +#include <GCF/TM/GCF_Event.h> + +//# local includes +#include "APL/APLCommon/PropertySetAnswerHandlerInterface.h" +#include "APL/APLCommon/PropertySetAnswer.h" +#include "APL/APLCommon/APLCommonExceptions.h" +#include "APL/APLCommon/LogicalDevice_Protocol.ph" +#include "APL/APLCommon/StartDaemon_Protocol.ph" + +//# Common Includes +#include <Common/lofar_string.h> +#include <Common/lofar_vector.h> +#include <Common/LofarLogger.h> + +//# ACC Includes +#include <OTDB/OTDBconnection.h> +#include <OTDB/TreeMaintenance.h> +#include <OTDB/OTDBnode.h> +#include <APS/ParameterSet.h> + +// forward declaration + +namespace LOFAR { + namespace MCU { + +using GCF::TM::GCFTCPPort; +using GCF::TM::GCFEvent; +using GCF::TM::GCFPortInterface; +using GCF::TM::GCFTask; + + +class MACScheduler : public GCFTask, + APLCommon::PropertySetAnswerHandlerInterface +{ +public: + MACScheduler(); + ~MACScheduler(); + + // PropertySetAnswerHandlerInterface method + virtual void handlePropertySetAnswer(GCFEvent& answer); + + // During the initial state all connections with the other programs are made. + GCFEvent::TResult initial_state (GCFEvent& e, + GCFPortInterface& p); + + // In this state the last-registered state is compared with the current + // database-state and an appropriate recovery is made for each observation. + GCFEvent::TResult recover_state (GCFEvent& e, + GCFPortInterface& p); + + // Normal control mode. Watching the OTDB and controlling the observations. + GCFEvent::TResult active_state (GCFEvent& e, + GCFPortInterface& p); + +private: + // avoid copying + MACScheduler(const MACScheduler&); + MACScheduler& operator=(const MACScheduler&); + + void _connectedHandler(GCFPortInterface& port); + void _disconnectedHandler(GCFPortInterface& port); + void _doOTDBcheck(); + boost::shared_ptr<ACC::APS::ParameterSet> + readObservationParameters (OTDB::treeIDType ObsTreeID); + + typedef boost::shared_ptr<GCF::PAL::GCFMyPropertySet> GCFMyPropertySetPtr; + + APLCommon::PropertySetAnswer itsPropertySetAnswer; + GCFMyPropertySetPtr itsPropertySet; + +#if 0 + typedef GCFTCPPort TRemotePort; + + typedef boost::shared_ptr<GCFTCPPort> TTCPPortPtr; + typedef boost::shared_ptr<TRemotePort> TRemotePortPtr; + typedef vector<TTCPPortPtr> TTCPPortVector; + typedef vector<TRemotePortPtr> TRemotePortVector; + typedef map<string,TRemotePortPtr> TStringRemotePortMap; + typedef map<string,TTCPPortPtr> TStringTCPportMap; + + bool _isServerPort (const GCFPortInterface& server, + const GCFPortInterface& port) const; + bool _isVISDclientPort (const GCFPortInterface& port, + string& visd) const; + bool _isVIclientPort (const GCFPortInterface& port) const; + string _getVInameFromPort (const GCFPortInterface& port) const; + string _getShareLocation () const; + + void createChildsSections(OTDB::TreeMaintenance& tm, + int32 treeID, + OTDB::nodeIDType topItem, + const string& nodeName, + boost::shared_ptr<ACC::APS::ParameterSet> ps); + + void _schedule (const string& VIrootID, + GCFPortInterface* port=0); + void _updateSchedule (const string& VIrootID, + GCFPortInterface* port=0); + void _cancelSchedule (const string& VIrootID, + GCFPortInterface* port=0); + + TStringRemotePortMap m_VISDclientPorts; // connected VI StartD clients + string m_VIparentPortName; + TRemotePort m_VIparentPort; // parent for VI's + + // the vector and map both contain the child ports. The vector is used + // to cache the port at the moment of the accept. However, at that moment, + // the parent does not yet know the ID of that child. The child sends its + // ID in the CONNECT event and when that message is received, the port and ID + // are stored in the TPortMap. The map is used in all communication with the + // childs. + TRemotePortVector m_VIclientPorts; // created VI's + TStringRemotePortMap m_connectedVIclientPorts; // maps node ID's to ports +#endif + + // Administration of the ObservationControllers + typedef struct { + OTDB::treeIDType treeID; // tree in the OTDB + GCFTCPPort* port; // TCP connection with controller + uint16 state; // state the controller has + } ObsCntlr_t; + + // Map with all active ObservationControllers. + map<GCFTCPPort*, ObsCntlr_t> itsObsCntlrMap; + vector<GCFTCPPort*> itsObsCntlrPorts; + + // Ports for StartDaemon and ObservationControllers. + GCFTCPPort* itsSDclientPort; // connection to StartDaemon + GCFTCPPort* itsLDserverPort; // listener for ObsControllers + + // Second timer used for internal timing. + uint32 itsSecondTimer; // 1 second hardbeat + uint32 itsSDretryTimer; // for reconnecting to SD + + // Scheduling settings + uint32 itsQueuePeriod; // period between qeueuing and start + uint32 itsClaimPeriod; // period between claiming and start + + // OTDB related variables. + OTDB::OTDBconnection* itsOTDBconnection; // connection to the database + uint32 itsOTDBpollInterval; // itv between OTDB polls + int32 itsNextOTDBpolltime; // when next OTDB poll is scheduled + +}; + + };//MCU +};//LOFAR +#endif diff --git a/MAC/APL/MainCU/src/MACScheduler/MACScheduler.log_prop.in b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.log_prop.in new file mode 100644 index 00000000000..438f6f9039e --- /dev/null +++ b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.log_prop.in @@ -0,0 +1,44 @@ +# add your custom loggers and appenders here +# + +log4cplus.rootLogger=INFO, STDOUT + +log4cplus.logger.TRC=PUTJE +log4cplus.additivity.TRC=FALSE + +log4cplus.logger.MAC=DEBUG, STDOUT, FILE +log4cplus.additivity.MAC=FALSE + +log4cplus.logger.TRC.MAC=TRACE, FILE +log4cplus.additivity.TRC.MAC=FALSE + +log4cplus.appender.PUTJE=log4cplus::NullAppender + +log4cplus.appender.STDOUT=log4cplus::ConsoleAppender +log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout +log4cplus.appender.STDOUT.layout.ConversionPattern=%x %D{%d-%m-%y %H:%M:%S} %-5p %c{9} - %m [%.25l]%n +log4cplus.appender.STDOUT.logToStdErr=true +#log4cplus.appender.STDOUT.Threshold=WARN +#log4cplus.appender.STDOUT.filters.1=log4cplus::spi::LogLevelRangeFilter +#log4cplus.appender.STDOUT.filters.1.LogLevelMin=INFO +#log4cplus.appender.STDOUT.filters.1.LogLevelMax=FATAL +#log4cplus.appender.STDOUT.filters.1.AcceptOnMatch=true +#log4cplus.appender.STDOUT.filters.2=log4cplus::spi::DenyAllFilter + +log4cplus.appender.FILE=log4cplus::RollingFileAppender +log4cplus.appender.FILE.File=../log/MACScheduler.log +log4cplus.appender.FILE.MaxFileSize=5MB +log4cplus.appender.FILE.MaxBackupIndex=5 +log4cplus.appender.FILE.layout=log4cplus::PatternLayout +log4cplus.appender.FILE.layout.ConversionPattern=%x %D{%d-%m-%y %H:%M:%S} %-5p %c{3} - %m [%.25l]%n + +log4cplus.appender.XMLFILE=log4cplus::RollingFileAppender +log4cplus.appender.XMLFILE.File=../log/MACSchedulerlog.xml +log4cplus.appender.XMLFILE.MaxFileSize=5MB +log4cplus.appender.XMLFILE.MaxBackupIndex=5 +log4cplus.appender.XMLFILE.layout=log4cplus::XMLLayout + +log4cplus.appender.CHAINSAW=log4cplus::XMLSocketAppender +log4cplus.appender.CHAINSAW.host=localhost +log4cplus.appender.CHAINSAW.port=4448 +log4cplus.appender.CHAINSAW.layout=log4cplus::XMLLayout diff --git a/MAC/APL/MainCU/src/MACScheduler/MACSchedulerDefines.h b/MAC/APL/MainCU/src/MACScheduler/MACSchedulerDefines.h new file mode 100644 index 00000000000..23c036e3733 --- /dev/null +++ b/MAC/APL/MainCU/src/MACScheduler/MACSchedulerDefines.h @@ -0,0 +1,47 @@ +//# MACScheduler_Defines.h: preprocessor definitions of various constants +//# +//# Copyright (C) 2002-2003 +//# 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 MACScheduler_DEFINES_H +#define MACScheduler_DEFINES_H + +namespace LOFAR { + namespace MCU { + +#define MS_TASKNAME "MACScheduler" + +#define MS_PROPSET_NAME "MACScheduler" +#define MS_PROPSET_TYPE "TAplMacScheduler" + +#define PVSSNAME_MS_QUEUEPERIOD "QueuePeriod" +#define PVSSNAME_MS_CLAIMPERIOD "ClaimPeriod" + +// next lines should be defined somewhere in Common. +#define PVSSNAME_FSM_STATE "state" +#define PVSSNAME_FSM_ERROR "error" + +#define SN_STARTDAEMON "StartDaemon" +#define SN_STARTDAEMON_VERSION "V1" + +}; // MCU +}; // LOFAR + +#endif diff --git a/MAC/APL/MainCU/src/MACScheduler/MACSchedulerMain.cc b/MAC/APL/MainCU/src/MACScheduler/MACSchedulerMain.cc new file mode 100644 index 00000000000..87f6cd0e211 --- /dev/null +++ b/MAC/APL/MainCU/src/MACScheduler/MACSchedulerMain.cc @@ -0,0 +1,38 @@ +//# VirtualInstrumentStartDaemonMain.cc: Main entry for the VirtualInstrument start daemon +//# +//# Copyright (C) 2002-2005 +//# 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 "MACScheduler.h" + +int main(int argc, char* argv[]) +{ + LOFAR::GCF::TM::GCFTask::init(argc, argv); + + LOFAR::MCU::MACScheduler ms; + ms.start(); // make initial transition + + LOFAR::GCF::TM::GCFTask::run(); + + return 0; +} + diff --git a/MAC/APL/MainCU/src/MACScheduler/Makefile.am b/MAC/APL/MainCU/src/MACScheduler/Makefile.am new file mode 100644 index 00000000000..2b02b395772 --- /dev/null +++ b/MAC/APL/MainCU/src/MACScheduler/Makefile.am @@ -0,0 +1,44 @@ +bin_PROGRAMS = MACScheduler + +MACScheduler_CPPFLAGS = -DBOOST_DISABLE_THREADS \ + -Wno-deprecated \ + -fmessage-length=0 \ + -fdiagnostics-show-location=once + +MACScheduler_SOURCES = MACScheduler.cc \ + MACSchedulerMain.cc \ + LogicalDeviceState.cc +MACScheduler_LDADD = -lpqxx $(LOFAR_DEPEND) +MACScheduler_DEPENDENCIES = $(LOFAR_DEPEND) + +NOINSTHDRS = MACScheduler.h \ + MACSchedulerDefines.h + +INSTHDRS = LogicalDeviceState.h + +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 = customPrepPVSSDB.ctl + +sysconf_DATA = MACScheduler.conf \ + MACScheduler.log_prop + +%.log_prop: %.log_prop.in + cp $< $@ + +%.conf: %.conf.in + cp $< $@ + +%.ctl: %.ctl.in + cp $< $@ + +clean-local: + rm -f *.ph + +include $(top_srcdir)/Makefile.common diff --git a/MAC/APL/MainCU/src/MACScheduler/customPrepPVSSDB.ctl.in b/MAC/APL/MainCU/src/MACScheduler/customPrepPVSSDB.ctl.in new file mode 100644 index 00000000000..f057aa4833e --- /dev/null +++ b/MAC/APL/MainCU/src/MACScheduler/customPrepPVSSDB.ctl.in @@ -0,0 +1,17 @@ +// this script must reside in the <PVSS project>/scripts directory +main() +{ + // create an enabled flag for CCU_PIC + dpCreate("PIC__enabled", "GCFPaPsEnabled"); + dpSet("PIC__enabled.","autoloaded|TCcuPic"); + dpCreate("PIC_Stations__enabled", "GCFPaPsEnabled"); + dpSet("PIC_Stations__enabled.","autoloaded|TCcuPic"); + dpCreate("PIC_CEP__enabled", "GCFPaPsEnabled"); + dpSet("PIC_CEP__enabled.","autoloaded|TCcuCep"); + dpCreate("GSO__enabled", "GCFPaPsEnabled"); + dpSet("GSO__enabled.","autoloaded|TCcuPic"); + dpCreate("VIC__enabled", "GCFPaPsEnabled"); + dpSet("VIC__enabled.","autoloaded|TCcuPic"); + + dpDelete("GSO_MACScheduler"); +} diff --git a/MAC/APL/MainCU/src/Makefile.am b/MAC/APL/MainCU/src/Makefile.am new file mode 100644 index 00000000000..ae74088b44c --- /dev/null +++ b/MAC/APL/MainCU/src/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = MACScheduler + +include $(top_srcdir)/Makefile.common + diff --git a/MAC/APL/StationCU/src/StationControl/customPrepPVSSDB.ctl.in b/MAC/APL/StationCU/src/StationControl/customPrepPVSSDB.ctl.in new file mode 100644 index 00000000000..f057aa4833e --- /dev/null +++ b/MAC/APL/StationCU/src/StationControl/customPrepPVSSDB.ctl.in @@ -0,0 +1,17 @@ +// this script must reside in the <PVSS project>/scripts directory +main() +{ + // create an enabled flag for CCU_PIC + dpCreate("PIC__enabled", "GCFPaPsEnabled"); + dpSet("PIC__enabled.","autoloaded|TCcuPic"); + dpCreate("PIC_Stations__enabled", "GCFPaPsEnabled"); + dpSet("PIC_Stations__enabled.","autoloaded|TCcuPic"); + dpCreate("PIC_CEP__enabled", "GCFPaPsEnabled"); + dpSet("PIC_CEP__enabled.","autoloaded|TCcuCep"); + dpCreate("GSO__enabled", "GCFPaPsEnabled"); + dpSet("GSO__enabled.","autoloaded|TCcuPic"); + dpCreate("VIC__enabled", "GCFPaPsEnabled"); + dpSet("VIC__enabled.","autoloaded|TCcuPic"); + + dpDelete("GSO_MACScheduler"); +} -- GitLab