From bffb76e72ca7430bdf719a8a7104a7859fab9d9c Mon Sep 17 00:00:00 2001
From: blaakmeer <sdos@astron.nl>
Date: Thu, 14 Sep 2006 21:05:55 +0000
Subject: [PATCH] BugID: 803 First version of OfflineControl

---
 .../OfflineControl/CEPApplicationManager.cc   | 129 +++
 .../OfflineControl/CEPApplicationManager.h    | 230 +++++
 MAC/APL/CEPCU/src/OfflineControl/Makefile.am  |  38 +
 .../src/OfflineControl/OfflineControl.cc      | 853 ++++++++++++++++++
 .../CEPCU/src/OfflineControl/OfflineControl.h | 154 ++++
 .../OfflineControl/OfflineControl.log_prop.in |  20 +
 .../OfflineControl/OfflineControlDefines.h    |  43 +
 .../src/OfflineControl/OfflineControlMain.cc  |  52 ++
 8 files changed, 1519 insertions(+)
 create mode 100644 MAC/APL/CEPCU/src/OfflineControl/CEPApplicationManager.cc
 create mode 100644 MAC/APL/CEPCU/src/OfflineControl/CEPApplicationManager.h
 create mode 100644 MAC/APL/CEPCU/src/OfflineControl/Makefile.am
 create mode 100644 MAC/APL/CEPCU/src/OfflineControl/OfflineControl.cc
 create mode 100644 MAC/APL/CEPCU/src/OfflineControl/OfflineControl.h
 create mode 100644 MAC/APL/CEPCU/src/OfflineControl/OfflineControl.log_prop.in
 create mode 100644 MAC/APL/CEPCU/src/OfflineControl/OfflineControlDefines.h
 create mode 100644 MAC/APL/CEPCU/src/OfflineControl/OfflineControlMain.cc

