From cfce4812eeafd2d1658199bbda61c0bdab207e3c Mon Sep 17 00:00:00 2001
From: Ruud Overeem <overeem@astron.nl>
Date: Wed, 29 Nov 2006 22:06:14 +0000
Subject: [PATCH] BugID: 679 Some small modification to support SCHEDULE
 messages better.

---
 .gitattributes                                |  1 -
 .../include/APL/APLCommon/ChildControl.h      |  5 +
 .../include/APL/APLCommon/ControllerInfo.h    |  2 +
 MAC/APL/APLCommon/src/APLCommon.dpl           | 17 ----
 MAC/APL/APLCommon/src/ChildControl.cc         | 93 +++++++++++++++++--
 MAC/APL/APLCommon/src/ParentControl.cc        | 35 +++++--
 MAC/APL/APLCommon/src/PropertySetAnswer.cc    |  4 +-
 7 files changed, 125 insertions(+), 32 deletions(-)
 delete mode 100644 MAC/APL/APLCommon/src/APLCommon.dpl

diff --git a/.gitattributes b/.gitattributes
index 2bf801d760f..425ff7e3826 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -231,7 +231,6 @@ LCS/Common/src/Common-Model.cat -text
 MAC/APL/APLCommon/Makefile.am -text svneol=native#application/octet-stream
 MAC/APL/APLCommon/bootstrap -text svneol=native#application/octet-stream
 MAC/APL/APLCommon/configure.in -text svneol=native#application/octet-stream
-MAC/APL/APLCommon/src/APLCommon.dpl -text svneol=native#application/octet-stream
 MAC/APL/APLCommon/src/Makefile.am -text svneol=native#application/octet-stream
 MAC/APL/APLCommon/src/StartDaemon_Protocol.prot -text svneol=native#application/octet-stream
 MAC/APL/DEPENDENCIES -text svneol=native#application/octet-stream
diff --git a/MAC/APL/APLCommon/include/APL/APLCommon/ChildControl.h b/MAC/APL/APLCommon/include/APL/APLCommon/ChildControl.h
index 5870f085223..5052db52809 100644
--- a/MAC/APL/APLCommon/include/APL/APLCommon/ChildControl.h
+++ b/MAC/APL/APLCommon/include/APL/APLCommon/ChildControl.h
@@ -104,6 +104,11 @@ public:
 								 const string&		aName, 
 								 OTDBtreeIDType		anObsID = 0, 
 								 uint16				aCntlrType = CNTLRTYPE_NO_TYPE);
+	bool		rescheduleChilds(time_t				aStartTime,
+								 time_t				aStopTime,
+								 const string&		aName, 
+								 OTDBtreeIDType		anObsID = 0, 
+								 uint16				aCntlrType = CNTLRTYPE_NO_TYPE);
 	uint32		countChilds		(OTDBtreeIDType		anObsID = 0, 
 								 uint16				aCntlrType = CNTLRTYPE_NO_TYPE);
 
diff --git a/MAC/APL/APLCommon/include/APL/APLCommon/ControllerInfo.h b/MAC/APL/APLCommon/include/APL/APLCommon/ControllerInfo.h
index dba91064b74..5e3cd2c41a7 100644
--- a/MAC/APL/APLCommon/include/APL/APLCommon/ControllerInfo.h
+++ b/MAC/APL/APLCommon/include/APL/APLCommon/ControllerInfo.h
@@ -83,6 +83,8 @@ private:
 	CTState::CTstateNr	currentState;	// the state the controller has
 	time_t				establishTime;	// time the current state was reached
 	uint16				result;			// error nr of last action
+	time_t				startTime;		// time the controller must be active
+	time_t				stopTime;		// time the controller must be stopped
 	// --- for use in action list ---
 	time_t				retryTime;		// time the request must be retried
 	uint32				nrRetries;		// nr of retries performed
