Newer
Older
//# MACScheduler.cc: Implementation of the MAC Scheduler task
//#
//# 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>
Ruud Overeem
committed
#include <Common/SystemUtil.h>
Ruud Overeem
committed
#include <Common/StringUtil.h>
#include <Common/ParameterSet.h>
Ruud Overeem
committed
#include <MACIO/MACServiceInfo.h>
#include <GCF/PVSS/GCF_PVTypes.h>
Ruud Overeem
committed
#include <APL/RTDBCommon/CM_Protocol.ph>
Ruud Overeem
committed
#include "PVSSDatapointDefs.h"

Marcel Loose
committed
#include <MainCU/Package__Version.h>

Marcel Loose
committed
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace LOFAR::GCF::PVSS;

Marcel Loose
committed
using namespace boost::posix_time;
using namespace std;
namespace LOFAR {
using namespace APLCommon;
#define MAX_CONCURRENT_OBSERVATIONS 100
#define MIN2(a,b) (((a) < (b)) ? (a) : (b))
// static (this) pointer used for signal handling
static MACScheduler* pMacScheduler = 0;
//
// MACScheduler()
//
MACScheduler::MACScheduler() :
Ruud Overeem
committed
GCFTask ((State)&MACScheduler::initial_state,string("MACScheduler")),
Ruud Overeem
committed
itsClaimerTask (0),
itsClaimerPort (0),
itsTimerPort (0),
Ruud Overeem
committed
itsNextPlannedTime (0),
itsNextActiveTime (0),
itsNextFinishedTime (0),
itsNrPlanned (0),
itsNrActive (0),
Ruud Overeem
committed
itsOTDBconnection (0)
Ruud Overeem
committed
LOG_INFO_STR("MACProcessScope: " << PSN_MAC_SCHEDULER);
LOG_INFO(Version::getInfo<MainCUVersion>("MACScheduler"));
Ruud Overeem
committed
// Read timersettings from the ParameterSet
itsPlannedItv = globalParameterSet()->getTime("pollIntervalPlanned", 60);
itsActiveItv = globalParameterSet()->getTime("pollIntervalExecute", 5);
itsFinishedItv = globalParameterSet()->getTime("pollIntervalFinished", 60);
itsPlannedPeriod = globalParameterSet()->getTime("plannedPeriod", 86400) / 60; // in minutes
itsFinishedPeriod= globalParameterSet()->getTime("finishedPeriod", 86400) / 60; // in minutes
itsMaxPlanned = globalParameterSet()->getTime("maxPlannedList", 30);
itsMaxFinished = globalParameterSet()->getTime("maxFinishedList", 40);
ASSERTSTR(itsMaxPlanned + itsMaxFinished < MAX_CONCURRENT_OBSERVATIONS, "maxPlannedList + maxFinishedList should be less than " << MAX_CONCURRENT_OBSERVATIONS);
Ruud Overeem
committed
// Read the schedule periods for starting observations.
Arno Schoenmakers
committed
LOG_INFO_STR("Queueperiod = " << itsQueuePeriod);
itsChildPort = new GCFITCPort (*this, *itsChildControl, "childITCport",
GCFPortInterface::SAP, CONTROLLER_PROTOCOL);
ASSERTSTR(itsChildPort, "Cannot allocate ITCport for childcontrol");
itsChildPort->open(); // will result in F_CONNECTED
Ruud Overeem
committed
// 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");
Ruud Overeem
committed
registerProtocol(CONTROLLER_PROTOCOL, CONTROLLER_PROTOCOL_STRINGS);
Ruud Overeem
committed
registerProtocol(DP_PROTOCOL, DP_PROTOCOL_STRINGS);
}
//
// ~MACScheduler()
//
MACScheduler::~MACScheduler()
{
LOG_TRACE_OBJ ("~MACscheduler");
if (itsOTDBconnection) {
delete itsOTDBconnection;
}
}
//
// sigintHandler(signum)
//
void MACScheduler::sigintHandler(int signum)
LOG_DEBUG (formatString("SIGINT signal detected (%d)",signum));
if (pMacScheduler) {
pMacScheduler->finish();
}
Ruud Overeem
committed
// LOG_DEBUG_STR ("_databaseEventHandler:" << eventName(event));
switch(event.signal) {
case DP_CHANGED: {
DPChangedEvent dpEvent(event);
Ruud Overeem
committed
#if 0
if (strstr(dpEvent.DPname.c_str(), PVSSNAME_MS_QUEUEPERIOD) != 0) {
uint32 newVal = ((GCFPVUnsigned*) (dpEvent.value._pValue))->getValue();
LOG_INFO_STR ("Changing QueuePeriod from " << itsQueuePeriod << " to " << newVal);
itsQueuePeriod = newVal;
}
Ruud Overeem
committed
#endif
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) {
LOG_DEBUG_STR ("Activating my propertySet(" << PSN_MAC_SCHEDULER << ")");
itsPropertySet = new RTDBPropertySet(PSN_MAC_SCHEDULER,
PST_MAC_SCHEDULER,
Arno Schoenmakers
committed
PSAT_CW,
case DP_CREATED: {
// NOTE: thsi function may be called DURING the construction of the PropertySet.
// Always exit this event in a way that GCF can end the construction.
DPCreatedEvent dpEvent(event);
LOG_DEBUG_STR("Result of creating " << dpEvent.DPname << " = " << dpEvent.result);
itsTimerPort->cancelAllTimers();
itsTimerPort->setTimer(0.0);
}
break;
Ruud Overeem
committed
itsPropertySet->setValue(PN_FSM_CURRENT_ACTION, GCFPVString ("initial"));
itsPropertySet->setValue(PN_FSM_ERROR, GCFPVString (""));
itsPropertySet->setValue(PN_MS_OTDB_CONNECTED, GCFPVBool (false));
itsPropertySet->setValue(PN_MS_OTDB_LAST_POLL, GCFPVString (""));
itsPropertySet->setValue(PN_MS_OTDB_POLLINTERVAL, GCFPVInteger (itsPlannedItv));
Ruud Overeem
committed
GCFPValueArray emptyArr;
itsPropertySet->setValue(PN_MS_ACTIVE_OBSERVATIONS, GCFPVDynArr(LPT_STRING, emptyArr));
itsPropertySet->setValue(PN_MS_PLANNED_OBSERVATIONS, GCFPVDynArr(LPT_STRING, emptyArr));
itsPropertySet->setValue(PN_MS_FINISHED_OBSERVATIONS, GCFPVDynArr(LPT_STRING, emptyArr));
ParameterSet* pParamSet = globalParameterSet();
string username = pParamSet->getString("OTDBusername");
string DBname = pParamSet->getString("OTDBdatabasename");
string password = pParamSet->getString("OTDBpassword");
LOG_DEBUG_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(),
"Unable to connect to database " << DBname << " on " << hostname <<
" using " << username << "," << password);
itsPropertySet->setValue(PN_MS_OTDB_CONNECTED, GCFPVBool(true));
// Start ChildControl task
LOG_DEBUG ("Enabling ChildControltask");
itsChildControl->openService(MAC_SVCMASK_SCHEDULERCTRL, 0);
Ruud Overeem
committed
// setup initial schedule: first planned, next run active, second run finished
itsNextPlannedTime = time(0);
itsNextActiveTime = itsNextPlannedTime + itsPlannedItv;
itsNextFinishedTime = itsNextPlannedTime + 2*itsPlannedItv;
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)
{
LOG_DEBUG_STR ("recover_state:" << eventName(event) << "@" << port.getName());
GCFEvent::TResult status = GCFEvent::HANDLED;
switch (event.signal) {
case F_INIT:
break;
case F_ENTRY: {
// update PVSS
Ruud Overeem
committed
itsPropertySet->setValue(string(PN_FSM_CURRENT_ACTION),GCFPVString("recover"));
itsPropertySet->setValue(string(PN_FSM_ERROR),GCFPVString(""));
//
// TODO: do recovery
TRAN(MACScheduler::active_state);
break;
}
default:
status = GCFEvent::NOT_HANDLED;
break;
}
return (status);
}
//
// active_state(event, port)
//
Ruud Overeem
committed
// Normal operation state. Check OTDB every itsActiveItv seconds and control
// the running observations.
//
GCFEvent::TResult MACScheduler::active_state(GCFEvent& event, GCFPortInterface& port)
{
LOG_DEBUG_STR ("active:" << eventName(event) << "@" << port.getName());
GCFEvent::TResult status = GCFEvent::HANDLED;
switch (event.signal) {
case F_INIT:
break;
case F_ENTRY: {
// install my own signal handler. GCFTask also installs a handler so we have
// to install our handler later than the GCFTask handler.
Ruud Overeem
committed
itsPropertySet->setValue(string(PN_FSM_CURRENT_ACTION),GCFPVString("active"));
itsPropertySet->setValue(string(PN_FSM_ERROR),GCFPVString(""));
Ruud Overeem
committed
// Start heartbeat timer.
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 DP_CHANGED:
_databaseEventHandler(event);
break;
Ruud Overeem
committed
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());
Arno Schoenmakers
committed
if (cmEvent.result != CM_NO_ERR) {
LOG_ERROR_STR("Error during checking observation " << obsID);
OTDB::TreeMaintenance tm(itsOTDBconnection);
TreeStateConv tsc(itsOTDBconnection);
tm.setTreeState(obsID, tsc.get("aborted"));
itsPreparedObs.erase(obsID);
break;
}
// claim was successful, update admin
LOG_INFO_STR("Observation " << obsID << " is mapped to " << cmEvent.DPname);
Ruud Overeem
committed
LOG_DEBUG_STR("PVSS preparation of observation " << obsID << " ready.");
Ruud Overeem
committed
itsPreparedObs[obsID].prepReady = true;
Ruud Overeem
committed
}
break;
case F_TIMER: { // secondTimer or reconnectTimer.
GCFTimerEvent& timerEvent=static_cast<GCFTimerEvent&>(event);
if (timerEvent.id == itsSecondTimer) {
// time to poll the OTDB?
Ruud Overeem
committed
// Note: We assume here that the PlannedItv is smaller than the ActiveItv and the FinishedItv.
// When it is not smaller (very unlikely) than the ActiveItv and FinishedItv those two
// intervals will default to the PlannedItv.
if (time(0) >= itsNextPlannedTime) { // check shortest interval
Ruud Overeem
committed
// reinit polltime at multiple of intervaltime.
// (=more change to hit hh.mm:00)
Ruud Overeem
committed
itsNextPlannedTime = time(0) + itsPlannedItv;
itsNextPlannedTime -= (itsNextPlannedTime % itsPlannedItv);
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;
}
// -------------------- EVENTS FROM CHILDCONTROL --------------------
Ruud Overeem
committed
//
// That must be events from the ObservationControllers that are currently
// started or running.
//
// Child control received a message from the startDaemon that the
// observationController was started (or not)
LOG_DEBUG_STR("Start of " << msg.cntlrName <<
" was successful, waiting for connection.");
}
else {
LOG_ERROR_STR("Observation controller " << msg.cntlrName <<
" could not be started");
LOG_INFO_STR("Observation is be removed from administration, " <<
"restart will occur in next cycle");
Ruud Overeem
committed
itsControllerMap.erase(msg.cntlrName);
Ruud Overeem
committed
case CONTROL_CONNECTED: {
// The observationController has registered itself at childControl.
Ruud Overeem
committed
CONTROLConnectedEvent conEvent(event);
Arno Schoenmakers
committed
LOG_DEBUG_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.
Ruud Overeem
committed
CMiter theObs(itsControllerMap.find(conEvent.cntlrName));
if (theObs == itsControllerMap.end()) {
LOG_WARN_STR("Cannot find controller " << conEvent.cntlrName <<
". Can't update the SAS database");
break;
}
OTDB::TreeMaintenance tm(itsOTDBconnection);
TreeStateConv tsc(itsOTDBconnection);
Ruud Overeem
committed
tm.setTreeState(theObs->second, tsc.get("queued"));
Arno Schoenmakers
committed
LOG_DEBUG_STR("Received QUITED(" << quitedEvent.cntlrName << "," << quitedEvent.result << ")");
Ruud Overeem
committed
CMiter theObs(itsControllerMap.find(quitedEvent.cntlrName));
if (theObs == itsControllerMap.end()) {
LOG_WARN_STR("Cannot find controller " << quitedEvent.cntlrName <<
". Can't update the SAS database");
break;
}
OTDB::TreeMaintenance tm(itsOTDBconnection);
TreeStateConv tsc(itsOTDBconnection);
// CT_RESULT_: MANUAL_REMOVED, MANUAL_ABORT, LOST_CONNECTION, NO_ERROR
Ruud Overeem
committed
tm.setTreeState(theObs->second, tsc.get("finished"));
Ruud Overeem
committed
tm.setTreeState(theObs->second, tsc.get("aborted"));
LOG_DEBUG_STR("Removing observation " << quitedEvent.cntlrName << " from activeList");
itsControllerMap.erase(quitedEvent.cntlrName);
case CONTROL_RESUMED: {
// update SAS database.
CONTROLResumedEvent msg(event);
Ruud Overeem
committed
CMiter theObs(itsControllerMap.find(msg.cntlrName));
if (theObs == itsControllerMap.end()) {
LOG_WARN_STR("Cannot find controller " << msg.cntlrName <<
". Can't update the SAS database");
break;
}
OTDB::TreeMaintenance tm(itsOTDBconnection);
TreeStateConv tsc(itsOTDBconnection);
Ruud Overeem
committed
tm.setTreeState(theObs->second, tsc.get("active"));
// NOTE: ignore all other CONTROL events, we are not interested in the
// states of the Observations. (not our job).
status = GCFEvent::NOT_HANDLED;
break;
}
return (status);
}
//
// finishing_state(event, port)
//
// Write controller state to PVSS, wait for 1 second (using a timer) to let GCF handle the property change
// and close the controller
//
GCFEvent::TResult MACScheduler::finishing_state(GCFEvent& event, GCFPortInterface& port)
{
LOG_DEBUG_STR ("finishing_state:" << eventName(event) << "@" << port.getName());
GCFEvent::TResult status = GCFEvent::HANDLED;
switch (event.signal) {
case F_INIT:
break;
case F_ENTRY: {
// update PVSS
Ruud Overeem
committed
itsPropertySet->setValue(PN_FSM_CURRENT_ACTION, GCFPVString("finished"));
itsPropertySet->setValue(PN_FSM_ERROR, GCFPVString(""));
itsPropertySet->setValue(PN_MS_OTDB_CONNECTED, GCFPVBool (false));
itsTimerPort->setTimer(1L);
break;
}
case F_TIMER:
break;
default:
LOG_DEBUG("finishing_state, default");
status = GCFEvent::NOT_HANDLED;
break;
}
return (status);
}
//
// finish
//
// Make the transition to the finishing state
//
void MACScheduler::finish()
{
TRAN(MACScheduler::finishing_state);
}
//
// _doOTDBcheck
//
// Check if a new action should be taken based on the contents of OTDB and our own
// administration.
//
void MACScheduler::_doOTDBcheck()
{
Ruud Overeem
committed
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
time_t now = time(0);
ptime currentTime = from_time_t(now);
itsPropertySet->setValue(string(PN_MS_OTDB_LAST_POLL), GCFPVString(to_simple_string(currentTime)));
// always update planned list because we might need to start some of those
// (and we assumed that the PlannedItv was the smallest)
_updatePlannedList();
// update active lists when its time to do so.
if (now >= itsNextActiveTime) {
_updateActiveList();
while (itsNextActiveTime <= now) {
itsNextActiveTime += itsActiveItv;
}
}
// update finished lists when its time to do so.
if (now >= itsNextFinishedTime) {
_updateFinishedList();
while (itsNextFinishedTime <= now) {
itsNextFinishedTime += itsFinishedItv;
}
}
}
//
// _updatePlannedList()
//
void MACScheduler::_updatePlannedList()
{
LOG_DEBUG("_updatePlannedList()");
Ruud Overeem
committed
// get time info
time_t now = time(0);
ptime currentTime = from_time_t(now);
ASSERTSTR (currentTime != not_a_date_time, "Can't determine systemtime, bailing out");
Ruud Overeem
committed
vector<OTDBtree> plannedDBlist = itsOTDBconnection->getTreeGroup(1, itsPlannedPeriod); // planned observations
Arno Schoenmakers
committed
LOG_DEBUG(formatString("OTDBCheck:First planned observation (%d) is at %s (active over %d seconds)",
Ruud Overeem
committed
plannedDBlist[0].treeID(), to_simple_string(plannedDBlist[0].starttime).c_str(),
Arno Schoenmakers
committed
time_duration(plannedDBlist[0].starttime - currentTime).total_seconds()));
}
// NOTE: do not exit routine on emptylist: we need to write an empty list to clear the DB
Arno Schoenmakers
committed
// make a copy of the current prepared observations (= observations shown in the navigator in the 'future'
// list). By eliminating the observations that are in the current SAS list we end up (at the end of this function)
// with a list of observations that were in the SASlist the last time but now not anymore. Normally those observations
// will appear in the active-list and will be removed there from the prepared list but WHEN AN OPERATOR CHANGES
// THE STATUS MANUALLY into something different (e.g. ON-HOLD) the observation stays in the preparedlist.
// EVEN WORSE: when the observation re-enters the system with different settings (again as scheduled) the system
// still knows the observation and will use the OLD information of the observation.
ObsList backupObsList = itsPreparedObs;
Ruud Overeem
committed
// walk through the list, prepare PVSS for the new obs, update own admin lists.
GCFPValueArray plannedArr;
int32 idx = MIN2(plannedDBlist.size(), itsMaxPlanned) - 1;
Arno Schoenmakers
committed
while (idx >= 0) {
Ruud Overeem
committed
// construct name and timings info for observation
treeIDType obsID = plannedDBlist[idx].treeID();
string obsName(observationName(obsID));
Ruud Overeem
committed
ptime modTime = plannedDBlist[idx].modificationDate;
Ruud Overeem
committed
Arno Schoenmakers
committed
// remove obs from backup of the planned-list (it is in the list again)
OLiter oldObsIter = backupObsList.find(obsID);
if (oldObsIter != backupObsList.end()) {
backupObsList.erase(oldObsIter);
}
Ruud Overeem
committed
// must we claim this observation at the claimMgr?
OLiter prepIter = itsPreparedObs.find(obsID);
Ruud Overeem
committed
if ((prepIter == itsPreparedObs.end()) || (prepIter->second.prepReady == false) ||
(prepIter->second.modTime != modTime)) {
Ruud Overeem
committed
// create a ParameterFile for this Observation
TreeMaintenance tm(itsOTDBconnection);
OTDBnode topNode = tm.getTopNode(obsID);
string filename(observationParset(obsID));
Ruud Overeem
committed
if (!tm.exportTree(obsID, topNode.nodeID(), filename)) {
LOG_ERROR_STR ("Cannot create ParameterSet '" << filename <<
"' for new observation. Observation CANNOT BE STARTED!");
Ruud Overeem
committed
}
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);
itsClaimerTask->prepareObservation(obsName);
Ruud Overeem
committed
itsPreparedObs[obsID] = schedInfo(modTime, false); // requested claim but no answer yet.
Ruud Overeem
committed
}
else {
// only add observations to the PVSS list when the claim was succesfull
// otherwise thing will go wrong in the Navigator
plannedArr.push_back(new GCFPVString(obsName));
}
Ruud Overeem
committed
// should this observation (have) be(en) started?
Arno Schoenmakers
committed
int timeBeforeStart = time_duration(plannedDBlist[idx].starttime - currentTime).total_seconds();
// LOG_DEBUG_STR(obsName << " starts over " << timeBeforeStart << " seconds");
if (timeBeforeStart > 0 && timeBeforeStart <= (int)itsQueuePeriod) {
Ruud Overeem
committed
if (itsPreparedObs[obsID].prepReady == false) {
Ruud Overeem
committed
LOG_ERROR_STR("Observation " << obsID << " must be started but is not claimed yet.");
Ruud Overeem
committed
// starttime of observation lays in queuePeriod. Start the controller-chain,
// this will result in CONTROL_STARTED event in our main task
// Note: as soon as the ObservationController has reported itself to the MACScheduler
// the observation will not be returned in the 'plannedDBlist' anymore.
string cntlrName(controllerName(CNTLRTYPE_OBSERVATIONCTRL, 0, obsID));
Arno Schoenmakers
committed
if (itsControllerMap.find(cntlrName) == itsControllerMap.end()) {
Arno Schoenmakers
committed
LOG_DEBUG_STR("Requesting start of " << cntlrName);
Arno Schoenmakers
committed
itsChildControl->startChild(CNTLRTYPE_OBSERVATIONCTRL,
obsID,
0, // instanceNr
myHostname(true));
// Note: controller is now in state NO_STATE/CONNECTED (C/R)
// add controller to our 'monitor' administration
itsControllerMap[cntlrName] = obsID;
LOG_DEBUG_STR("itsControllerMap[" << cntlrName << "]=" << obsID);
}
else {
LOG_DEBUG_STR("Observation " << obsID << " is already (being) started");
}
Arno Schoenmakers
committed
idx--;
Ruud Overeem
committed
} // while processing all planned obs'
Ruud Overeem
committed
// Finally we can pass the list with planned observations to PVSS.
itsPropertySet->setValue(PN_MS_PLANNED_OBSERVATIONS, GCFPVDynArr(LPT_DYNSTRING, plannedArr));
itsNrPlanned = plannedArr.size();
Arno Schoenmakers
committed
// free used memory
for (int i = plannedArr.size()-1; i>=0; --i) {
delete plannedArr[i];
}
Arno Schoenmakers
committed
// the backupObsList now contains the observations that were are in the preparedObs list but are not in
// the SAS list anymore. Remove them here from the preparedObs list.
OLiter oldObsIter = backupObsList.begin();
OLiter prepIter;
while (oldObsIter != backupObsList.end()) {
prepIter = itsPreparedObs.find(oldObsIter->first);
if (prepIter != itsPreparedObs.end()) {
Arno Schoenmakers
committed
LOG_INFO_STR("Removing " << oldObsIter->first << " from the 'preparing' list.");
Arno Schoenmakers
committed
itsPreparedObs.erase(prepIter);
}
oldObsIter++;
}
Ruud Overeem
committed
// _updateActiveList()
Ruud Overeem
committed
void MACScheduler::_updateActiveList()
Ruud Overeem
committed
LOG_DEBUG("_updateActiveList()");
Ruud Overeem
committed
// get new list (list is ordered on starttime)
vector<OTDBtree> activeDBlist = itsOTDBconnection->getTreeGroup(2, 0);
if (activeDBlist.empty()) {
LOG_DEBUG ("No active Observations");
// NOTE: do not exit routine on emptylist: we need to write an empty list to clear the DB
Ruud Overeem
committed
// walk through the list, prepare PVSS for the new obs, update own admin lists.
GCFPValueArray activeArr;
Arno Schoenmakers
committed
int32 idx = activeDBlist.size() - 1;
while (idx >= 0) {
Ruud Overeem
committed
// construct name and timings info for observation
string obsName(observationName(activeDBlist[idx].treeID()));
Ruud Overeem
committed
activeArr.push_back(new GCFPVString(obsName));
// remove obs from planned-list if its still their.
OLiter prepIter = itsPreparedObs.find(activeDBlist[idx].treeID());
if (prepIter != itsPreparedObs.end()) {
itsPreparedObs.erase(prepIter);
}
Arno Schoenmakers
committed
idx--;
Ruud Overeem
committed
} // while
// Finally we can pass the list with active observations to PVSS.
Ruud Overeem
committed
itsPropertySet->setValue(PN_MS_ACTIVE_OBSERVATIONS, GCFPVDynArr(LPT_DYNSTRING, activeArr));
itsNrActive = activeArr.size();
Arno Schoenmakers
committed
// free used memory
for (int i = activeArr.size()-1; i>=0; --i) {
delete activeArr[i];
}
Ruud Overeem
committed
// _updateFinishedList()
Ruud Overeem
committed
void MACScheduler::_updateFinishedList()
Ruud Overeem
committed
LOG_DEBUG("_updateFinishedList()");
Ruud Overeem
committed
// get new list (list is ordered on starttime)
vector<OTDBtree> finishedDBlist = itsOTDBconnection->getTreeGroup(3, itsFinishedPeriod);
if (finishedDBlist.empty()) {
LOG_DEBUG ("No finished Observations");
// NOTE: do not exit routine on emptylist: we need to write an empty list to clear the DB
Ruud Overeem
committed
// walk through the list, prepare PVSS for the new obs, update own admin lists.
// We must show the last part of the (optional) limited list.
Ruud Overeem
committed
GCFPValueArray finishedArr;
int32 freeSpace = MAX_CONCURRENT_OBSERVATIONS - itsNrPlanned - itsNrActive;
int32 idx = finishedDBlist.size() - 1;
int32 limit = idx - (MIN2(MIN2(finishedDBlist.size(), itsMaxFinished), (uint32)freeSpace) - 1);
Ruud Overeem
committed
// construct name and timings info for observation
string obsName(observationName(finishedDBlist[idx].treeID()));
Ruud Overeem
committed
finishedArr.push_back(new GCFPVString(obsName));
Arno Schoenmakers
committed
idx--;
Ruud Overeem
committed
} // while
// Finally we can pass the list with finished observations to PVSS.
Arno Schoenmakers
committed
itsPropertySet->setValue(PN_MS_FINISHED_OBSERVATIONS, GCFPVDynArr(LPT_DYNSTRING, finishedArr));
Arno Schoenmakers
committed
// free used memory
for (int i = finishedArr.size()-1; i>=0; --i) {
delete finishedArr[i];
}