diff --git a/.gitattributes b/.gitattributes index 59b55c7589b8718249561160631a2d42d2d1ced4..892f62bdd43862f18e25a8d4b815f05366febed3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -242,10 +242,12 @@ MAC/APL/_GSO/MACScheduler/src/MACScheduler.log_prop.in -text svneol=native#appli MAC/APL/_GSO/MACScheduler/src/Makefile.am -text svneol=native#application/octet-stream MAC/APL/_GSO/MACScheduler/src/SAS_Protocol.prot -text svneol=native#application/octet-stream MAC/APL/_GSO/MACScheduler/src/customPrepPVSSDB.ctl.in -text svneol=native#application/octet-stream +MAC/APL/_GSO/MACScheduler/test/BeamletAllocatorTest.log_prop.in -text svneol=native#application/octet-stream MAC/APL/_GSO/MACScheduler/test/CCU_increment1[!!-~]newbse.btsw -text svneol=native#application/octet-stream MAC/APL/_GSO/MACScheduler/test/CCU_increment1.btsw -text svneol=native#application/octet-stream MAC/APL/_GSO/MACScheduler/test/CCU_increment1.io -text svneol=native#application/octet-stream MAC/APL/_GSO/MACScheduler/test/CCU_increment1.prot -text svneol=native#application/octet-stream +MAC/APL/_GSO/MACScheduler/test/Makefile.am -text svneol=native#application/octet-stream MAC/APL/_GSO/MACScheduler/test/VI1.ps -text svneol=native#application/octet-stream MAC/APL/_GSO/MACScheduler/test/VI1.ps.cepemulatie -text svneol=native#application/octet-stream MAC/APL/_GSO/MACScheduler/test/VI1.ps.cepreal -text svneol=native#application/octet-stream diff --git a/MAC/APL/_GSO/MACScheduler/Makefile.am b/MAC/APL/_GSO/MACScheduler/Makefile.am index 4700d27db8516bebe3857fa6007afdf29a489a38..9bf2d143595794132d5d2ed7c6d8445e652462be 100644 --- a/MAC/APL/_GSO/MACScheduler/Makefile.am +++ b/MAC/APL/_GSO/MACScheduler/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS=src +SUBDIRS=src test include $(lofar_sharedir)/Makefile.common diff --git a/MAC/APL/_GSO/MACScheduler/configure.in b/MAC/APL/_GSO/MACScheduler/configure.in index 18796f670abe1e03f534ccf6bb6151cc98f1da2c..0123a90d607ee2181ff4a1373b531fcbe32c5a62 100644 --- a/MAC/APL/_GSO/MACScheduler/configure.in +++ b/MAC/APL/_GSO/MACScheduler/configure.in @@ -75,5 +75,6 @@ dnl Output Makefiles dnl AC_OUTPUT( src/Makefile +test/Makefile Makefile ) diff --git a/MAC/APL/_GSO/MACScheduler/src/BeamletAllocator.cc b/MAC/APL/_GSO/MACScheduler/src/BeamletAllocator.cc index beaeb759799d027594162f4404932af2a97c2bd7..e95ddeb20a2e9eb56905e71f32276f83d87055a6 100644 --- a/MAC/APL/_GSO/MACScheduler/src/BeamletAllocator.cc +++ b/MAC/APL/_GSO/MACScheduler/src/BeamletAllocator.cc @@ -23,6 +23,7 @@ #undef PACKAGE #undef VERSION #include <lofar_config.h> +#include <Common/lofar_sstream.h> #include <Common/LofarLogger.h> #include <APLCommon/APLUtilities.h> @@ -30,7 +31,6 @@ INIT_TRACER_CONTEXT(LOFAR::GSO::BeamletAllocator,LOFARLOGGER_PACKAGE); -using namespace LOFAR::GCF::Common; using namespace LOFAR::APLCommon; namespace LOFAR @@ -39,84 +39,347 @@ namespace LOFAR namespace GSO { -BeamletAllocator::BeamletAllocator() : - m_allocation() +BeamletAllocator::BeamletAllocator(int16 maxBeamlets) : + m_allocation(), + m_maxBeamlets(maxBeamlets) { - LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,getName().c_str()); + LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,"BeamletAllocator"); } BeamletAllocator::~BeamletAllocator() { - LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,getName().c_str()); + LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,"BeamletAllocator"); } bool BeamletAllocator::allocateBeamlets( - string station, - time_t startTime, - time_t stopTime, - vector<int16> subbands, - vector<int16>& beamlets) + const string& vi, + const vector<string> stations, + const time_t startTime, + const time_t stopTime, + const vector<int16> subbands, + TStationBeamletAllocation& allocation) { - LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,getName().c_str()); + LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,"BeamletAllocator"); + + // First the current allocation of a VI is removed. + // The the new allocation is tested and added. + // Finally, if the new allocation does not fit, + // the extracted allocated is re-inserted + + TStation2AllocationMapPtr oldAllocationDetailsPtr(new TStation2AllocationMap); + TStation2AllocationMapPtr newAllocationDetailsPtr(new TStation2AllocationMap); + + _extractAllocation(vi,oldAllocationDetailsPtr); + bool allocationOk = _testAllocateBeamlets(vi,stations,startTime,stopTime,subbands,newAllocationDetailsPtr,allocation); + if(allocationOk) + { + allocationOk = _mergeAllocation(newAllocationDetailsPtr); + } + else + { + _mergeAllocation(oldAllocationDetailsPtr); + } + return allocationOk; +} + +void BeamletAllocator::deallocateBeamlets(const string& vi) +{ + LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,"BeamletAllocator"); + + // Deallocate a VI by removing the current allocation + + TStation2AllocationMapPtr oldAllocationDetailsPtr(new TStation2AllocationMap); + _extractAllocation(vi,oldAllocationDetailsPtr); +} + +void BeamletAllocator::logAllocation(bool groupByVI) +{ + LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,"BeamletAllocator"); + + map<string,string> logs; + map<string,string>::iterator logsIterator; + TStation2AllocationMap::iterator itStationAllocation; + + for(itStationAllocation = m_allocation.begin();itStationAllocation != m_allocation.end();++itStationAllocation) + { + TBeamlet2AllocationMap::iterator itBeamletAllocation; + for(itBeamletAllocation = itStationAllocation->second.begin();itBeamletAllocation != itStationAllocation->second.end();++itBeamletAllocation) + { + TAllocationInfoVector::iterator itAllocationInfo; + for(itAllocationInfo = itBeamletAllocation->second.begin();itAllocationInfo != itBeamletAllocation->second.end();++itAllocationInfo) + { + tm* pStartTm = localtime(&itAllocationInfo->startTime); + char startTimeStr[100]; + sprintf(startTimeStr,"%02d-%02d-%04d %02d:%02d:%02d",pStartTm->tm_mday,pStartTm->tm_mon+1,pStartTm->tm_year+1900,pStartTm->tm_hour,pStartTm->tm_min,pStartTm->tm_sec); + + tm* pStopTm = localtime(&itAllocationInfo->stopTime); + char stopTimeStr[100]; + sprintf(stopTimeStr,"%02d-%02d-%04d %02d:%02d:%02d",pStopTm->tm_mday,pStopTm->tm_mon+1,pStopTm->tm_year+1900,pStopTm->tm_hour,pStopTm->tm_min,pStopTm->tm_sec); + + char allocationStr[100]; + sprintf(allocationStr,"%03d,->,%03d",itBeamletAllocation->first,itAllocationInfo->subband); + + stringstream logStream; + + if(groupByVI) + { + logStream << itAllocationInfo->vi << ","; + logStream << itStationAllocation->first << ","; + } + else + { + logStream << itStationAllocation->first << ","; + logStream << itAllocationInfo->vi << ","; + } + logStream << allocationStr << ","; + logStream << startTimeStr << ","; + logStream << stopTimeStr << endl; + + string log; + string key = itStationAllocation->first; + if(groupByVI) + { + key = itAllocationInfo->vi; + } + logsIterator = logs.find(key); + if(logsIterator != logs.end()) + { + log = logsIterator->second; + } + logs[key] = log+logStream.str(); + } + } + } + + string logString("Current beamlet allocation:\n"); + if(groupByVI) + { + logString += "VI, Station, beamlet->subband, starttime, stoptime\n"; + } + else + { + logString += "Station, VI, beamlet->subband, starttime, stoptime\n"; + } + for(logsIterator=logs.begin();logsIterator!=logs.end();++logsIterator) + { + logString+=logsIterator->second; + } + LOG_DEBUG(logString.c_str()); +} + +BeamletAllocator::TStation2AllocationMap::iterator BeamletAllocator::_addStationAllocation(const string& station) +{ + LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,"BeamletAllocator"); + + // add empty allocation vectors for all beamlets + TAllocationInfoVector emptyVector; + TBeamlet2AllocationMap beamlet2AllocationMap; + for(int16 beamlet=0;beamlet<m_maxBeamlets;beamlet++) + { + beamlet2AllocationMap[beamlet] = emptyVector; + } + pair<TStation2AllocationMap::iterator,bool> inserted; + inserted = m_allocation.insert(TStation2AllocationMap::value_type(station,beamlet2AllocationMap)); + return inserted.first; +} + +bool BeamletAllocator::_testAllocateBeamlets( + const string& vi, + const vector<string> stations, + const time_t startTime, + const time_t stopTime, + const vector<int16> subbands, + TStation2AllocationMapPtr& newAllocationDetailsPtr, + TStationBeamletAllocation& newAllocationBeamlets) +{ + LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,"BeamletAllocator"); time_t timeNow = APLUtilities::getUTCtime(); + bool allocationOk(true); + newAllocationDetailsPtr->clear(); + newAllocationBeamlets.clear(); - bool result(true); - TStation2AllocationMap::iterator itStationAllocation = m_allocation.find(station); - if(itStationAllocation != m_allocation.end()) + vector<string>::const_iterator itStation; + for(itStation = stations.begin();allocationOk && itStation != stations.end(); ++itStation) { - vector<int16>::iterator itSubbands = subbands.begin(); - TBeamlet2AllocationMap::iterator itBeamletAllocation = itStationAllocation.second.begin(); - while(result && itSubbands!=subbands.end() && itBeamletAllocation != itStationAllocation.second.end()) + vector<int16> beamletVector; + TBeamlet2AllocationMap beamletAllocationMap; + + TStation2AllocationMap::iterator itStationAllocation = m_allocation.find(*itStation); + if(itStationAllocation == m_allocation.end()) + { + LOG_TRACE_FLOW(formatString("Adding station %s to allocation data",itStation->c_str())); + itStationAllocation = _addStationAllocation(*itStation); + } + if(itStationAllocation == m_allocation.end()) + { + allocationOk = false; + LOG_FATAL(formatString("Beamlet allocation for station %s, VI %s failed",itStation->c_str(),vi.c_str())); + } + else { - bool allocated=false; - // search the next free beamlet - while(!allocated && itBeamletAllocation != itStationAllocation.second.end()) + // station found in allocation administration. + // Check its current allocation + vector<int16>::const_iterator itSubbands = subbands.begin(); + TBeamlet2AllocationMap::iterator itBeamletAllocation = itStationAllocation->second.begin(); + while(allocationOk && itSubbands!=subbands.end() && itBeamletAllocation != itStationAllocation->second.end()) { - // check ALL allocations for one beamlet - bool roomForAllocation(true); - TAllocationInfoVector::iterator itAllocationInfo = itBeamletAllocation.second.begin(); - while(roomForAllocation && itAllocationInfo != itBeamletAllocation.second.end()) + bool allocated=false; + // search the next free beamlet + while(!allocated && itBeamletAllocation != itStationAllocation->second.end()) { - // overlapping start/stoptimes not allowed - if(startTime <= itAllocationInfo->stopTime && stopTime >= itAllocationInfo->startTime) - roomForAllocation=false; + // check ALL allocations for one beamlet + bool roomForAllocation(true); + TAllocationInfoVector::iterator itAllocationInfo = itBeamletAllocation->second.begin(); + while(roomForAllocation && itAllocationInfo != itBeamletAllocation->second.end()) + { + // overlapping start/stoptimes not allowed + if(startTime < itAllocationInfo->stopTime && stopTime > itAllocationInfo->startTime) + { + roomForAllocation=false; + } + + // garbage collection on the fly: remove allocations with stoptimes before now + if(itAllocationInfo->stopTime < timeNow) + { + itAllocationInfo = itBeamletAllocation->second.erase(itAllocationInfo); + } + else + { + ++itAllocationInfo; + } + } + if(roomForAllocation) + { + // Yes, this beamlet is free for allocation + TAllocationInfo newAllocation; + newAllocation.vi = vi; + newAllocation.startTime = startTime; + newAllocation.stopTime = stopTime; + newAllocation.subband = (*itSubbands); - // garbage collection on the fly: remove allocations with stoptimes before now - TAllocationInfoVector::iterator itAllocationInfoGarbage = itAllocationInfo; - ++itAllocationInfo; - if(itAllocationInfoGarbage->stopTime < timeNow) - itBeamletAllocation.second.erase(itAllocationInfoGarbage); + TAllocationInfoVector allocationVector; + allocationVector.push_back(newAllocation); + beamletAllocationMap[itBeamletAllocation->first] = allocationVector; + beamletVector.push_back(itBeamletAllocation->first); + + allocated=true; + } + ++itBeamletAllocation; // next round: begin with the next beamlet because the current has been allocated. } - if(roomForAllocation) + if(!allocated) { - beamlets.push_back(itBeamletAllocation.first); - - TAllocationInfo newAllocation; - newAllocation.startTime = startTime; - newAllocation.stopTime = stopTime; - newAllocation.subband = (*itSubbands); - itBeamletAllocation.second.push_back(newAllocation); - - allocated=true + allocationOk = false; + LOG_FATAL(formatString("Beamlet allocation for station %s, VI %s, subband %d failed",itStation->c_str(),vi.c_str(),(*itSubbands))); } - ++itBeamletAllocation; // next round: begin with the next beamlet because the current has been allocated. + ++itSubbands; // allocate next subband } - if(!allocated) + if(itSubbands!=subbands.end()) { - result = false; + allocationOk = false; + LOG_FATAL(formatString("Beamlet allocation for station %s, VI %s failed",itStation->c_str(),vi.c_str())); } - ++itSubbands; // allocate next subband } + if(allocationOk) + { + (*newAllocationDetailsPtr)[*itStation] = beamletAllocationMap; + newAllocationBeamlets[*itStation] = beamletVector; + } + } + + if(!allocationOk) + { + newAllocationDetailsPtr->clear(); + newAllocationBeamlets.clear(); } - else + return allocationOk; +} + +bool BeamletAllocator::_mergeAllocation(TStation2AllocationMapPtr newAllocationDetailsPtr) +{ + LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,"BeamletAllocator"); + + // merge the new allocation with the existing allocation + + bool allocationOk = true; + + for(TStation2AllocationMap::iterator itNewStationAllocation = newAllocationDetailsPtr->begin();itNewStationAllocation != newAllocationDetailsPtr->end();++itNewStationAllocation) { - // add new allocation + TStation2AllocationMap::iterator itStationAllocation = m_allocation.find(itNewStationAllocation->first); + if(itStationAllocation == m_allocation.end()) + { + allocationOk = false; + LOG_FATAL(formatString("Beamlet allocation for station %s failed",itNewStationAllocation->first.c_str())); + } + else + { + // station found in allocation administration; go through all beamlets. + TBeamlet2AllocationMap::iterator itNewBeamletAllocation = itNewStationAllocation->second.begin(); + while(allocationOk && itNewBeamletAllocation != itNewStationAllocation->second.end()) + { + TBeamlet2AllocationMap::iterator itBeamletAllocation = itStationAllocation->second.find(itNewBeamletAllocation->first); + if(itBeamletAllocation == itStationAllocation->second.end()) + { + allocationOk = false; + LOG_FATAL(formatString("Beamlet allocation for station %s, beamlet %d failed",itNewStationAllocation->first.c_str(),itNewBeamletAllocation->first)); + } + else + { + // merge the new allocation into the existing + itBeamletAllocation->second.insert(itBeamletAllocation->second.end(), + itNewBeamletAllocation->second.begin(), + itNewBeamletAllocation->second.end()); + ++itNewBeamletAllocation; + } + } + } } + return allocationOk; +} + +void BeamletAllocator::_extractAllocation(const string& vi, TStation2AllocationMapPtr& allocationDetailsPtr) +{ + LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,"BeamletAllocator"); - return result; + // Extract an allocation for a VI from the allocation administration. + // The extracted allocation details are returned to the caller + + allocationDetailsPtr->clear(); + TStation2AllocationMap::iterator itStationAllocation; + for(itStationAllocation = m_allocation.begin();itStationAllocation != m_allocation.end();++itStationAllocation) + { + TBeamlet2AllocationMap beamletAllocationMap; + TBeamlet2AllocationMap::iterator itBeamletAllocation; + for(itBeamletAllocation = itStationAllocation->second.begin();itBeamletAllocation != itStationAllocation->second.end();++itBeamletAllocation) + { + TAllocationInfoVector::iterator itAllocationInfo = itBeamletAllocation->second.begin(); + while(itAllocationInfo != itBeamletAllocation->second.end()) + { + if(itAllocationInfo->vi == vi) + { + TAllocationInfo allocation; + allocation.vi = itAllocationInfo->vi; + allocation.startTime = itAllocationInfo->startTime; + allocation.stopTime = itAllocationInfo->stopTime; + allocation.subband = itAllocationInfo->subband; + + TAllocationInfoVector allocationVector; + allocationVector.push_back(allocation); + beamletAllocationMap[itBeamletAllocation->first] = allocationVector; + + itAllocationInfo = itBeamletAllocation->second.erase(itAllocationInfo); + } + else + { + ++itAllocationInfo; + } + } + } + (*allocationDetailsPtr)[itStationAllocation->first] = beamletAllocationMap; + } } + }; }; diff --git a/MAC/APL/_GSO/MACScheduler/src/BeamletAllocator.h b/MAC/APL/_GSO/MACScheduler/src/BeamletAllocator.h index bc9a193d95d4301db3c8b83c8f0755b5d615ef93..bc5da970e4cd17089d9360aca11097f13f475da0 100644 --- a/MAC/APL/_GSO/MACScheduler/src/BeamletAllocator.h +++ b/MAC/APL/_GSO/MACScheduler/src/BeamletAllocator.h @@ -24,6 +24,7 @@ #define BeamletAllocator_H //# Includes +#include <boost/shared_ptr.hpp> //# GCF Includes @@ -46,10 +47,19 @@ namespace GSO class BeamletAllocator { public: - BeamletAllocator(); + typedef map<string, vector<int16> > TStationBeamletAllocation; + + BeamletAllocator(int16 maxBeamlets); virtual ~BeamletAllocator(); - bool allocateBeamlets(vector<string> stations, vector<int16> subbands, time_t startTime, time_t stopTime, vector<int16>& beamlets); + bool allocateBeamlets(const string& vi, + const vector<string> stations, + const time_t startTime, + const time_t stopTime, + const vector<int16> subbands, + TStationBeamletAllocation& allocation); + void deallocateBeamlets(const string& vi); + void logAllocation(bool groupByVI=false); protected: // protected copy constructor @@ -60,15 +70,29 @@ namespace GSO private: typedef struct { - int16 subband; - time_t startTime; - time_t stopTime; + int16 subband; + string vi; + time_t startTime; + time_t stopTime; } TAllocationInfo; typedef vector<TAllocationInfo> TAllocationInfoVector; typedef map<int16, TAllocationInfoVector> TBeamlet2AllocationMap; typedef map<string, TBeamlet2AllocationMap> TStation2AllocationMap; + typedef boost::shared_ptr<TStation2AllocationMap> TStation2AllocationMapPtr; + + TStation2AllocationMap::iterator _addStationAllocation(const string& station); + bool _testAllocateBeamlets(const string& vi, + const vector<string> stations, + const time_t startTime, + const time_t stopTime, + const vector<int16> subbands, + TStation2AllocationMapPtr& newAllocationDetailsPtr, + TStationBeamletAllocation& newAllocationBeamlets); + bool _mergeAllocation(TStation2AllocationMapPtr newAllocationDetailsPtr); + void _extractAllocation(const string& vi, TStation2AllocationMapPtr& allocationDetailsPtr); TStation2AllocationMap m_allocation; + const int16 m_maxBeamlets; ALLOC_TRACER_CONTEXT }; diff --git a/MAC/APL/_GSO/MACScheduler/src/MACScheduler.cc b/MAC/APL/_GSO/MACScheduler/src/MACScheduler.cc index 5d401587fc1c6b56df41564a60bd90bb110c627f..82e166d23c3763c51815408c44ad5d690bf13d00 100644 --- a/MAC/APL/_GSO/MACScheduler/src/MACScheduler.cc +++ b/MAC/APL/_GSO/MACScheduler/src/MACScheduler.cc @@ -30,7 +30,6 @@ #include <GCF/GCF_PVInteger.h> #include "APLCommon/APLUtilities.h" -#include "BeamletAllocator.h" #include "MACScheduler.h" #define ADJUSTEVENTSTRINGPARAMTOBSE(str) \ @@ -83,7 +82,7 @@ MACScheduler::MACScheduler() : #ifndef ACC_CONFIGURATIONMGR_UNAVAILABLE m_configurationManager(), #endif // ACC_CONFIGURATIONMGR_UNAVAILABLE - m_beamletAllocator() + m_beamletAllocator(128) { LOG_TRACE_LIFETIME(TRACE_LEVEL_FLOW,getName().c_str()); @@ -830,10 +829,11 @@ void MACScheduler::_handleSASprotocol(GCFEvent& event, GCFPortInterface& port) // make all relative times absolute _convertRelativeTimes(ps); - if(!m_beamletAllocator.allocateBeamlets(ps)) + if(!_allocateBeamlets(sasScheduleEvent.VIrootID,ps)) { SASResponseEvent sasResponseEvent; sasResponseEvent.result = SAS_RESULT_ERROR_BEAMLET_ALLOCATION_FAILED; + sasResponseEvent.VIrootID = sasScheduleEvent.VIrootID; ADJUSTEVENTSTRINGPARAMTOBSE(sasResponseEvent.VIrootID) @@ -870,6 +870,7 @@ ADJUSTEVENTSTRINGPARAMTOBSE(sdScheduleEvent.fileName) { SASResponseEvent sasResponseEvent; sasResponseEvent.result = SAS_RESULT_ERROR_VI_NOT_FOUND; + sasResponseEvent.VIrootID = sasScheduleEvent.VIrootID; ADJUSTEVENTSTRINGPARAMTOBSE(sasResponseEvent.VIrootID) @@ -882,6 +883,7 @@ ADJUSTEVENTSTRINGPARAMTOBSE(sasResponseEvent.VIrootID) LOG_FATAL(formatString("Error reading schedule parameters: %s",e.message().c_str())); SASResponseEvent sasResponseEvent; sasResponseEvent.result = SAS_RESULT_ERROR_UNSPECIFIED; + sasResponseEvent.VIrootID = sasScheduleEvent.VIrootID; ADJUSTEVENTSTRINGPARAMTOBSE(sasResponseEvent.VIrootID) @@ -922,17 +924,21 @@ ADJUSTEVENTSTRINGPARAMTOBSE(sasResponseEvent.VIrootID) { SASResponseEvent sasResponseEvent; sasResponseEvent.result = SAS_RESULT_ERROR_VI_NOT_FOUND; + sasResponseEvent.VIrootID = sasCancelScheduleEvent.VIrootID; ADJUSTEVENTSTRINGPARAMTOBSE(sasResponseEvent.VIrootID) port.send(sasResponseEvent); - } + } + + m_beamletAllocator.deallocateBeamlets(sasCancelScheduleEvent.VIrootID); } catch(Exception& e) { LOG_FATAL(formatString("Error reading schedule parameters: %s",e.message().c_str())); SASResponseEvent sasResponseEvent; sasResponseEvent.result = SAS_RESULT_ERROR_UNSPECIFIED; + sasResponseEvent.VIrootID = sasCancelScheduleEvent.VIrootID; ADJUSTEVENTSTRINGPARAMTOBSE(sasResponseEvent.VIrootID) @@ -993,6 +999,7 @@ ADJUSTEVENTSTRINGPARAMTOBSE(scheduleEvent.fileName) { SASResponseEvent sasResponseEvent; sasResponseEvent.result = SAS_RESULT_ERROR_VI_NOT_FOUND; + sasResponseEvent.VIrootID = sasUpdateScheduleEvent.VIrootID; ADJUSTEVENTSTRINGPARAMTOBSE(sasResponseEvent.VIrootID) @@ -1004,6 +1011,7 @@ ADJUSTEVENTSTRINGPARAMTOBSE(sasResponseEvent.VIrootID) LOG_FATAL(formatString("Error reading schedule parameters: %s",e.message().c_str())); SASResponseEvent sasResponseEvent; sasResponseEvent.result = SAS_RESULT_ERROR_UNSPECIFIED; + sasResponseEvent.VIrootID = sasUpdateScheduleEvent.VIrootID; ADJUSTEVENTSTRINGPARAMTOBSE(sasResponseEvent.VIrootID) @@ -1059,15 +1067,7 @@ void MACScheduler::_convertRelativeTimesChild(string child, boost::shared_ptr<AC string childs; vector<string> childKeys; childs = ps->getString(childsKey); - char* pch; - boost::shared_array<char> childsCopy(new char[childs.length()+1]); - strcpy(childsCopy.get(),childs.c_str()); - pch = strtok (childsCopy.get(),","); - while (pch != NULL) - { - childKeys.push_back(string(pch)); - pch = strtok (NULL, ","); - } + APLUtilities::string2Vector(childs,childKeys,','); vector<string>::iterator chIt; for(chIt=childKeys.begin(); chIt!=childKeys.end();++chIt) { @@ -1081,5 +1081,47 @@ void MACScheduler::_convertRelativeTimesChild(string child, boost::shared_ptr<AC } } +bool MACScheduler::_allocateBeamlets(const string& VIrootID, boost::shared_ptr<ACC::ParameterSet> ps) +{ + bool allocationOk(true); + + m_beamletAllocator.logAllocation(); + + vector<string> childKeys; + string childs = ps->getString("childs"); + APLUtilities::string2Vector(childs,childKeys,','); + + vector<string> stations; + string subbands = ps->getString("subbands"); + time_t startTime = ps->getInt("claimTime"); + time_t stopTime = ps->getInt("stopTime"); + vector<int16> subbandsVector; + APLUtilities::string2Vector(subbands,subbandsVector,'|'); + + for(vector<string>::iterator childsIt=childKeys.begin();allocationOk && childsIt!=childKeys.end();++childsIt) + { + string ldType = ps->getString(*childsIt + ".logicalDeviceType"); + if(ldType == string("VIRTUALTELESCOPE") || atoi(ldType.c_str()) == static_cast<int>(LDTYPE_VIRTUALTELESCOPE)) + { + stations.push_back(ps->getString(*childsIt + ".remoteSystem")); + } + } + + BeamletAllocator::TStationBeamletAllocation allocation; + allocationOk = m_beamletAllocator.allocateBeamlets( + VIrootID, + stations, + startTime, + stopTime, + subbandsVector, + allocation); + + // do something with it + + m_beamletAllocator.logAllocation(false); + + return allocationOk; +} + }; }; diff --git a/MAC/APL/_GSO/MACScheduler/src/MACScheduler.h b/MAC/APL/_GSO/MACScheduler/src/MACScheduler.h index 6c600a6b1f24987e93a0824bf7e5f4699fb01ed4..2d58d6219a799cd569090c5f162523687f72c5b1 100644 --- a/MAC/APL/_GSO/MACScheduler/src/MACScheduler.h +++ b/MAC/APL/_GSO/MACScheduler/src/MACScheduler.h @@ -40,6 +40,7 @@ #include "SAS_Protocol.ph" #include "APLCommon/LogicalDevice_Protocol.ph" #include "APLCommon/StartDaemon_Protocol.ph" +#include "BeamletAllocator.h" //# Common Includes #include <Common/lofar_string.h> @@ -146,6 +147,8 @@ namespace GSO void _convertRelativeTimes(boost::shared_ptr<ACC::ParameterSet> ps); void _convertRelativeTimesChild(string child, boost::shared_ptr<ACC::ParameterSet> ps); + bool _allocateBeamlets(const string& VIrootID, boost::shared_ptr<ACC::ParameterSet> ps); + string m_SASserverPortName; GCF::TM::GCFTCPPort m_SASserverPort; // SAS-MAC communication TTCPPortVector m_SASclientPorts; // connected SAS clients diff --git a/MAC/APL/_GSO/MACScheduler/src/SAS_Protocol.prot b/MAC/APL/_GSO/MACScheduler/src/SAS_Protocol.prot index 61ac9f078466e07199cafbbb799246b80aab8fe8..054d59ba295db96ba3181c55f0a40acfdcc0037f 100644 --- a/MAC/APL/_GSO/MACScheduler/src/SAS_Protocol.prot +++ b/MAC/APL/_GSO/MACScheduler/src/SAS_Protocol.prot @@ -49,7 +49,7 @@ enum TSASResult SAS_RESULT_ERROR_WRONG_STATE, SAS_RESULT_ERROR_SHUTDOWN, SAS_RESULT_ERROR_ALREADY_EXISTS, - + SAS_RESULT_ERROR_BEAMLET_ALLOCATION_FAILED }; PRELUDE_END; diff --git a/MAC/APL/_GSO/MACScheduler/test/BeamletAllocatorTest.cc b/MAC/APL/_GSO/MACScheduler/test/BeamletAllocatorTest.cc new file mode 100644 index 0000000000000000000000000000000000000000..78c22322081bb8160536854381664825ea0f6b68 --- /dev/null +++ b/MAC/APL/_GSO/MACScheduler/test/BeamletAllocatorTest.cc @@ -0,0 +1,298 @@ +//# BeamletAllocatorTest.cc: Main entry for the BeamletAllocator test +//# +//# 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 <sys/time.h> +#include <Common/LofarLogger.h> +#include <APLCommon/APLUtilities.h> +#include "../src/BeamletAllocator.h" + +using namespace LOFAR; +using namespace LOFAR::GSO; +using namespace LOFAR::APLCommon; + +int main(int argc, char* argv[]) +{ + int retval=0; + + INIT_LOGGER("./BeamletAllocatorTest.log_prop"); + + vector<string> stations1; + stations1.push_back(string("STS1")); + + vector<string> stations2; + stations2.push_back(string("STS1")); + stations2.push_back(string("STS2")); + + vector<string> stations3; + stations3.push_back(string("STS1")); + stations3.push_back(string("STS2")); + stations3.push_back(string("STS3")); + + vector<string> stations4; + stations4.push_back(string("STS1")); + stations4.push_back(string("STS2")); + stations4.push_back(string("STS3")); + stations4.push_back(string("STS4")); + + vector<string> vis; + vis.push_back(string("VI1")); + vis.push_back(string("VI2")); + vis.push_back(string("VI3")); + vis.push_back(string("VI4")); + vis.push_back(string("VI5")); + vis.push_back(string("VI6")); + vis.push_back(string("VI7")); + + vector<time_t> startTimes; + vector<time_t> stopTimes; + startTimes.push_back(APLUtilities::getUTCtime() +100); + stopTimes.push_back (APLUtilities::getUTCtime() +120); + startTimes.push_back(APLUtilities::getUTCtime() +50); + stopTimes.push_back (APLUtilities::getUTCtime() +70); + startTimes.push_back(APLUtilities::getUTCtime() +120); + stopTimes.push_back (APLUtilities::getUTCtime() +140); + startTimes.push_back(APLUtilities::getUTCtime() +90); + stopTimes.push_back (APLUtilities::getUTCtime() +110); + startTimes.push_back(APLUtilities::getUTCtime() +110); + stopTimes.push_back (APLUtilities::getUTCtime() +130); + startTimes.push_back(APLUtilities::getUTCtime() +90); + stopTimes.push_back (APLUtilities::getUTCtime() +130); + startTimes.push_back(APLUtilities::getUTCtime() +105); + stopTimes.push_back (APLUtilities::getUTCtime() +115); + + vector<int16> subbands; + for(int i=0;i<10;i++) + subbands.push_back(i); + + BeamletAllocator::TStationBeamletAllocation beamlets; + + { + BeamletAllocator beamletAllocator(25); + beamletAllocator.logAllocation(); + + LOG_INFO("Allocating 10 subbands for 1 station"); + if(!beamletAllocator.allocateBeamlets(vis[0],stations1,startTimes[0],stopTimes[0],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + + LOG_INFO("Deallocating 1 VI"); + beamletAllocator.deallocateBeamlets(vis[0]); + beamletAllocator.logAllocation(); + + LOG_INFO("Deallocating 1 VI"); + beamletAllocator.deallocateBeamlets(vis[0]); + beamletAllocator.logAllocation(); + + LOG_INFO("Allocating 10 subbands for 2 stations"); + if(!beamletAllocator.allocateBeamlets(vis[0],stations2,startTimes[0],stopTimes[0],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + + LOG_INFO("Reallocating 10 subbands for 2 stations"); + if(!beamletAllocator.allocateBeamlets(vis[0],stations2,startTimes[1],stopTimes[1],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + + LOG_INFO("Allocating 10 subbands for 1 station using overlapping times"); + if(!beamletAllocator.allocateBeamlets(vis[1],stations1,startTimes[1],stopTimes[1],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + + LOG_INFO("Allocating 10 subbands for 1 station at non-overlapping times"); + if(!beamletAllocator.allocateBeamlets(vis[2],stations1,startTimes[0],stopTimes[0],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + + LOG_INFO("Reallocating 10 subbands for 1 station at overlapping times. This must fail because not enough beamlets are available"); + if(beamletAllocator.allocateBeamlets(vis[2],stations1,startTimes[1],stopTimes[1],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + + LOG_INFO("Allocating 10 subbands for 1 station using overlapping times. This must fail because not enough beamlets are available"); + if(beamletAllocator.allocateBeamlets(vis[3],stations1,startTimes[1],stopTimes[1],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + + LOG_INFO("Deallocating 1 VI"); + beamletAllocator.deallocateBeamlets(vis[0]); + beamletAllocator.logAllocation(); + LOG_INFO("Deallocating 1 VI"); + beamletAllocator.deallocateBeamlets(vis[1]); + beamletAllocator.logAllocation(); + LOG_INFO("Deallocating 1 VI"); + beamletAllocator.deallocateBeamlets(vis[2]); + beamletAllocator.logAllocation(); + LOG_INFO("Deallocating 1 VI"); + beamletAllocator.deallocateBeamlets(vis[3]); + beamletAllocator.logAllocation(); + + LOG_INFO("Allocating 10 subbands for 1 station"); + if(!beamletAllocator.allocateBeamlets(vis[0],stations1,startTimes[0],stopTimes[0],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + LOG_INFO("Allocating 10 subbands for 1 station at non-overlapping times"); + if(!beamletAllocator.allocateBeamlets(vis[1],stations1,startTimes[1],stopTimes[1],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + LOG_INFO("Allocating 10 subbands for 1 station at non-overlapping times"); + if(!beamletAllocator.allocateBeamlets(vis[2],stations1,startTimes[2],stopTimes[2],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + LOG_INFO("Allocating 10 subbands for 1 station at overlapping times"); + if(!beamletAllocator.allocateBeamlets(vis[3],stations1,startTimes[3],stopTimes[3],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + LOG_INFO("Allocating 10 subbands for 2 stations at overlapping times"); + if(!beamletAllocator.allocateBeamlets(vis[4],stations2,startTimes[4],stopTimes[4],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + LOG_INFO("Allocating 10 subbands for 2 stations at overlapping times. This should fail because station1 has not enough beamlets available"); + if(beamletAllocator.allocateBeamlets(vis[5],stations2,startTimes[5],stopTimes[5],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + LOG_INFO("Allocating 10 subbands for 2 stations at overlapping times. This should fail because station1 has not enough beamlets available"); + if(beamletAllocator.allocateBeamlets(vis[6],stations2,startTimes[6],stopTimes[6],subbands,beamlets)) + { + LOG_FATAL("test failed"); + return -1; + } + beamletAllocator.logAllocation(); + beamletAllocator.logAllocation(true); + } + + { + vector<int16> allsubbands; + for(int i=0;i<200;i++) + allsubbands.push_back(i); + + vector<string> allvis; + vector<string> allstations; + vector<time_t> allstartTimes; + vector<time_t> allstopTimes; + for(int i=0;i<100;i++) + { + char tempStr[10]; + sprintf(tempStr,"STS%03d",i); + allstations.push_back(string(tempStr)); + + sprintf(tempStr,"VI%03d",i); + allvis.push_back(string(tempStr)); + + allstartTimes.push_back(APLUtilities::getUTCtime() + 1000 + i*10); + allstopTimes.push_back (APLUtilities::getUTCtime() + 1000 + i*10+5); + } + allvis.push_back(string("VI100")); + + BeamletAllocator beamletAllocator(200); + beamletAllocator.logAllocation(); + + LOG_INFO("and now something big"); + + struct timeval beginTv; + struct timeval endTv; + double t1,t2,timediff; + bool success; + + for(int t=0;t<5;t++) + { + gettimeofday(&beginTv,0); + success=beamletAllocator.allocateBeamlets(allvis[t],allstations,allstartTimes[t],allstopTimes[t],allsubbands,beamlets); + gettimeofday(&endTv,0); + t1 = beginTv.tv_sec + ((double)beginTv.tv_usec/1000000); + t2 = endTv.tv_sec + ((double)endTv.tv_usec/1000000); + timediff = t2-t1; + LOG_INFO(formatString("It took me (%f - %f = ) %f to allocate it all",t2,t1,timediff)); + if(!success) + { + LOG_FATAL("test failed"); + return -1; + } + } + + gettimeofday(&beginTv,0); + success=beamletAllocator.allocateBeamlets(allvis[100],allstations,allstartTimes[0],allstopTimes[0],allsubbands,beamlets); + gettimeofday(&endTv,0); + t1 = beginTv.tv_sec + ((double)beginTv.tv_usec/1000000); + t2 = endTv.tv_sec + ((double)endTv.tv_usec/1000000); + timediff = t2-t1; + LOG_INFO(formatString("It took me (%f - %f = ) %f to conclude that allocation is not possible",t2,t1,timediff)); + if(success) + { + LOG_FATAL("test failed"); + return -1; + } + + for(int t=0;t<5;t++) + { + gettimeofday(&beginTv,0); + beamletAllocator.deallocateBeamlets(allvis[t]); + gettimeofday(&endTv,0); + t1 = beginTv.tv_sec + ((double)beginTv.tv_usec/1000000); + t2 = endTv.tv_sec + ((double)endTv.tv_usec/1000000); + timediff = t2-t1; + LOG_INFO(formatString("It took me (%f - %f = ) %f to deallocate one VI",t2,t1,timediff)); + } + + //beamletAllocator.logAllocation(); + } + return retval; +} + diff --git a/MAC/APL/_GSO/MACScheduler/test/BeamletAllocatorTest.log_prop.in b/MAC/APL/_GSO/MACScheduler/test/BeamletAllocatorTest.log_prop.in new file mode 100644 index 0000000000000000000000000000000000000000..f7a9cfe90b84d069decc4cd2d2eda64a1d34c3a1 --- /dev/null +++ b/MAC/APL/_GSO/MACScheduler/test/BeamletAllocatorTest.log_prop.in @@ -0,0 +1,34 @@ +# add your custom loggers and appenders here +# + +log4cplus.rootLogger=INFO, STDOUT + +log4cplus.logger.TRC=PUTJE +log4cplus.additivity.TRC=FALSE + +log4cplus.logger.MAC=DEBUG, STDOUT, FILE +log4cplus.additivity.MAC=FALSE + +log4cplus.logger.TRC.MAC=TRACE, FILE +log4cplus.additivity.TRC.MAC=FALSE + +log4cplus.appender.PUTJE=log4cplus::NullAppender + +log4cplus.appender.STDOUT=log4cplus::ConsoleAppender +log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout +log4cplus.appender.STDOUT.layout.ConversionPattern=%x %D{%d-%m-%y %H:%M:%S} %-5p %c{9} - %m [%.25l]%n +log4cplus.appender.STDOUT.logToStdErr=true +#log4cplus.appender.STDOUT.Threshold=WARN +#log4cplus.appender.STDOUT.filters.1=log4cplus::spi::LogLevelRangeFilter +#log4cplus.appender.STDOUT.filters.1.LogLevelMin=INFO +#log4cplus.appender.STDOUT.filters.1.LogLevelMax=FATAL +#log4cplus.appender.STDOUT.filters.1.AcceptOnMatch=true +#log4cplus.appender.STDOUT.filters.2=log4cplus::spi::DenyAllFilter + +log4cplus.appender.FILE=log4cplus::RollingFileAppender +log4cplus.appender.FILE.File=BeamletAllocatorTest.log +log4cplus.appender.FILE.MaxFileSize=5MB +log4cplus.appender.FILE.MaxBackupIndex=5 +log4cplus.appender.FILE.layout=log4cplus::PatternLayout +log4cplus.appender.FILE.layout.ConversionPattern=%x %D{%d-%m-%y %H:%M:%S} %-5p %c{3} - %m [%.25l]%n + diff --git a/MAC/APL/_GSO/MACScheduler/test/Makefile.am b/MAC/APL/_GSO/MACScheduler/test/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..7e6ca1af38b634cdd63c94f255a23d700d91c94e --- /dev/null +++ b/MAC/APL/_GSO/MACScheduler/test/Makefile.am @@ -0,0 +1,22 @@ +noinst_PROGRAMS = BeamletAllocatorTest + +BeamletAllocatorTest_CPPFLAGS= \ + -Wno-deprecated \ + -fmessage-length=0 \ + -fdiagnostics-show-location=once + +BeamletAllocatorTest_SOURCES = \ + BeamletAllocatorTest.cc \ + $(top_srcdir)/src/BeamletAllocator.cc + +BeamletAllocatorTest_LDADD = + +BUILT_SOURCES = BeamletAllocatorTest.log_prop + +EXTRA_DIST = BeamletAllocatorTest.log_prop + +%.log_prop: %.log_prop.in + cp $< $@ + + +include $(lofar_sharedir)/Makefile.common diff --git a/MAC/APL/_GSO/MACScheduler/test/VI1.ps b/MAC/APL/_GSO/MACScheduler/test/VI1.ps index 9624439c9dfd15456ba0e98605cfc564734b1ccf..9ccd07afa2501e3e54cc09fc2d795ffedf943e04 100644 --- a/MAC/APL/_GSO/MACScheduler/test/VI1.ps +++ b/MAC/APL/_GSO/MACScheduler/test/VI1.ps @@ -15,6 +15,7 @@ claimTime=+20 prepareTime=+40 startTime=+115 stopTime=+648000 +subbands=0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27 childs=VT1,VT2,VB1 ###########################