diff --git a/MAC/APL/APLCommon/src/APLCommon.dpl b/MAC/APL/APLCommon/src/APLCommon.dpl
deleted file mode 100644
index 941bbdf9d81..00000000000
--- a/MAC/APL/APLCommon/src/APLCommon.dpl
+++ /dev/null
@@ -1,17 +0,0 @@
-# ascii dump of database
-
-# DpType
-TypeName
-TAplStartDaemon.TAplStartDaemon	1#1
-	command	25#2
-	status	21#3
-TAplLogicalDevice.TAplLogicalDevice	1#1
-	command	25#2
-	status	21#9
-	state	25#4
-	prepareTime	21#10
-	startTime	21#11
-	stopTime	21#12
-	__childs	9#8
-	claimTime	21#13
-	version	25#14
diff --git a/MAC/APL/APLCommon/src/ChildControl.cc b/MAC/APL/APLCommon/src/ChildControl.cc
index b52583ded34..80cfb69f37b 100644
--- a/MAC/APL/APLCommon/src/ChildControl.cc
+++ b/MAC/APL/APLCommon/src/ChildControl.cc
@@ -205,6 +205,7 @@ bool ChildControl::startChild (uint16				aCntlrType,
 		if (hostname != GCF::Common::myHostname(false)  && 
 			hostname != GCF::Common::myHostname(true)) {
 			APLUtilities::remoteCopy(cntlrSetName, hostname, cntlrSetName);
+			APLUtilities::remoteCopy(baseSetName, hostname, baseSetName);
 		}
 	}
 
@@ -224,6 +225,8 @@ bool ChildControl::startChild (uint16				aCntlrType,
 	ci.retryTime	  = 0;
 	ci.nrRetries	  = 0;
 	ci.result		  = CT_RESULT_NO_ERROR;
+	ci.startTime	  = 0;					// only used for reschedule
+	ci.stopTime		  = 0;					// only used for reschedule
 
 	// Update our administration.
 	itsCntlrList->push_back(ci);
@@ -235,6 +238,7 @@ bool ChildControl::startChild (uint16				aCntlrType,
 	// Trigger statemachine.
 	if (itsListener) {
 		itsActionTimer = itsListener->setTimer(0.0);
+		LOG_DEBUG_STR("ACTIONTIMER=" << itsActionTimer);
 	}
 
 	LOG_TRACE_COND_STR ("Scheduled start of " << cntlrName << " for obs " << anObsID);
@@ -273,7 +277,7 @@ void ChildControl::startChildControllers()
 				startChild(childCntlrType, 
 						   treeID, 
 						   instanceNr,
-						   myHostname(true));
+						   childhostname);
 				// Note: controller is now in state NO_STATE/CONNECTED (C/R)
 
 				LOG_DEBUG_STR("Requested start of " << childCntlrName);
@@ -314,20 +318,76 @@ bool ChildControl::requestState	(CTState::CTstateNr	aState,
 		if (!(checkName && iter->cntlrName != aName) && 
 			!(checkID && iter->obsID != anObsID) && 
 		    !(checkType && iter->cntlrType != aCntlrType)) {
-			// send request to child
+
+			// update controllerinfo to requested state and make an action of it.
 			iter->requestedState = aState;
 			iter->requestTime    = currentTime;
 			iter->result		 = CT_RESULT_NO_ERROR;
 			iter->nrRetries		 = 0;
 			iter->retryTime		 = 0;
-
-			// add it to the actionlist
 			itsActionList.push_back(*iter);
 		}
 			
 		iter++;
 	}	
+	itsTimerPort.cancelTimer(itsActionTimer);
 	itsActionTimer = itsTimerPort.setTimer(0.0);	// invoke _processActionList
+	LOG_DEBUG_STR("ACTIONTIMER=" << itsActionTimer);
+
+	return (true);
+}
+
+//
+// rescheduleChilds(startTime, stopTime, [name], [observation], [type])
+//
+// Sends a reschedule request to the given child or childs.
+//
+bool ChildControl::rescheduleChilds	(time_t				aStartTime,
+									 time_t				aStopTime,
+									 const string&		aName, 
+									 OTDBtreeIDType		anObsID, 
+									 uint16				aCntlrType)
+{
+	CTState		cts;
+	LOG_TRACE_FLOW_STR("reschedule(" << aStartTime << "," 
+									 << aStopTime  << ","
+									 << aName <<","<< anObsID <<","<< aCntlrType <<")" );
+
+	bool	checkName   = (aName != "");
+	bool	checkID     = (anObsID != 0);
+	bool	checkType   = (aCntlrType != CNTLRTYPE_NO_TYPE);
+	time_t	currentTime = time(0);
+
+	CIiter			iter  = itsCntlrList->begin();
+	const_CIiter	end   = itsCntlrList->end();
+	while (iter != end) {
+		// count the child when x has to be checked and matches:
+		//  id==id	checkID	count_it
+		//	  Y		  Y			Y
+		//	  Y		  N			Y
+		//	  N		  Y			N --> checkID && id!=id
+		//	  N		  N			Y
+		if (!(checkName && iter->cntlrName != aName) && 
+			!(checkID && iter->obsID != anObsID) && 
+		    !(checkType && iter->cntlrType != aCntlrType)) {
+			// remember the reschedule.
+			iter->startTime = aStartTime;
+			iter->stopTime  = aStopTime;
+			// don't change state of original, it's an interim state.
+			ControllerInfo	cntlrCopy(*iter);
+			cntlrCopy.requestedState = CTState::SCHEDULED;
+			cntlrCopy.requestTime	 = currentTime;
+			cntlrCopy.result		 = CT_RESULT_NO_ERROR;
+			cntlrCopy.nrRetries		 = 0;
+			cntlrCopy.retryTime		 = 0;
+			itsActionList.push_back(cntlrCopy);	// TODO: push_front????
+		}
+			
+		iter++;
+	}	
+	itsTimerPort.cancelTimer(itsActionTimer);
+	itsActionTimer = itsTimerPort.setTimer(0.0);	// invoke _processActionList
+	LOG_DEBUG_STR("ACTIONTIMER=" << itsActionTimer);
 
 	return (true);
 }
