From b492203429af1da799addae76999e835ebd2d57c Mon Sep 17 00:00:00 2001
From: Ruud Overeem <overeem@astron.nl>
Date: Fri, 17 Jan 2014 11:04:09 +0000
Subject: [PATCH] Task #4480: MACScheduler calls 'free' of the claimmanager
 when an observation finishes or aborts.

---
 .gitattributes                                |   2 +
 .../MainCU/src/MACScheduler/CMakeLists.txt    |   4 +
 .../MainCU/src/MACScheduler/MACScheduler.cc   |  15 +-
 MAC/APL/MainCU/src/MACScheduler/ObsClaimer.cc |  35 +++-
 MAC/APL/MainCU/src/MACScheduler/ObsClaimer.h  |   7 +
 MAC/APL/MainCU/src/MACScheduler/claimTest.cc  | 156 ++++++++++++++++++
 MAC/APL/MainCU/src/MACScheduler/claimTest.h   |  70 ++++++++
 .../include/APL/RTDBCommon/ClaimMgrTask.h     |   3 +
 MAC/APL/RTDBCommon/src/ClaimMgrTask.cc        |  77 +++++++--
 9 files changed, 347 insertions(+), 22 deletions(-)
 create mode 100644 MAC/APL/MainCU/src/MACScheduler/claimTest.cc
 create mode 100644 MAC/APL/MainCU/src/MACScheduler/claimTest.h

diff --git a/.gitattributes b/.gitattributes
index 8758b67450e..f1656326586 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2589,6 +2589,8 @@ MAC/APL/MainCU/src/CRTriggerControl/TriggerControl.h -text
 MAC/APL/MainCU/src/CRTriggerControl/TriggerControlMain.cc -text
 MAC/APL/MainCU/src/CRTriggerControl/crctl.cc -text
 MAC/APL/MainCU/src/CRTriggerControl/crctl.h -text
+MAC/APL/MainCU/src/MACScheduler/claimTest.cc -text
+MAC/APL/MainCU/src/MACScheduler/claimTest.h -text
 MAC/APL/MainCU/src/ObservationControl/ObservationControl.conf.in -text
 MAC/APL/PAC/Cal_Server/src/CS010C_HALF_positions.dat -text
 MAC/APL/PAC/Cal_Server/src/CS010C_positions.dat -text
diff --git a/MAC/APL/MainCU/src/MACScheduler/CMakeLists.txt b/MAC/APL/MainCU/src/MACScheduler/CMakeLists.txt
index 76a5c790621..cb70cfd7ff9 100644
--- a/MAC/APL/MainCU/src/MACScheduler/CMakeLists.txt
+++ b/MAC/APL/MainCU/src/MACScheduler/CMakeLists.txt
@@ -5,6 +5,10 @@ lofar_add_bin_program(MACScheduler
   MACScheduler.cc
   ObsClaimer.cc)
                                                   
+lofar_add_bin_program(claimTest
+  claimTest.cc
+  ObsClaimer.cc)
+                                                  
 configure_file(
   ${CMAKE_CURRENT_SOURCE_DIR}/MACScheduler.conf.in
   ${CMAKE_CURRENT_BINARY_DIR}/MACScheduler.conf)