diff --git a/MAC/APL/CEPCU/src/OfflineControl/CEPApplicationManager.cc b/MAC/APL/CEPCU/src/OfflineControl/CEPApplicationManager.cc
new file mode 100644
index 00000000000..89ce40b8011
--- /dev/null
+++ b/MAC/APL/CEPCU/src/OfflineControl/CEPApplicationManager.cc
@@ -0,0 +1,129 @@
+//#  CEPApplicationManager.cc: Implementation of the Virtual CEPApplicationManager 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 "CEPApplicationManager.h"
+
+namespace LOFAR
+{
+
+using namespace ACC::ALC;
+  
+  namespace CEPCU
+  {
+INIT_TRACER_CONTEXT(CEPApplicationManager, LOFARLOGGER_PACKAGE);
+
+     
+void CEPApplicationManager::workProc()
+{
+  if (_continuePoll)
+  {
+    _acClient.processACmsgFromServer();
+  }
+}
+
+void  CEPApplicationManager::handleAckMsg(ACCmd         cmd, 
+                                          uint16        result,
+                                          const string& info)
+{
+  LOG_INFO(formatString("command: %d, result: %d, info: %s", cmd, result, info.c_str()));
+  switch (cmd)
+  {
+    case ACCmdBoot:
+      if (result == AcCmdMaskOk)
+      {
+        _lastOkCmd = cmd;
+      }
+      _interface.appBooted(_procName, result);
+      break;
+
+    case ACCmdQuit:
+      if (result == AcCmdMaskOk && result == 0)
+      {
+        _continuePoll = false;
+      }
+      _interface.appQuitDone(_procName, result);
+      break;
+
+    case ACCmdDefine:
+      if (result == AcCmdMaskOk)
+      {
+        _lastOkCmd = cmd;
+      }
+      _interface.appDefined(_procName, result);
+      break;
+
+    case ACCmdInit:
+      if (result == AcCmdMaskOk)
+      {
+        _lastOkCmd = cmd;
+      }
+      _interface.appInitialized(_procName, result);
+      break;
+
+    case ACCmdPause:
+      _interface.appPaused(_procName, result);
+      break;
+
+    case ACCmdRun:
+      if (result == AcCmdMaskOk)
+      {
+        _lastOkCmd = cmd;
+      }
+      _interface.appRunDone(_procName, result);
+      break;
+
+    case ACCmdSnapshot:
+      _interface.appSnapshotDone(_procName, result);
+      break;
+
+    case ACCmdRecover:
+      _interface.appRecovered(_procName, result);
+      break;
+
+    case ACCmdReinit:
+      _interface.appReinitialized(_procName, result);
+      break;
+
+    case ACCmdReplace:
+      _interface.appReplaced(_procName, result);
+      break;
+
+    default:
+      LOG_WARN_STR("Received command = " << cmd << ", result = " << result
+          << ", info = " << info << " not handled!");
+      break;
+  }
+}                                                
+
+void  CEPApplicationManager::handleAnswerMsg   (const string& answer)
+{
+  _interface.appSupplyInfoAnswer(_procName, answer);
+}
+
+string  CEPApplicationManager::supplyInfoFunc  (const string& keyList)
+{
+  return _interface.appSupplyInfo(_procName, keyList);
+}
+
+  } // namespace CEPCU
+} // namespace LOFAR
diff --git a/MAC/APL/CEPCU/src/OfflineControl/CEPApplicationManager.h b/MAC/APL/CEPCU/src/OfflineControl/CEPApplicationManager.h
new file mode 100644
index 00000000000..0a0c45ab36e
--- /dev/null
+++ b/MAC/APL/CEPCU/src/OfflineControl/CEPApplicationManager.h
@@ -0,0 +1,230 @@
+//#  CEPApplicationManager.h: factory class for Virtual Backends.
+//#
+//#  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$
+
+#ifndef CEPAPPLICATIONMANAGER_H
+#define CEPAPPLICATIONMANAGER_H
+
+//# Includes
+#include <ALC/ACAsyncClient.h>
+#include <GCF/TM/GCF_Handler.h>
+
+//# local includes
+//# Common Includes
+
+// forward declaration
+
+namespace LOFAR
+{  
+  namespace CEPCU
+  {
+
+class CEPApplicationManagerInterface
+{
+  protected:
+    CEPApplicationManagerInterface() {}
+
+  public:
+    virtual ~CEPApplicationManagerInterface() {}
+    
+  public:
+    virtual void    appBooted(const string& procName, uint16 result) = 0;
+    virtual void    appDefined(const string& procName, uint16 result) = 0;
+    virtual void    appInitialized(const string& procName, uint16 result) = 0;
+    virtual void    appRunDone(const string& procName, uint16 result) = 0;
+    virtual void    appPaused(const string& procName, uint16 result) = 0;
+    virtual void    appQuitDone(const string& procName, uint16 result) = 0;
+    virtual void    appSnapshotDone(const string& procName, uint16 result) = 0;
+    virtual void    appRecovered(const string& procName, uint16 result) = 0;
+    virtual void    appReinitialized(const string& procName, uint16 result) = 0;
+    virtual void    appReplaced(const string& procName, uint16 result) = 0;
+    virtual string  appSupplyInfo(const string& procName, const string& keyList) = 0;
+    virtual void    appSupplyInfoAnswer(const string& procName, const string& answer) = 0;    
+
+  private:
+    // protected copy constructor
+    CEPApplicationManagerInterface(const CEPApplicationManagerInterface&);
+    // protected assignment operator
+    CEPApplicationManagerInterface& operator=(const CEPApplicationManagerInterface&);
+};
+
+class CEPApplicationManager : public ACC::ALC::ACClientFunctions,
+                                     GCF::TM::GCFHandler
+{
+  public:
+    CEPApplicationManager(CEPApplicationManagerInterface& interface, const string& appName);
+    virtual ~CEPApplicationManager();
+    
+  public: // methods may be called from specialized CEPApplicationManagerInterface
+    bool  boot     (const time_t    scheduleTime,
+                    const string&   configID);
+    bool  define   (const time_t    scheduleTime)  const;
+    bool  init     (const time_t    scheduleTime)  const;
+    bool  run      (const time_t    scheduleTime)  const;
+    bool  pause    (const time_t    scheduleTime,
+                    const time_t    maxWaitTime,
+                    const string&   condition)     const;
+    bool  quit     (const time_t    scheduleTime)  const;
+    bool  shutdown (const time_t    scheduleTime)  const;
+    bool  snapshot (const time_t    scheduleTime,
+                    const string&   destination)   const;
+    bool  recover  (const time_t    scheduleTime,
+                    const string&   source)        const;
+    bool  reinit   (const time_t    scheduleTime,
+                    const string&   configID)      const;
+    bool  replace  (const time_t    scheduleTime,
+                    const string&   processList,
+                    const string&   nodeList,
+                    const string&   configID)      const;
+    string  askInfo (const string&  keylist)       const;    
+    bool  cancelCmdQueue ()                        const;    
+    ACC::ALC::ACCmd getLastOkCmd()                 const;
+     
+  private: // implemenation of abstract GCFHandler methods
+    friend class GCF::TM::GCFHandler;
+    void workProc();    
+    void stop();
+  
+  private: // implemenation of abstract ACClientFunctions methods
+    friend class ACC::ALC::ACClientFunctions;
+    void  handleAckMsg      (ACC::ALC::ACCmd    cmd, 
+                             uint16        result,
+                             const string& info);
+  
+    void  handleAnswerMsg   (const string& answer);
+  
+    string  supplyInfoFunc  (const string& keyList);
+    
+  protected:
+    // protected copy constructor
+    CEPApplicationManager(const CEPApplicationManager&);
+    // protected assignment operator
+    CEPApplicationManager& operator=(const CEPApplicationManager&);
+
+  private:
+    CEPApplicationManagerInterface& _interface;
+    ACC::ALC::ACAsyncClient         _acClient;
+    bool                            _continuePoll;
+    ACC::ALC::ACCmd                 _lastOkCmd;
+	string                          _procName;
+    
+    ALLOC_TRACER_CONTEXT  
+};
+
+inline CEPApplicationManager::CEPApplicationManager(
+                                    CEPApplicationManagerInterface& interface, 
+                                    const string& appName) :
+      _interface(interface),
+	  _acClient(this, appName, 10, 100, 1, 0),
+      _continuePoll(false),
+	  _lastOkCmd(ACC::ALC::ACCmdNone),
+      _procName(appName)
+{ 
+  use(); // to avoid that this object will be deleted in GCFTask::stop;
+}
+
+inline CEPApplicationManager::~CEPApplicationManager()
+{
+  GCFTask::deregisterHandler(*this);
+}
+
+inline bool  CEPApplicationManager::boot     (const time_t    scheduleTime,
+                                              const string&   configID)      
+{
+  _continuePoll = true;  
+  return _acClient.boot(scheduleTime, configID);
+}
+                                              
+inline bool  CEPApplicationManager::define   (const time_t    scheduleTime)  const
+{
+  return _acClient.define(scheduleTime);
+}
+ 
+inline bool  CEPApplicationManager::init     (const time_t    scheduleTime)  const
+{
+  return _acClient.init(scheduleTime);  
+}
+ 
+inline bool  CEPApplicationManager::run      (const time_t    scheduleTime)  const
+{
+  return _acClient.run(scheduleTime);  
+}
+ 
+inline bool  CEPApplicationManager::pause    (const time_t    scheduleTime,
+                                              const time_t    maxWaitTime,
+                                              const string&   condition)     const
+{
+  return _acClient.pause(scheduleTime, maxWaitTime, condition);  
+}
+ 
+inline bool  CEPApplicationManager::quit     (const time_t    scheduleTime)  const
+{
+  return _acClient.quit(scheduleTime);
+}
+ 
+inline bool  CEPApplicationManager::shutdown (const time_t    scheduleTime)  const
+{
+  return _acClient.shutdown(scheduleTime);
+}
+ 
+inline bool  CEPApplicationManager::snapshot (const time_t    scheduleTime,
+                                              const string&   destination)   const
+{
+  return _acClient.snapshot(scheduleTime, destination);
+}
+ 
+inline bool  CEPApplicationManager::recover  (const time_t    scheduleTime,
+                                              const string&   source)        const
+{
+  return _acClient.recover(scheduleTime, source);
+}
+ 
+inline bool  CEPApplicationManager::reinit   (const time_t    scheduleTime,
+                                              const string&   configID)      const
+{
+  return _acClient.reinit(scheduleTime, configID);
+}
+ 
+inline bool  CEPApplicationManager::replace  (const time_t    scheduleTime,
+                                              const string&   processList,
+                                              const string&   nodeList,
+                                              const string&   configID)      const
+{
+  return _acClient.replace(scheduleTime, processList, nodeList, configID);
+}
+ 
+inline bool  CEPApplicationManager::cancelCmdQueue ()                       const
+{
+  return _acClient.cancelCmdQueue();
+}
+ 
+inline ACC::ALC::ACCmd CEPApplicationManager::getLastOkCmd() const 
+{
+  return _lastOkCmd;
+}
+
+inline void CEPApplicationManager::stop()
+{
+}
+
+  } // namespace CEPCU
+} // namespace LOFAR
+#endif
diff --git a/MAC/APL/CEPCU/src/OfflineControl/Makefile.am b/MAC/APL/CEPCU/src/OfflineControl/Makefile.am
new file mode 100644
index 00000000000..106bb28c82f
--- /dev/null
+++ b/MAC/APL/CEPCU/src/OfflineControl/Makefile.am
@@ -0,0 +1,38 @@
+bin_PROGRAMS 				= OfflineControl
+
+OfflineControl_CPPFLAGS		= -Wno-deprecated \
+								  -fmessage-length=0 \
+								  -fdiagnostics-show-location=once
+
+OfflineControl_SOURCES		= CEPApplicationManager.cc \
+								OfflineControl.cc \
+								OfflineControlMain.cc 
+
+OfflineControl_LDADD		= $(LOFAR_DEPEND)
+OfflineControl_DEPENDENCIES	= $(LOFAR_DEPEND)
+
+NOINSTHDRS 					= CEPApplicationManager.h \
+								OfflineControl.h \
+							  	OfflineControlDefines.h
+
+INSTHDRS 					= 
+
+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		= OfflineControl.log_prop
+
+%.log_prop: %.log_prop.in
+	cp $< $@
+
+clean-local:
+	rm -f *.ph
+
+include $(top_srcdir)/Makefile.common
diff --git a/MAC/APL/CEPCU/src/OfflineControl/OfflineControl.cc b/MAC/APL/CEPCU/src/OfflineControl/OfflineControl.cc
new file mode 100644
index 00000000000..1b02f12aaf2
--- /dev/null
+++ b/MAC/APL/CEPCU/src/OfflineControl/OfflineControl.cc
@@ -0,0 +1,853 @@
+//#  OfflineControl.cc: Implementation of the MAC Scheduler task
+//#
+//#  Copyright (C) 2006
+//#  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 <APS/Exceptions.h>
+#include <GCF/GCF_PVTypes.h>
+#include <GCF/PAL/GCF_PVSSInfo.h>
+#include <GCF/Utils.h>
+#include <GCF/GCF_ServiceInfo.h>
+#include <GCF/Protocols/PA_Protocol.ph>
+#include <APL/APLCommon/APL_Defines.h>
+#include <APL/APLCommon/APLUtilities.h>
+#include <APL/APLCommon/APLCommonExceptions.h>
+#include <APL/APLCommon/Controller_Protocol.ph>
+#include <APL/APLCommon/StationInfo.h>
+#include <APL/APLCommon/APLUtilities.h>
+
+#include "OfflineControl.h"
+#include "OfflineControlDefines.h"
+
+using namespace LOFAR::GCF::Common;
+using namespace LOFAR::GCF::TM;
+using namespace LOFAR::GCF::PAL;
+using namespace std;
+
+namespace LOFAR {
+	using namespace APLCommon;
+	using namespace ACC::APS;
+    using namespace ACC::ALC;
+	namespace CEPCU {
+	
+//
+// OfflineControl()
+//
+OfflineControl::OfflineControl(const string&	cntlrName) :
+	GCFTask 			((State)&OfflineControl::initial_state,cntlrName),
+	PropertySetAnswerHandlerInterface(),
+	itsPropertySetAnswer(*this),
+	itsPropertySet		(),
+	itsPropertySetInitialized (false),
+	itsParentControl	(0),
+	itsParentPort		(0),
+	itsTimerPort		(0),
+    itsCepApplications  (),
+	itsCepAppParams     (),
+	itsResultParams     (),
+	itsProcessDependencies(),
+	itsState			(CTState::NOSTATE),
+	itsTreePrefix       (""),
+	itsInstanceNr       (0),
+	itsStartTime        (),
+	itsStopTime         (),
+	itsClaimPeriod      (),
+	itsPreparePeriod    (),
+	itsCntlrName        (cntlrName)
+{
+	LOG_TRACE_OBJ_STR (cntlrName << " construction");
+
+	// First readin our observation related config file.
+	LOG_DEBUG_STR("Reading parset file:" << LOFAR_SHARE_LOCATION << "/" << cntlrName);
+	globalParameterSet()->adoptFile(string(LOFAR_SHARE_LOCATION)+"/"+cntlrName);
+
+
+	// Readin some parameters from the ParameterSet.
+	itsTreePrefix = globalParameterSet()->getString("prefix");
+	itsInstanceNr = globalParameterSet()->getUint32("_instanceNr");
+
+	// get Observation based information
+	itsStartTime     = time_from_string(globalParameterSet()->
+											 getString("Observation.startTime"));
+	itsStopTime      = time_from_string(globalParameterSet()->
+											 getString("Observation.stopTime"));
+	itsClaimPeriod   = globalParameterSet()->getTime  ("Observation.claimPeriod");
+	itsPreparePeriod = globalParameterSet()->getTime  ("Observation.preparePeriod");
+
+	// attach to parent control task
+	itsParentControl = ParentControl::instance();
+	itsParentPort = new GCFITCPort (*this, *itsParentControl, "ParentITCport", 
+									GCFPortInterface::SAP, CONTROLLER_PROTOCOL);
+	ASSERTSTR(itsParentPort, "Cannot allocate ITCport for Parentcontrol");
+	itsParentPort->open();		// will result in F_CONNECTED
+
+	// need port for timers.
+	itsTimerPort = new GCFTimerPort(*this, "TimerPort");
+
+	// for debugging purposes
+	registerProtocol (CONTROLLER_PROTOCOL, CONTROLLER_PROTOCOL_signalnames);
+	registerProtocol (PA_PROTOCOL, 		   PA_PROTOCOL_signalnames);
+
+	setState(CTState::CREATED);
+}
+
+
+//
+// ~OfflineControl()
+//
+OfflineControl::~OfflineControl()
+{
+	LOG_TRACE_OBJ_STR (getName() << " destruction");
+
+	if (itsPropertySet) {
+		itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("down"));
+		itsPropertySet->disable();
+	}
+
+	// ...
+}
+
+//
+// setState(CTstateNr)
+//
+void    OfflineControl::setState(CTState::CTstateNr     newState)
+{
+	itsState = newState;
+
+	if (itsPropertySet) {
+		CTState		cts;
+		itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),
+								 GCFPVString(cts.name(newState)));
+	}
+}   
+
+
+//
+// handlePropertySetAnswer(answer)
+//
+void OfflineControl::handlePropertySetAnswer(GCFEvent& answer)
+{
+	LOG_DEBUG_STR ("handlePropertySetAnswer:" << evtstr(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));
+		}
+		// always let timer expire so main task will continue.
+		itsTimerPort->setTimer(1.0);
+		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.
+		break;
+	}  
+
+//	case F_SUBSCRIBED:
+//	case F_UNSUBSCRIBED:
+//	case F_PS_CONFIGURED:
+//	case F_EXTPS_LOADED:
+//	case F_EXTPS_UNLOADED:
+//	case F_MYPS_ENABLED:
+//	case F_MYPS_DISABLED:
+//	case F_VGETRESP:
+//	case F_VCHANGEMSG:
+//	case F_SERVER_GONE:
+
+	default:
+		break;
+	}  
+}
+
+
+//
+// initial_state(event, port)
+//
+// Setup all connections.
+//
+GCFEvent::TResult OfflineControl::initial_state(GCFEvent& event, 
+													GCFPortInterface& port)
+{
+	LOG_DEBUG_STR ("initial:" << evtstr(event) << "@" << port.getName());
+
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+  
+	switch (event.signal) {
+	case F_ENTRY:
+   		break;
+
+    case F_INIT: {
+		// Get access to my own propertyset.
+		LOG_DEBUG ("Activating PropertySet");
+		string	propSetName = formatString(ONC_PROPSET_NAME, itsInstanceNr);
+		itsPropertySet = GCFMyPropertySetPtr(new GCFMyPropertySet(propSetName.c_str(),
+																  ONC_PROPSET_TYPE,
+																  PS_CAT_TEMPORARY,
+																  &itsPropertySetAnswer));
+		itsPropertySet->enable();
+		// Wait for timer that is set in PropertySetAnswer on ENABLED event
+		}
+		break;
+
+	case F_TIMER:
+		if (!itsPropertySetInitialized) {
+			itsPropertySetInitialized = true;
+
+			// update PVSS.
+			LOG_TRACE_FLOW ("Updateing state to PVSS");
+			itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("initial"));
+			itsPropertySet->setValue(string(PVSSNAME_FSM_ERROR),GCFPVString(""));
+		  
+			// Start ParentControl task
+			LOG_DEBUG ("Enabling ParentControl task");
+			itsParentPort = itsParentControl->registerTask(this);
+
+			LOG_DEBUG ("Going to operational state");
+			TRAN(OfflineControl::active_state);				// go to next state.
+		}
+		break;
+
+	case F_CONNECTED:
+		ASSERTSTR (&port == itsParentPort, 
+									"F_CONNECTED event from port " << port.getName());
+		break;
+
+	case F_DISCONNECTED:
+		break;
+	
+	default:
+		LOG_DEBUG_STR ("initial, default");
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}    
+	return (status);
+}
+
+
+//
+// active_state(event, port)
+//
+// Normal operation state. 
+//
+GCFEvent::TResult OfflineControl::active_state(GCFEvent& event, GCFPortInterface& port)
+{
+	LOG_DEBUG_STR ("active:" << evtstr(event) << "@" << port.getName());
+
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+
+	switch (event.signal) {
+	case F_ENTRY: {
+		// update PVSS
+		itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("active"));
+		itsPropertySet->setValue(string(PVSSNAME_FSM_ERROR),GCFPVString(""));
+		break;
+	}
+
+	case F_INIT:
+		break;
+
+	case F_ACCEPT_REQ:
+		break;
+
+	case F_CONNECTED: {
+		ASSERTSTR (&port == itsParentPort, "F_CONNECTED event from port " << port.getName());
+		break;
+	}
+
+	case F_DISCONNECTED: {
+		port.close();
+		break;
+	}
+
+	case F_TIMER: 
+//		GCFTimerEvent& timerEvent=static_cast<GCFTimerEvent&>(event);
+		break;
+
+	// -------------------- EVENTS RECEIVED FROM PARENT CONTROL --------------------
+	case CONTROL_CONNECT: {
+		CONTROLConnectEvent		msg(event);
+		LOG_DEBUG_STR("Received CONNECT(" << msg.cntlrName << ")");
+		setState(CTState::CONNECTED);
+		CONTROLConnectedEvent	answer;
+		answer.cntlrName = msg.cntlrName;
+		port.send(answer);
+		break;
+	}
+
+	case CONTROL_SCHEDULED: {
+		CONTROLScheduledEvent		msg(event);
+		LOG_DEBUG_STR("Received SCHEDULED(" << msg.cntlrName << ")");
+		// TODO: do something usefull with this information!
+		break;
+	}
+
+	case CONTROL_CLAIM: {
+		CONTROLClaimEvent		msg(event);
+		LOG_DEBUG_STR("Received CLAIM(" << msg.cntlrName << ")");
+		setState(CTState::CLAIM);
+		setState(CTState::CLAIMED);
+		CONTROLClaimedEvent             answer;
+		answer.cntlrName = getName();
+		answer.result    = doClaim(msg.cntlrName);
+		if(answer.result == CT_RESULT_NO_ERROR) 
+		{
+		  setState(CTState::CLAIMED);
+		}
+		port.send(answer);
+		
+		break;
+	}
+
+	case CONTROL_PREPARE: {
+		CONTROLPrepareEvent		msg(event);
+		LOG_DEBUG_STR("Received PREPARE(" << msg.cntlrName << ")");
+		setState(CTState::PREPARE);
+		CONTROLPreparedEvent    answer;
+		answer.cntlrName = getName();
+		answer.result    = doPrepare(msg.cntlrName);
+		if(answer.result == CT_RESULT_NO_ERROR) 
+		{
+		  setState(CTState::PREPARED);
+		}
+		port.send(answer);
+		break;
+	}
+
+	case CONTROL_RESUME: {
+		CONTROLResumeEvent		msg(event);
+		LOG_DEBUG_STR("Received RESUME(" << msg.cntlrName << ")");
+		setState(CTState::ACTIVE);
+		// TODO: implement something useful
+		CONTROLResumedEvent		answer;
+		answer.cntlrName = msg.cntlrName;
+		port.send(answer);
+		break;
+	}
+
+	case CONTROL_SUSPEND: {
+		CONTROLSuspendEvent		msg(event);
+		LOG_DEBUG_STR("Received SUSPEND(" << msg.cntlrName << ")");
+		setState(CTState::SUSPENDED);
+		// TODO: implement something useful
+		CONTROLSuspendedEvent		answer;
+		answer.cntlrName = msg.cntlrName;
+		port.send(answer);
+		break;
+	}
+
+	case CONTROL_RELEASE: {
+		CONTROLReleaseEvent		msg(event);
+		LOG_DEBUG_STR("Received RELEASE(" << msg.cntlrName << ")");
+		setState(CTState::RELEASE);
+		doRelease();
+		setState(CTState::RELEASED);
+		CONTROLReleasedEvent	answer;
+		answer.cntlrName = msg.cntlrName;
+		port.send(answer);
+		break;
+	}
+
+	default:
+		LOG_DEBUG("active_state, default");
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	return (status);
+}
+
+//
+// finished_state(event, port)
+//
+// Finishing state. 
+//
+GCFEvent::TResult OfflineControl::finished_state(GCFEvent& event, GCFPortInterface& port)
+{
+	LOG_DEBUG_STR ("active:" << evtstr(event) << "@" << port.getName());
+
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+
+	switch (event.signal) {
+	case F_ENTRY: {
+      GCFTask::stop();
+      break;
+	}
+	default:
+		LOG_DEBUG("active_state, default");
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	return (status);
+}
+
+
+
+
+//
+// doPrepare(cntlrName)
+//
+uint16_t OfflineControl::doClaim(const string& cntlrName)
+{
+  uint16_t result = CT_RESULT_NO_ERROR;
+  try
+  {
+	string processScope("AC.process");
+	string offlineCtrlPrefix(globalParameterSet()->locateModule("OfflineCtrl") + "OfflineCtrl.");
+  
+	vector<string> procNames, nodes;
+	string executable, hostName, startstoptype;
+	string ldName(getName().c_str());
+	
+	procNames = globalParameterSet()->getStringVector(offlineCtrlPrefix+"ApplCtrl.ACCprocess.name");
+
+	for(size_t i=0;i<procNames.size();i++)
+	{
+	  string procName = procNames[i];
+
+	  startstoptype = globalParameterSet()->getString(formatString("%sApplCtrl.%s.startstopType",
+																   offlineCtrlPrefix.c_str(),
+																   procName.c_str()));
+	  executable    = globalParameterSet()->getString(formatString("%sApplCtrl.%s.executable",
+																   offlineCtrlPrefix.c_str(),
+																   procName.c_str()));
+	  hostName      = globalParameterSet()->getString(formatString("%sApplCtrl.%s.hostname",
+																   offlineCtrlPrefix.c_str(),
+																   procName.c_str()));
+	  nodes   = globalParameterSet()->getStringVector(formatString("%sApplCtrl.%s.nodes",
+																   offlineCtrlPrefix.c_str(),
+																   procName.c_str()));
+	  itsProcessDependencies[procName] = globalParameterSet()->getStringVector(formatString("%sApplCtrl.%s.depends",
+																							offlineCtrlPrefix.c_str(),
+																							procName.c_str()));
+
+	  CEPApplicationManagerPtr accClient(new CEPApplicationManager(*this, procName));
+	  itsCepApplications[procName] = accClient;
+	  
+	  ACC::APS::ParameterSet params;
+	  params.clear();
+	  params.replace("AC.application", cntlrName);
+	  // import the ApplCtrl section
+	  params.adoptCollection(globalParameterSet()->makeSubset(offlineCtrlPrefix+"ApplCtrl", "AC"));
+	  // import the <procname> section
+	  params.adoptCollection(globalParameterSet()->makeSubset(offlineCtrlPrefix+procName, procName));
+	  // import the OLAP section
+	  params.adoptCollection(globalParameterSet()->makeSubset(offlineCtrlPrefix+"OLAP", "OLAP"));
+	  
+	  // add some keys to cope with the differences between the OTDB and ACC
+	  params.replace("AC.resultfile", formatString("./ACC-%s_%s_result.param", cntlrName.c_str(),procName.c_str()));
+	  params.replace("AC.process[0].count","1");
+	  params.replace("AC.application",procName);
+	  params.replace("AC.process[1].ID",procName);
+	  params.replace("AC.hostname",hostName);
+	  params.replace(formatString("%s.%s[0].startstoptype",procName.c_str(),procName.c_str()),startstoptype);
+	  params.replace(formatString("%s.%s[0].executable",procName.c_str(),procName.c_str()),executable);
+
+	  // create nodelist
+	  int nodeIndex=1;
+	  for(vector<string>::iterator it=nodes.begin();it!=nodes.end();++it)
+	  {
+		params.replace(formatString("AC.%s[%d].node",procName.c_str(),nodeIndex++),*it);
+	  }
+	  itsCepAppParams[procName] = params;
+	}
+  }
+  catch(APSException &)
+  {
+	// key not found. skip
+	result = CT_RESULT_UNSPECIFIED;
+  }
+  return result;
+}
+
+//
+// doPrepare(cntlrName)
+//
+uint16_t OfflineControl::doPrepare(const string& cntlrName)
+{
+  uint16_t result = CT_RESULT_NO_ERROR;
+
+  try
+  {
+	map<string, ACC::APS::ParameterSet>::iterator it;
+	for(it = itsCepAppParams.begin(); it != itsCepAppParams.end();++it)
+	{
+	  // only start processes that do not depend on other processes
+	  // other process will start once the processes they depend on have finished
+	  if(itsProcessDependencies[it->first].size() == 0)
+	  {
+		prepareProcess(cntlrName, it->first, to_time_t(itsStartTime));
+	  }
+	}
+  }
+  catch(APSException &)
+  {
+	// key not found. skip
+	result = CT_RESULT_UNSPECIFIED;
+  }
+  return result;
+}
+
+//
+// _prepareProcess(procName, startTime)
+//
+void OfflineControl::prepareProcess(const string& cntlrName, const string& procName, const time_t startTime)
+{
+  map<string, ACC::APS::ParameterSet>::iterator it = itsCepAppParams.find(procName);
+  if(it != itsCepAppParams.end())
+  {
+	string procName = it->second.getString("AC.process[1].ID");
+	string hostName = it->second.getString("AC.hostname");
+	string paramFileName(formatString("ACC-%s_%s.param", cntlrName.c_str(),procName.c_str()));
+	it->second.writeFile(paramFileName);
+  
+	// schedule all ACC commands
+	time_t initTime   = startTime  - it->second.getTime("AC.timeout_init");
+	time_t defineTime = initTime   - it->second.getTime("AC.timeout_define") - 
+	                                 it->second.getTime("AC.timeout_startup");
+	time_t bootTime   = defineTime - it->second.getTime("AC.timeout_createsubsets");
+	time_t now = time(0);
+	time_t stopTime = to_time_t(itsStopTime);
+	LOG_DEBUG(formatString("%d now %s time %d", now,        ctime(&now), time(0)));
+	LOG_DEBUG(formatString("%d boot %s",        bootTime,   ctime(&bootTime)));
+	LOG_DEBUG(formatString("%d define %s",      defineTime, ctime(&defineTime)));
+	LOG_DEBUG(formatString("%d init %s",        initTime,   ctime(&initTime)));
+	LOG_DEBUG(formatString("%d start %s",       startTime,  ctime(&startTime)));
+	LOG_DEBUG(formatString("%d stop %s",        stopTime,   ctime(&stopTime)));
+	
+	if (now > bootTime)
+	{
+	  APLCommon::APLUtilities::remoteCopy(paramFileName,hostName,LOFAR_SHARE_LOCATION);
+	  LOG_WARN("Cannot guarantee all CEP processes are started in time.");
+	}
+	else
+	{
+	  CEPApplicationManagerPtr cepAppPtr = itsCepApplications[procName];
+	  if(NULL != cepAppPtr)
+	  {
+		switch (cepAppPtr->getLastOkCmd())
+		{
+		  case ACCmdNone:
+			cepAppPtr->boot(bootTime, paramFileName);
+			break;
+        
+		  case ACCmdBoot:
+			cepAppPtr->define(defineTime);
+			break;
+        
+		  case ACCmdDefine:
+          case ACCmdInit:
+		  case ACCmdRun:
+			cepAppPtr->recover(0, "snapshot-DB");
+			break;
+              
+		  default:
+			assert(0);
+			break;
+		}   
+	  } 
+	  APLCommon::APLUtilities::remoteCopy(paramFileName,hostName,LOFAR_SHARE_LOCATION);
+	}
+  }
+}
+
+//
+// doRelease()
+//
+void OfflineControl::doRelease(void)
+{
+  try
+  {
+	map<string, ACC::APS::ParameterSet>::iterator it;
+	for(it = itsCepAppParams.begin(); it != itsCepAppParams.end();++it)
+	{
+	  string hostName, remoteFile, resultFile, procName;
+	  hostName = it->second.getString("AC.hostname");
+	  procName = it->second.getString("AC.process[1].ID");
+	  resultFile = formatString("ACC-%s_%s_result.param", getName().c_str(),procName.c_str());
+	  remoteFile = string(LOFAR_SHARE_LOCATION) + string("/") + resultFile;
+	  APLCommon::APLUtilities::copyFromRemote(hostName,remoteFile,resultFile);
+	  itsResultParams.adoptFile(resultFile);
+	  //  itsResultParams.replace(KVpair(formatString("%s.quality", getName().c_str()), (int) _qualityGuard.getQuality()));
+	  if (!itsResultParams.isDefined(formatString("%s.faultyNodes", getName().c_str())))
+	  {
+		itsResultParams.add(formatString("%s.faultyNodes", getName().c_str()), "");
+	  }
+	  itsResultParams.writeFile(formatString("%s_result.param", getName().c_str()));
+	}
+  }
+  catch(...)
+  {
+  }
+  map<string, CEPApplicationManagerPtr>::iterator it;
+  for(it = itsCepApplications.begin();it != itsCepApplications.end();++it)
+  {
+	it->second->quit(0);
+  }
+}
+
+//
+// finishController
+//
+void OfflineControl::finishController(uint16_t /*result*/)
+{
+  setState(CTState::RELEASE);
+  doRelease();
+  setState(CTState::RELEASED);
+  LOG_DEBUG ("Going to finished state");
+  TRAN(OfflineControl::finished_state); // go to next state.
+}
+
+//
+// _connectedHandler(port)
+//
+void OfflineControl::_connectedHandler(GCFPortInterface& /*port*/)
+{
+}
+
+//
+// _disconnectedHandler(port)
+//
+void OfflineControl::_disconnectedHandler(GCFPortInterface& port)
+{
+	port.close();
+}
+
+void OfflineControl::appBooted(const string& procName, uint16 result)
+{
+  LOG_INFO_STR("appBooted from " << procName);
+  if (result == (AcCmdMaskOk | AcCmdMaskScheduled))  
+  {
+    time_t startTime  = to_time_t(itsStartTime);
+    time_t initTime   = startTime  - itsCepAppParams[0].getTime("AC.timeout_init");
+    time_t defineTime = initTime   - itsCepAppParams[0].getTime("AC.timeout_define") - 
+                                     itsCepAppParams[0].getTime("AC.timeout_startup");
+	map<string,CEPApplicationManagerPtr>::iterator it = itsCepApplications.find(procName);
+	if(it != itsCepApplications.end())
+	{
+	  it->second->define(defineTime);
+	}
+  }
+  else if (result == 0) // Error
+  {
+    LOG_ERROR("Error in ACC. Stops CEP application and releases Offline Control.");
+	finishController(CT_RESULT_UNSPECIFIED);
+  }
+}
+
+void OfflineControl::appDefined(const string& procName, uint16 result)
+{
+  LOG_INFO_STR("appDefined from " << procName);
+  if (result == (AcCmdMaskOk | AcCmdMaskScheduled))
+  {
+    time_t startTime  = to_time_t(itsStartTime);
+    time_t initTime   = startTime  - itsCepAppParams[0].getTime("AC.timeout_init");
+  
+	map<string,CEPApplicationManagerPtr>::iterator it =  itsCepApplications.find(procName);
+	if(it != itsCepApplications.end())
+	{
+	  it->second->init(initTime);
+	}
+  }
+  else if (result == 0) // Error
+  {
+    LOG_ERROR("Error in ACC. Stops CEP application and releases VB.");
+	finishController(CT_RESULT_UNSPECIFIED);
+  }
+}
+
+void OfflineControl::appInitialized(const string& procName, uint16 result)
+{
+  LOG_INFO_STR("appInitialized from " << procName);
+  if (result == AcCmdMaskOk)
+  {    
+	//    _doStateTransition(LOGICALDEVICE_STATE_SUSPENDED);
+  }
+  else if (result == (AcCmdMaskOk | AcCmdMaskScheduled))  
+  {
+	map<string,CEPApplicationManagerPtr>::iterator it =  itsCepApplications.find(procName);
+	if(it != itsCepApplications.end())
+	{
+	  it->second->run(to_time_t(itsStartTime));
+	}
+  }
+  else if (result == 0) // Error
+  {
+    LOG_ERROR("Error in ACC. Stops CEP application and releases VB.");
+	finishController(CT_RESULT_UNSPECIFIED);
+  }
+}
+
+void OfflineControl::appRunDone(const string& procName, uint16 result)
+{
+  LOG_INFO_STR("appRunDone from " << procName);
+  if (result == (AcCmdMaskOk | AcCmdMaskScheduled))
+  {      
+	map<string,CEPApplicationManagerPtr>::iterator it =  itsCepApplications.find(procName);
+	if(it != itsCepApplications.end())
+	{
+	  it->second->quit(to_time_t(itsStopTime));
+	}
+  }
+  else if (result == AcCmdMaskOk)
+  {
+	// Run done. Check if processes depend on this process.
+	map<string, vector<string> >::iterator it;
+	for(it = itsProcessDependencies.begin(); it != itsProcessDependencies.end();++it)
+	{
+	  if(it->second.size() > 0)
+	  {
+		for(vector<string>::iterator dIt = it->second.begin(); dIt != it->second.end(); ++dIt)
+		{
+		  if((*dIt) == procName)
+		  {
+			// This process depends on the process that just finished
+			// Remove the process from the dependencies list. 
+			it->second.erase(dIt);
+			// If the list is empty now, the new process can be started
+			if(it->second.size() == 0)
+			{
+			  // start the process in 5 seconds
+			  prepareProcess(itsCntlrName,it->first,time(0)+5);
+			}
+		  }
+		}
+	  }
+	}
+  }
+  else if (result == 0) // Error
+  {
+    LOG_ERROR("Error in ACC. Stops CEP application and releases VB.");
+	finishController(CT_RESULT_UNSPECIFIED);
+  }
+}
+
+void OfflineControl::appPaused(const string& procName, uint16 /*result*/)
+{
+  LOG_INFO_STR("appPaused from " << procName);
+}
+
+void OfflineControl::appQuitDone(const string& procName, uint16 result)
+{
+  LOG_INFO_STR("appQuitDone from " << procName);
+  if (result == (AcCmdMaskOk | AcCmdMaskScheduled))
+  {  
+    //_qualityGuard.stopMonitoring(); // not in this increment
+  }
+  else
+  {
+	finishController(CT_RESULT_NO_ERROR);
+  }
+}
+
+void OfflineControl::appSnapshotDone(const string& procName, uint16 /*result*/)
+{
+  LOG_INFO_STR("appSnapshotDone from " << procName);
+  time_t rsto(0);
+  try 
+  {
+    rsto = globalParameterSet()->getTime("rescheduleTimeOut");
+  }
+  catch (...) {}
+  map<string,CEPApplicationManagerPtr>::iterator it =  itsCepApplications.find(procName);
+  if(it != itsCepApplications.end())
+  {
+	it->second->pause(0, rsto, "condition");
+  }
+}
+
+void OfflineControl::appRecovered(const string& procName, uint16 /*result*/)
+{
+  LOG_INFO_STR("appRecovered from " << procName);
+  
+  time_t startTime  = to_time_t(itsStartTime);
+  time_t reinitTime = startTime  - itsCepAppParams[0].getTime("AC.timeout_reinit");
+  
+  string paramFileName(formatString("ACC-%s.param", getName().c_str()));
+  
+  map<string,CEPApplicationManagerPtr>::iterator it =  itsCepApplications.find(procName);
+  if(it != itsCepApplications.end())
+  {
+	it->second->reinit(reinitTime, paramFileName);
+  }
+}
+
+void OfflineControl::appReinitialized(const string& procName, uint16 result)
+{ 
+  LOG_INFO_STR("appReinitialized from " << procName);
+  if (result == AcCmdMaskOk)
+  {    
+	//    _doStateTransition(LOGICALDEVICE_STATE_SUSPENDED);
+  }
+  else if (result == (AcCmdMaskOk | AcCmdMaskScheduled))  
+  {  
+	map<string,CEPApplicationManagerPtr>::iterator it =  itsCepApplications.find(procName);
+	if(it != itsCepApplications.end())
+    {
+	  it->second->run(to_time_t(itsStartTime));
+	}
+  }
+}
+
+void OfflineControl::appReplaced(const string& procName, uint16 /*result*/)
+{
+  LOG_INFO_STR("appReplaced from " << procName);
+}
+
+string OfflineControl::appSupplyInfo(const string& procName, const string& keyList)
+{
+  LOG_INFO_STR("appSupplyInfo from " << procName);
+  string ret(keyList);
+  return ret;
+}
+
+void OfflineControl::appSupplyInfoAnswer(const string& procName, const string& answer)
+{
+  LOG_INFO_STR("Answer from " << procName << ": " << answer);
+}
+
+
+}; // CEPCU
+}; // LOFAR
diff --git a/MAC/APL/CEPCU/src/OfflineControl/OfflineControl.h b/MAC/APL/CEPCU/src/OfflineControl/OfflineControl.h
new file mode 100644
index 00000000000..7c3a477b86f
--- /dev/null
+++ b/MAC/APL/CEPCU/src/OfflineControl/OfflineControl.h
@@ -0,0 +1,154 @@
+//#  OfflineControl.h: Controller for the OfflineControl
+//#
+//#  Copyright (C) 2006
+//#  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 OFFLINECONTROL_H
+#define OFFLINECONTROL_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_ITCPort.h>
+#include <GCF/TM/GCF_TimerPort.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/Controller_Protocol.ph>
+#include <APL/APLCommon/ParentControl.h>
+#include <APL/APLCommon/CTState.h>
+
+#include <CEPApplicationManager.h>
+
+//# Common Includes
+#include <Common/lofar_string.h>
+#include <Common/lofar_vector.h>
+#include <Common/lofar_datetime.h>
+#include <Common/LofarLogger.h>
+
+//# ACC Includes
+#include <APS/ParameterSet.h>
+
+// forward declaration
+
+namespace LOFAR {
+	namespace CEPCU {
+
+using	GCF::TM::GCFTimerPort;
+using	GCF::TM::GCFITCPort;
+using	GCF::TM::GCFPort;
+using	GCF::TM::GCFEvent;
+using	GCF::TM::GCFPortInterface;
+using	GCF::TM::GCFTask;
+using	APLCommon::ParentControl;
+
+
+class OfflineControl : public GCFTask,
+                      public APLCommon::PropertySetAnswerHandlerInterface,
+                      public CEPApplicationManagerInterface
+{
+public:
+	explicit OfflineControl(const string& cntlrName);
+	~OfflineControl();
+
+   	// PropertySetAnswerHandlerInterface method
+   	void handlePropertySetAnswer(GCFEvent& answer);
+
+	// During the initial state all connections with the other programs are made.
+   	GCFEvent::TResult initial_state (GCFEvent& e, 
+									 GCFPortInterface& p);
+	
+	// Normal control mode. 
+   	GCFEvent::TResult active_state  (GCFEvent& e, 
+									 GCFPortInterface& p);
+
+	// Finishing mode. 
+	GCFEvent::TResult finished_state(GCFEvent& event, 
+									 GCFPortInterface& port);
+
+protected: // implemenation of abstract CEPApplicationManagerInterface methods
+    void    appBooted(const string& procName, uint16 result);
+    void    appDefined(const string& procName, uint16 result);
+    void    appInitialized(const string& procName, uint16 result);
+    void    appRunDone(const string& procName, uint16 result);
+    void    appPaused(const string& procName, uint16 result);
+    void    appQuitDone(const string& procName, uint16 result);
+    void    appSnapshotDone(const string& procName, uint16 result);
+    void    appRecovered(const string& procName, uint16 result);
+    void    appReinitialized(const string& procName, uint16 result);
+    void    appReplaced(const string& procName, uint16 result);
+    string  appSupplyInfo(const string& procName, const string& keyList);
+    void    appSupplyInfoAnswer(const string& procName, const string& answer);
+  
+private:
+	// avoid defaultconstruction and copying
+	OfflineControl();
+	OfflineControl(const OfflineControl&);
+   	OfflineControl& operator=(const OfflineControl&);
+
+	uint16_t doClaim(const string& cntlrName);
+	uint16_t doPrepare(const string& cntlrName);
+	void prepareProcess(const string& cntlrName, const string& procName, const time_t startTime);
+	void	 doRelease();
+	void     finishController(uint16_t result);
+   	void	 _connectedHandler(GCFPortInterface& port);
+   	void	 _disconnectedHandler(GCFPortInterface& port);
+	void	 setState(CTState::CTstateNr     newState);
+
+   	typedef boost::shared_ptr<GCF::PAL::GCFMyPropertySet> GCFMyPropertySetPtr;
+	typedef boost::shared_ptr<CEPApplicationManager> CEPApplicationManagerPtr;
+
+   	APLCommon::PropertySetAnswer  itsPropertySetAnswer;
+   	GCFMyPropertySetPtr           itsPropertySet;
+	bool						  itsPropertySetInitialized;
+
+	// pointer to parent control task
+	ParentControl*			itsParentControl;
+	GCFITCPort*				itsParentPort;
+
+	GCFTimerPort*			itsTimerPort;
+
+    map<string, CEPApplicationManagerPtr> itsCepApplications;
+    map<string, ACC::APS::ParameterSet>   itsCepAppParams;
+    ACC::APS::ParameterSet  itsResultParams;
+	map<string, vector<string> >          itsProcessDependencies;
+
+	CTState::CTstateNr		itsState;
+
+	// ParameterSet variables
+	string					itsTreePrefix;
+	uint32					itsInstanceNr;
+	ptime					itsStartTime;
+	ptime					itsStopTime;
+	uint32					itsClaimPeriod;
+	uint32					itsPreparePeriod;
+	string                  itsCntlrName;
+};
+
+  };//CEPCU
+};//LOFAR
+#endif
diff --git a/MAC/APL/CEPCU/src/OfflineControl/OfflineControl.log_prop.in b/MAC/APL/CEPCU/src/OfflineControl/OfflineControl.log_prop.in
new file mode 100644
index 00000000000..fc002f4164c
--- /dev/null
+++ b/MAC/APL/CEPCU/src/OfflineControl/OfflineControl.log_prop.in
@@ -0,0 +1,20 @@
+# add your custom loggers and appenders here
+#
+
+log4cplus.rootLogger=DEBUG, STDOUT, FILE
+
+log4cplus.logger.TRC=TRACE2
+log4cplus.additivity.TRC=FALSE
+
+log4cplus.appender.STDOUT=log4cplus::ConsoleAppender
+log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout
+log4cplus.appender.STDOUT.layout.ConversionPattern=%D{%d-%m-%y %H:%M:%S.%q} %-5p %c{9} - %m [%.25l]%n
+log4cplus.appender.STDOUT.logToStdErr=true
+
+log4cplus.appender.FILE=log4cplus::RollingFileAppender
+log4cplus.appender.FILE.File=../log/OfflineControl.log
+log4cplus.appender.FILE.MaxFileSize=5MB
+log4cplus.appender.FILE.MaxBackupIndex=5
+log4cplus.appender.FILE.layout=log4cplus::PatternLayout
+log4cplus.appender.FILE.layout.ConversionPattern=%D{%d-%m-%y %H:%M:%S.%q} %-5p %c{3} - %m [%.25l]%n
+
diff --git a/MAC/APL/CEPCU/src/OfflineControl/OfflineControlDefines.h b/MAC/APL/CEPCU/src/OfflineControl/OfflineControlDefines.h
new file mode 100644
index 00000000000..fb7368cbc1a
--- /dev/null
+++ b/MAC/APL/CEPCU/src/OfflineControl/OfflineControlDefines.h
@@ -0,0 +1,43 @@
+//#  OfflineControlDefines.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 OFFLINECONTROLDEFINES_H
+#define OFFLINECONTROLDEFINES_H
+
+namespace LOFAR {
+  namespace CEPCU {
+
+#define ONC_TASKNAME					"OfflineCtrl"
+
+#define ONC_PROPSET_NAME				"LOFAR_ObsSW_ObsCtrl%d_OfflineCtrl"
+#define ONC_PROPSET_TYPE				"OfflineCtrl"
+#define ONC_OBSERVATIONSTATE			"observationState"
+
+// next lines should be defined somewhere in Common.
+#define PVSSNAME_FSM_STATE			"state"
+#define PVSSNAME_FSM_ERROR			"error"
+
+
+}; // MCU
+}; // LOFAR
+
+#endif
diff --git a/MAC/APL/CEPCU/src/OfflineControl/OfflineControlMain.cc b/MAC/APL/CEPCU/src/OfflineControl/OfflineControlMain.cc
new file mode 100644
index 00000000000..d8f1e2e3c14
--- /dev/null
+++ b/MAC/APL/CEPCU/src/OfflineControl/OfflineControlMain.cc
@@ -0,0 +1,52 @@
+//#  OfflineControlMain.cc: Main entry for the OfflineControl controller.
+//#
+//#  Copyright (C) 2006
+//#  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 "OfflineControl.h"
+
+using namespace LOFAR::GCF::TM;
+using namespace LOFAR::CEPCU;
+
+int main(int argc, char* argv[])
+{
+	// args: cntlrname
+    if(argc < 2)
+	{
+	  printf("Unexpected number of arguments: %d\n",argc);
+	  printf("%s usage: %s <controller name>\n",argv[0],argv[0]);
+	  exit(-1);
+	}
+	GCFTask::init(argc, argv);
+
+	ParentControl*	pc = ParentControl::instance();
+	pc->start();	// make initial transition
+
+	OfflineControl	ofc(argv[1]);
+	ofc.start(); 	// make initial transition
+
+	GCFTask::run();
+
+	return 0;
+}
+
-- 
GitLab