@@ -480,6 +540,10 @@ void ChildControl::_processActionList()
 {
 	LOG_TRACE_FLOW("_processActionList()");
 
+	// always cancel timer that brought me here.
+	itsTimerPort.cancelTimer(itsActionTimer);
+	itsActionTimer = 0;
+
 	uint32	nrActions = itsActionList.size();	// prevents handling rescheduled actions
 	// when list is empty return;
 	if (!nrActions) {
@@ -493,7 +557,7 @@ void ChildControl::_processActionList()
 	time_t		currentTime = time(0);
 	CIiter		action = itsActionList.begin();
 	while (nrActions > 0) {
-		// don't process (rescheduled) action that lay in the future
+		// don't process (rescheduled) action that lays in the future
 		if (action->retryTime > currentTime) {	// retry in future?
 			LOG_DEBUG_STR("parking:" << action->cntlrName << "->" << 
 					cts.name(action->requestedState) << " because its too early");
@@ -620,6 +684,16 @@ void ChildControl::_processActionList()
 			}
 			break;
 
+		case CTState::SCHEDULED:
+			{
+				CONTROLScheduleEvent		request;
+				request.cntlrName = controller->cntlrName;
+				request.startTime = controller->startTime;
+				request.stopTime  = controller->stopTime;
+				controller->port->send(request);
+			}
+			break;
+
 		case CTState::FINISHED:
 			{
 				CONTROLQuitEvent		request;
@@ -638,7 +712,9 @@ void ChildControl::_processActionList()
 	}
 
 	if (itsActionList.size()) {							// when unhandled actions in list
+		itsTimerPort.cancelTimer(itsActionTimer);
 		itsActionTimer = itsTimerPort.setTimer(1.0);	// restart timer
+		LOG_DEBUG_STR("ACTIONTIMER=" << itsActionTimer);
 	}
 
 }
@@ -954,12 +1030,12 @@ GCFEvent::TResult	ChildControl::operational(GCFEvent&			event,
 	case F_TIMER:
 		{
 			GCFTimerEvent&      timerEvent = static_cast<GCFTimerEvent&>(event);
+			LOG_DEBUG_STR("TIMERID=" << timerEvent.id);
 			if (timerEvent.id == itsGarbageTimer) {
 				itsGarbageTimer = 0;
 				_doGarbageCollection();
 			}
 			else {
-				itsActionTimer = 0;
 				_processActionList();
 			}
 		}
@@ -1029,6 +1105,7 @@ GCFEvent::TResult	ChildControl::operational(GCFEvent&			event,
 				controller->requestedState = cts.stateNr(msg.curState);
 				controller->currentState   = cts.stateNr(msg.curState);
 				controller->hostname	   = msg.hostname;
+				controller->port 		   = &port;
 				LOG_DEBUG_STR("Updated info of reconnected controller " << msg.cntlrName);
 			}
 
@@ -1075,6 +1152,10 @@ GCFEvent::TResult	ChildControl::operational(GCFEvent&			event,
 		}
 		break;
 	
+	case CONTROL_SCHEDULED:
+		// do nothing, is not a state change.
+		break;
+	
 	case CONTROL_FINISH: {
 			CONTROLFinishEvent		msg(event);
 			_setEstablishedState(msg.cntlrName, CTState::FINISH, time(0),
diff --git a/MAC/APL/APLCommon/src/ParentControl.cc b/MAC/APL/APLCommon/src/ParentControl.cc
index a333a651080..0937cdee9d6 100644
--- a/MAC/APL/APLCommon/src/ParentControl.cc
+++ b/MAC/APL/APLCommon/src/ParentControl.cc
@@ -66,7 +66,7 @@ static	stateFlow	stateFlowTable[] = {
 	{	CONTROL_FINISH,			CTState::RELEASED,		CTState::FINISHED	},
 	{	CONTROL_FINISHED,		CTState::RELEASED,		CTState::FINISHED	},
 //	{	CONTROL_FINISH,			CTState::ANYSTATE,		CTState::FINISHED	},
-//	{	CONTROL_FINISHED,		CTState::ANYSTATE,		CTState::FINISHED	},
+	{	CONTROL_FINISHED,		CTState::FINISH,		CTState::FINISHED	},
 	{	CONTROL_RESYNCED,		CTState::ANYSTATE,		CTState::ANYSTATE	},
 	{	CONTROL_SCHEDULE,		CTState::ANYSTATE,		CTState::ANYSTATE	},
 	{	CONTROL_QUIT,			CTState::ANYSTATE,		CTState::FINISH		},
@@ -208,19 +208,19 @@ bool ParentControl::activateObservationTimers(const string&		cntlrName,
 	}
 
 	// set or reset the real timers.
+	itsTimerPort.cancelTimer(parent->startTimer);
 	if (startDiff.seconds() > 0) {
 		parent->startTimer = itsTimerPort.setTimer((double)startDiff.seconds());
 	}
 	else {
-		itsTimerPort.cancelTimer(parent->startTimer);
 		parent->startTimer = 0;
 	}
 
+	itsTimerPort.cancelTimer(parent->stopTimer);
 	if (stopDiff.seconds() > 0) {
 		parent->stopTimer = itsTimerPort.setTimer((double)stopDiff.seconds());
 	}
 	else {
-		itsTimerPort.cancelTimer(parent->stopTimer);
 		parent->stopTimer = 0;
 	}
 
@@ -467,7 +467,7 @@ bool ParentControl::_confirmState(uint16			signal,
 
 	if (result != CT_RESULT_NO_ERROR) {
 		parent->failed = true;
-		LOG_DEBUG_STR(cntlrName << " DID NOT reach the " << 
+		LOG_ERROR_STR(cntlrName << " DID NOT reach the " << 
 			cts.name(requestedState(signal)) << " state, error=" << result);
 		return (false);
 	}
@@ -787,8 +787,26 @@ GCFEvent::TResult	ParentControl::operational(GCFEvent&			event,
 							cts.name(parent->requestedState));
 			}
 
+			if (event.signal == CONTROL_SCHEDULE) {		// reschedule request?
+				CONTROLScheduleEvent		schedMsg(event);
+				if (parent->stopTimer) {				// do we keep track of the time?
+					activateObservationTimers(parent->name, 	// yes
+											  from_time_t(schedMsg.startTime), 
+											  from_time_t(schedMsg.stopTime));
+					// don't bother maintask with reschedule.
+					CONTROLScheduledEvent	answer;
+					answer.cntlrName = schedMsg.cntlrName;
+					answer.result    = CT_RESULT_NO_ERROR;
+					parent->port->send(answer);
+					return (GCFEvent::HANDLED);
+				}
+				// maintask does not use my timers, just pass through the event.
+				itsMainTaskPort->sendBack(schedMsg);
+				return (GCFEvent::HANDLED);
+			}
+
 			// When we were resyncing just continue what we were trying to do.
-			if (event.signal != CONTROL_RESYNCED && event.signal != CONTROL_SCHEDULED) {
+			if (event.signal != CONTROL_RESYNCED && event.signal != CONTROL_SCHEDULE) {
 				// use stateFlowTable to determine the required state.
 				parent->requestedState = requestedState(event.signal);	
 			}
@@ -871,7 +889,11 @@ GCFEvent::TResult	ParentControl::operational(GCFEvent&			event,
 			PIiter		parent = findParent(msg.cntlrName);
 			if (isParent(parent)) {
 				// note do not register this state, it is not a real state
-				parent->port->send(msg);
+				LOG_INFO_STR("Controller " << msg.cntlrName << " is resynced");
+			}
+			else {
+				LOG_WARN_STR("Received RESYNCED message from unknown controller " 
+																	<< msg.cntlrName);
 			}
 		}
 		break;
@@ -883,6 +905,7 @@ GCFEvent::TResult	ParentControl::operational(GCFEvent&			event,
 			PIiter		parent = findParent(msg.cntlrName);
 			if (isParent(parent)) {
 				// note do not register this state, it is not a real state
+				LOG_DEBUG_STR("Passing SCHEDULED event to parent ocntroller");
 				parent->port->send(msg);
 			}
 		}
diff --git a/MAC/APL/APLCommon/src/PropertySetAnswer.cc b/MAC/APL/APLCommon/src/PropertySetAnswer.cc
index 2716d8b971f..b8580d56429 100644
--- a/MAC/APL/APLCommon/src/PropertySetAnswer.cc
+++ b/MAC/APL/APLCommon/src/PropertySetAnswer.cc
@@ -35,12 +35,12 @@ PropertySetAnswer::PropertySetAnswer(PropertySetAnswerHandlerInterface& handler)
   GCFAnswer(),
   m_handler(handler)
 {
-  LOG_DEBUG(formatString("PropertySetAnswer::PropertySetAnswer"));
+  LOG_DEBUG("PropertySetAnswer::PropertySetAnswer");
 }
 
 PropertySetAnswer::~PropertySetAnswer()
 {
-  LOG_DEBUG(formatString("PropertySetAnswer::~PropertySetAnswer"));
+  LOG_DEBUG("PropertySetAnswer::~PropertySetAnswer");
 }
 
 void PropertySetAnswer::handleAnswer(GCFEvent& answer)
-- 
GitLab