diff --git a/MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc
index a49d30918a9..120af530645 100644
--- a/MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc
+++ b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc
@@ -195,7 +195,7 @@ GCFEvent::TResult MACScheduler::initial_state(GCFEvent& event, GCFPortInterface&
 
 	case F_ENTRY: {
 		// Get access to my own propertyset.
-		LOG_DEBUG_STR ("Activating my propertySet(" << PSN_MAC_SCHEDULER << ")");
+		LOG_INFO_STR ("Activating my propertySet(" << PSN_MAC_SCHEDULER << ")");
 		itsPropertySet = new RTDBPropertySet(PSN_MAC_SCHEDULER,
 											 PST_MAC_SCHEDULER,
 											 PSAT_CW,
@@ -234,7 +234,7 @@ GCFEvent::TResult MACScheduler::initial_state(GCFEvent& event, GCFPortInterface&
 		string password	= pParamSet->getString("OTDBpassword");
 		string hostname	= pParamSet->getString("OTDBhostname");
 
-		LOG_DEBUG_STR ("Trying to connect to the OTDB on " << hostname);
+		LOG_INFO_STR ("Trying to connect to the OTDB on " << hostname);
 		itsOTDBconnection= new OTDBconnection(username, password, DBname, hostname);
 		ASSERTSTR (itsOTDBconnection, "Memory allocation error (OTDB)");
 		ASSERTSTR (itsOTDBconnection->connect(),
@@ -430,7 +430,7 @@ GCFEvent::TResult MACScheduler::active_state(GCFEvent& event, GCFPortInterface&
 	case CONTROL_CONNECTED: {
 		// The observationController has registered itself at childControl.
 		CONTROLConnectedEvent conEvent(event);
-		LOG_DEBUG_STR(conEvent.cntlrName << " is connected, updating SAS)");
+		LOG_INFO_STR(conEvent.cntlrName << " is connected, updating SAS)");
 
 		// Ok, controller is really up, update SAS so that obs will not appear in
 		// in the SAS list again.
@@ -494,6 +494,9 @@ GCFEvent::TResult MACScheduler::active_state(GCFEvent& event, GCFPortInterface&
 			tm.setTreeState(theObs->second, tsc.get("aborted"));
 		}
 
+		// free claimed observation in PVSS
+		itsClaimerTask->freeObservation(observationName(theObs->second));
+
 		// update our administration
 		LOG_INFO_STR("Removing observation " << quitedEvent.cntlrName << " from activeList");
 		itsControllerMap.erase(quitedEvent.cntlrName);
@@ -658,7 +661,7 @@ void MACScheduler::_updatePlannedList()
 			}
 			else {
 				// Claim a DP in PVSS and write obssettings to it so the operator can see it.
-				LOG_DEBUG_STR("Requesting preparation of PVSS for " << obsName);
+				LOG_INFO_STR("Requesting preparation of PVSS for " << obsName);
 				itsClaimerTask->prepareObservation(obsName);
 				itsPreparedObs[obsID] = schedInfo(modTime, false);	// requested claim but no answer yet.
 			}
@@ -674,7 +677,7 @@ void MACScheduler::_updatePlannedList()
 //		LOG_DEBUG_STR(obsName << " starts over " << timeBeforeStart << " seconds");
 		if (timeBeforeStart > 0 && timeBeforeStart <= (int)itsQueuePeriod) {
 			if (itsPreparedObs[obsID].prepReady == false) {
-				LOG_ERROR_STR("Observation " << obsID << " must be started but is not claimed yet.");
+				LOG_INFO_STR("Observation " << obsID << " must be started but is not claimed yet.");
 			}
 			else {
 				// starttime of observation lays in queuePeriod. Start the controller-chain,
@@ -683,7 +686,7 @@ void MACScheduler::_updatePlannedList()
 				//		 the observation will not be returned in the 'plannedDBlist' anymore.
 				string	cntlrName(controllerName(CNTLRTYPE_OBSERVATIONCTRL, 0, obsID));
 				if (itsControllerMap.find(cntlrName) == itsControllerMap.end()) {
-					LOG_DEBUG_STR("Requesting start of " << cntlrName);
+					LOG_INFO_STR("Requesting start of " << cntlrName);
 					itsChildControl->startChild(CNTLRTYPE_OBSERVATIONCTRL, 
 												obsID, 
 												0,		// instanceNr
diff --git a/MAC/APL/MainCU/src/MACScheduler/ObsClaimer.cc b/MAC/APL/MainCU/src/MACScheduler/ObsClaimer.cc
index e85eb66dafe..35d7ad030bd 100644
--- a/MAC/APL/MainCU/src/MACScheduler/ObsClaimer.cc
+++ b/MAC/APL/MainCU/src/MACScheduler/ObsClaimer.cc
@@ -97,7 +97,7 @@ ObsClaimer::~ObsClaimer()
 
 }
 
-// -------------------- The only public function --------------------
+// -------------------- The only two public function --------------------
 //
 // prepareObservation(const string&		observationName);
 //
@@ -122,6 +122,29 @@ void ObsClaimer::prepareObservation(const string&		observationName)
 	itsHeartBeat->setTimer(0.0);
 }
 
+//
+// freeObservation(const string&		observationName);
+//
+// Just add the observationname to our freeList and trigger main-loop.
+void ObsClaimer::freeObservation(const string&		observationName)
+{
+	OMiter	iter = itsFreeMap.find(observationName);
+	if (iter == itsFreeMap.end()) {	// new?
+		obsInfo*	oldObs = new obsInfo();
+		oldObs->obsName = observationName;
+		oldObs->state   = OS_NEW;
+		itsFreeMap["LOFAR_ObsSW_"+observationName] = oldObs;
+		LOG_DEBUG_STR("Added observation " << observationName << " to the freeList");
+	}	
+	else {
+		LOG_DEBUG_STR("Observation " << observationName << " already in the freeList with state " << iter->second->state);
+	}
+
+	// Wake up state-machine asap.
+	itsHeartBeat->cancelAllTimers();
+	itsHeartBeat->setTimer(0.0);
+}
+
 
 
 //
@@ -154,6 +177,16 @@ GCFEvent::TResult ObsClaimer::idle_state (GCFEvent& event, GCFPortInterface& por
 				}
 				++iter;
 			}
+			if (iter == end) {	// nothing to claim. Something to free?
+				FMiter		FreeIter = itsFreeMap.begin();
+				FMiter		FreeEnd  = itsFreeMap.end();
+				while (FreeIter != FreeEnd) {
+					itsClaimMgrTask->freeObject("Observation", "LOFAR_ObsSW_"+FreeIter->second->obsName);
+					// will not result in an event
+					++FreeIter;
+				}
+				itsFreeMap.clear();
+			}
 		}
 		break;
 
diff --git a/MAC/APL/MainCU/src/MACScheduler/ObsClaimer.h b/MAC/APL/MainCU/src/MACScheduler/ObsClaimer.h
index 4b2efec4dca..2d82212d08f 100644
--- a/MAC/APL/MainCU/src/MACScheduler/ObsClaimer.h
+++ b/MAC/APL/MainCU/src/MACScheduler/ObsClaimer.h
@@ -60,6 +60,9 @@ public:
 	// ask the ObsClaimer to prepare the PVSS database for the given observation.
 	void prepareObservation(const string&		observationName);
 
+	// ask the ObsClaimer to release the claim on this observation DP
+	void freeObservation(const string&			observationName);
+
 private:
 	// Connect to the PS of the claimManager
    	GCFEvent::TResult connect2claimMgr_state (GCFEvent& e, GCFPortInterface& p);
@@ -92,9 +95,13 @@ private:
 
 	// ----- DATAMEMBERS -----
 	// admin for observations
+	// queue for claiming
 	map<string, obsInfo*>	itsObsMap;
 	typedef		map<string, obsInfo*>::iterator		OMiter;
 	OMiter					itsCurrentObs;			// Obs currently handled by claimMgr.
+	// queue for freeing
+	map<string, obsInfo*>	itsFreeMap;
+	typedef		map<string, obsInfo*>::iterator		FMiter;
 
 	ClaimMgrTask*	itsClaimMgrTask;		// Pointer to claimMgr.
 	GCFITCPort*		itsITCPort;				// Answer back from CMtask.
diff --git a/MAC/APL/MainCU/src/MACScheduler/claimTest.cc b/MAC/APL/MainCU/src/MACScheduler/claimTest.cc
new file mode 100644
index 00000000000..03123f6e762
--- /dev/null
+++ b/MAC/APL/MainCU/src/MACScheduler/claimTest.cc
@@ -0,0 +1,156 @@
+//#  claimtest.cc: tool for manually testing the obsClaimer task.
+//#
+//#  Copyright (C) 2004-2012
+//#  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: claimTest.cc 27513 2013-11-26 14:49:20Z overeem $
+#include <lofar_config.h>
+#include <Common/LofarLogger.h>
+#include <Common/SystemUtil.h>
+#include <Common/StringUtil.h>
+
+#include <GCF/TM/GCF_Protocols.h>
+#include <MACIO/MACServiceInfo.h>
+#include <GCF/PVSS/GCF_PVTypes.h>
+#include <APL/APLCommon/APL_Defines.h>
+#include <APL/APLCommon/ControllerDefines.h>
+#include <GCF/RTDB/DP_Protocol.ph>
+#include <APL/RTDBCommon/CM_Protocol.ph>
+#include <signal.h>
+
+#include "claimTest.h"
+
+using namespace LOFAR::GCF::PVSS;
+using namespace LOFAR::GCF::TM;
+using namespace LOFAR::GCF::RTDB;
+using namespace std;
+
+namespace LOFAR {
+	using namespace APLCommon;
+	namespace MainCU {
+
+// Global vars
+bool	gClaimIt;
+string	gObsName;
+
+//
+// claimTest()
+//
+claimTest::claimTest() :
+	GCFTask 			((State)&claimTest::initial_state,string("claimTest")),
+	itsClaimerTask		(0),
+	itsClaimerPort		(0),
+	itsTimerPort		(0)
+{
+	// create an PVSSprepare Task
+	itsClaimerTask = new ObsClaimer(this);
+	ASSERTSTR(itsClaimerTask, "Cannot construct a ObsClaimerTask");
+	itsClaimerPort = new GCFITCPort (*this, *itsClaimerTask, "ObsClaimerPort", GCFPortInterface::SAP, CM_PROTOCOL);
+
+	// need port for timers
+	itsTimerPort = new GCFTimerPort(*this, "Timerport");
+}
+
+
+//
+// ~claimTest()
+//
+claimTest::~claimTest()
+{
+}
+
+//
+// initial_state(event, port)
+//
+// Setup all connections.
+//
+GCFEvent::TResult claimTest::initial_state(GCFEvent& event, GCFPortInterface& /*port*/)
+{
+	LOG_DEBUG_STR ("initial_state:" << eventName(event));
+
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+  
+	switch (event.signal) {
+    case F_INIT:
+   		break;
+
+	case F_ENTRY: {
+		itsTimerPort->setTimer(5.0);
+		if (gClaimIt) {
+			itsClaimerTask->prepareObservation(gObsName);
+		}
+		else {
+			itsClaimerTask->freeObservation(gObsName);
+		}
+	} break;
+
+	case CM_CLAIM_RESULT: {
+		// some observation was claimed by the claimMgr. Update our prepare_list.
+		CMClaimResultEvent	cmEvent(event);
+		ltrim(cmEvent.nameInAppl, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_");
+		int		obsID = atoi(cmEvent.nameInAppl.c_str());
+		// claim was successful, update admin
+		cout << "Observation " << obsID << " is mapped to " << cmEvent.DPname << endl;
+		GCFScheduler::instance()->stop();
+	} break;
+
+	case F_TIMER:
+		cout << "TIMEOUT" << endl;
+		GCFScheduler::instance()->stop();
+		break;
+
+	default:
+		LOG_DEBUG("claimTest::active, default");
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	return (status);
+}
+
+};   // namespace MainCU
+}; // namespace LOFAR
+
+
+using namespace LOFAR::GCF::TM;
+using namespace LOFAR::MainCU;
+using namespace LOFAR::APLCommon;
+using namespace LOFAR;
+
+int main(int argc, char* argv[])
+{
+	if (argc != 3) {
+		cout << "Syntax: claimTest action name" << endl;
+		cout << "  action: claim | free" << endl;
+		cout << "  name:   observationname" << endl;
+		return(-1);
+	}
+	cout << "######" << argv[1] << "#######" << endl;
+	gClaimIt = (strcmp(argv[1],"claim")==0);
+	gObsName = argv[2];
+
+	GCFScheduler::instance()->init(argc, argv, "claimTest");
+
+	claimTest	cT;
+	cT.start(); // make initial transition
+  
+	GCFScheduler::instance()->run();
+
+	return 0;
+}
+
diff --git a/MAC/APL/MainCU/src/MACScheduler/claimTest.h b/MAC/APL/MainCU/src/MACScheduler/claimTest.h
new file mode 100644
index 00000000000..1019fcf30ed
--- /dev/null
+++ b/MAC/APL/MainCU/src/MACScheduler/claimTest.h
@@ -0,0 +1,70 @@
+//#  claimTest.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: claimTest.h 23213 2012-12-07 13:00:09Z loose $
+
+#ifndef claimTest_H
+#define claimTest_H
+
+//# GCF Includes
+#include <MACIO/GCF_Event.h>
+#include <GCF/TM/GCF_Control.h>
+
+//# Common Includes
+#include <Common/lofar_string.h>
+#include <Common/lofar_vector.h>
+#include <Common/LofarLogger.h>
+
+#include "ObsClaimer.h"
+
+// forward declaration
+
+namespace LOFAR {
+	using	MACIO::GCFEvent;
+	using	GCF::TM::GCFTimerPort;
+	using	GCF::TM::GCFITCPort;
+	using	GCF::TM::GCFPort;
+	using	GCF::TM::GCFPortInterface;
+	using	GCF::TM::GCFTask;
+	namespace MainCU {
+
+class claimTest : public GCFTask
+{
+public:
+	claimTest();
+	~claimTest();
+
+	// During the initial state all connections with the other programs are made.
+   	GCFEvent::TResult initial_state (GCFEvent& e, GCFPortInterface& p);
+	
+private:
+	// avoid copying
+	claimTest(const claimTest&);
+   	claimTest& operator=(const claimTest&);
+
+	// ----- DATA MEMBERS -----
+	ObsClaimer*			itsClaimerTask;
+	GCFITCPort*			itsClaimerPort;
+   	GCFTimerPort*		itsTimerPort;			// for timers
+};
+
+  };//MainCU
+};//LOFAR
+#endif
diff --git a/MAC/APL/RTDBCommon/include/APL/RTDBCommon/ClaimMgrTask.h b/MAC/APL/RTDBCommon/include/APL/RTDBCommon/ClaimMgrTask.h
index 2fb9d8e2118..ad8bf96deeb 100644
--- a/MAC/APL/RTDBCommon/include/APL/RTDBCommon/ClaimMgrTask.h
+++ b/MAC/APL/RTDBCommon/include/APL/RTDBCommon/ClaimMgrTask.h
@@ -56,6 +56,9 @@ public:
 					 const string&		nameInAppl,
 					 GCFPortInterface&	replyPort);
   
+	// Ask the claimManager to flee an object. 
+    void freeObject (const string&		objectType,
+					 const string&		nameInAppl);
 private:
 	enum {
 		RO_UNDEFINED = 0,
diff --git a/MAC/APL/RTDBCommon/src/ClaimMgrTask.cc b/MAC/APL/RTDBCommon/src/ClaimMgrTask.cc
index 1c0cd0e14a7..93dc5009e2f 100644
--- a/MAC/APL/RTDBCommon/src/ClaimMgrTask.cc
+++ b/MAC/APL/RTDBCommon/src/ClaimMgrTask.cc
@@ -138,6 +138,38 @@ void ClaimMgrTask::claimObject(const string&		objectType,
 	// else: some other timer must be active.
 }
 
+//
+// freeObject(objectype, nameInAppl)
+//
+void ClaimMgrTask::freeObject(const string&		objectType,
+							  const string&		nameInAppl)
+{
+	// not yet started yet? (user called us directly after creation)
+	if (itsResolveState==RO_UNDEFINED) {
+		itsRequestPool.push(cmRequest_t(objectType,nameInAppl,0));
+		LOG_INFO_STR("freerequest '" << nameInAppl << "' queued because manager is still starting up");
+		return;
+	}
+
+	// are we in an idle state?
+	if (!itsObjectType.empty() || !itsNameInAppl.empty()) {
+		itsRequestPool.push(cmRequest_t(objectType,nameInAppl,0));
+		LOG_INFO_STR("freerequest '" << nameInAppl << "' queued because manager is still busy with " << itsNameInAppl);
+		return;
+	}
+
+	// save info
+	itsObjectType = objectType;
+	itsNameInAppl = nameInAppl;
+	itsReplyPort  = 0;
+	LOG_INFO_STR("freerequest '" << nameInAppl << "' will be handled immediately");
+	if (itsResolveState == RO_READY) {
+		itsTimerPort->setTimer(0.1);	// wake up FSM
+	}
+	// else: some other timer must be active.
+}
+
+
 
 // -------------------- INTERNAL FUNCTIONS --------------------
 
@@ -187,7 +219,7 @@ GCFEvent::TResult ClaimMgrTask::operational(GCFEvent& event, GCFPortInterface& p
 		case RO_READY:			// 4
 			if (itsObjectType.empty() || itsNameInAppl.empty()) {
 				if (itsRequestPool.empty()) {
-					LOG_DEBUG_STR("Nothing to claim");
+					LOG_DEBUG_STR("Nothing to claim or free");
 					break;
 				}
 				// continue with requests on the stack
@@ -197,20 +229,35 @@ GCFEvent::TResult ClaimMgrTask::operational(GCFEvent& event, GCFPortInterface& p
 				itsReplyPort  = newRequest.replyPort;
 				itsRequestPool.pop();
 			}
-			// request a DPname
-			LOG_INFO_STR("ClaimObject(" << itsObjectType << "," << itsNameInAppl << ")");
-			itsClaimMgrPS->setValue("request.typeName",       GCFPVString(itsObjectType), 0.0, false);
-			itsClaimMgrPS->setValue("request.newObjectName",  GCFPVString(itsNameInAppl), 0.0, false);
-			// clear the answer also otherwise we will not be notified when asking the same question twice.
-			itsClaimMgrPS->setValue("response.DPName",        GCFPVString(""), 0.0, false);
-			itsClaimMgrPS->setValue("response.newObjectName", GCFPVString(""), 0.0, false);
-			itsClaimMgrPS->flush();
-			itsResolveState = RO_ASKED; // 3
-			// clear result fields
-			itsFieldsReceived = 0;
-			itsResultDPname.clear();
-			itsTimerPort->cancelAllTimers();
-			itsTimerPort->setTimer(3.0);		// don't wait forever.
+			// free request?
+			if (itsReplyPort == 0) {
+				LOG_INFO_STR("FreeObject(" << itsObjectType << "," << itsNameInAppl << ")");
+				itsClaimMgrPS->setValue("reset.typeName",   GCFPVString(itsObjectType), 0.0, false);
+				itsClaimMgrPS->setValue("reset.objectName", GCFPVString(itsNameInAppl), 0.0, false);
+				itsClaimMgrPS->flush();
+				// stay in current (idle) mode
+				itsObjectType.clear();
+				itsNameInAppl.clear();
+				itsResultDPname.clear();
+				itsTimerPort->cancelAllTimers();
+				itsTimerPort->setTimer(0.1);		// hop to next request.
+			}
+			else {
+				// request a DPname
+				LOG_INFO_STR("ClaimObject(" << itsObjectType << "," << itsNameInAppl << ")");
+				itsClaimMgrPS->setValue("request.typeName",       GCFPVString(itsObjectType), 0.0, false);
+				itsClaimMgrPS->setValue("request.newObjectName",  GCFPVString(itsNameInAppl), 0.0, false);
+				// clear the answer also otherwise we will not be notified when asking the same question twice.
+				itsClaimMgrPS->setValue("response.DPName",        GCFPVString(""), 0.0, false);
+				itsClaimMgrPS->setValue("response.newObjectName", GCFPVString(""), 0.0, false);
+				itsClaimMgrPS->flush();
+				itsResolveState = RO_ASKED; // 3
+				// clear result fields
+				itsFieldsReceived = 0;
+				itsResultDPname.clear();
+				itsTimerPort->cancelAllTimers();
+				itsTimerPort->setTimer(3.0);		// don't wait forever.
+			}
 		break;
 
 		case RO_ASKED:		// 3
-- 
GitLab