BIter i;
BError err;
double t1, t2;
dprintf(DBG_EVENT, "Control::cycleStopEvent: %u\n", cycleNumber);
ocycleCompleteNumber.setValue(cycleNumber);
ocycleProcessed++;
// Check all requests
for(orequestList.start(i); !orequestList.isEnd(i); ){
if(cycleNumber >= orequestList[i].dataInfo.cycleNumber){
oeventServers.dataEvent(orequestList[i].dataInfo);
orequestList.del(i);
}
else {
orequestList.next(i);
}
}
oeventServers.cycleStopEvent(cycleNumber);
if(osimulation.setNextCycle){
t1 = getTime();
err = setNextCycleInternal(ocycleNumberNext, ocycleTypeNext);
t2 = getTime();
dprintf(DBG_SETNEXTCYCLE, "Send setNextCycle: %u current: %u Time: %fms Error: %s\n", ocycleNumberNext, cycleNumber, (t2 - t1) * 1000.0, err.getString().retStr());
ocycleNumberNext++;
}
}
BError Control::getData(DataInfo dataInfo, Data& data){
BError err;
BError e;
PuChannel puPhysChannel(0, 0, 1);
BList<BError> errList;
BUInt32 chan;
BUInt32 orbitNumber;
dprintf(DBG_CMD, "Control::getData\n");
// Setup for error return
data.numValues = 0;
data.dataType = 0;
data.numBunches = 0;
data.numChannels = 0;
// Check parameters
if(dataInfo.channel > oconfigInfo.puReferences.size())
return err.set(ErrorParam, "dataInfo.channel parameter is incorrect");
if(dataInfo.cyclePeriod > CyclePeriodEvent9)
return err.set(ErrorParam, "dataInfo.cyclePeriod parameter is incorrect");
if(dataInfo.startTime > 4000)
return err.set(ErrorParam, "dataInfo.startTime parameter is to large (max: 4000)");
if(dataInfo.orbitNumber > 1500000)
return err.set(ErrorParam, "dataInfo.orbitNumber parameter is to large (max: 1500000)");
if(dataInfo.bunchNumber > 500000)
return err.set(ErrorParam, "dataInfo.bunchNumber parameter is to large");
if(dataInfo.numValues > (40 * 8 * 500000))
return err.set(ErrorParam, "dataInfo.numValues parameter is to large (max: 40 * 8 * 500000)");
if(err = waitForData(dataInfo.cycleNumber))
return err;
if(osimulate){
err = odataAquire.getData(dataInfo, data);
}
else {
if(dataInfo.channel){
data.errors.resize(1);
olock.lock();
puPhysChannel = oconfigInfo.puReferences[dataInfo.channel - 1];
olock.unlock();
opuServersLock.rdLock();
if(puPhysChannel.moduleNum > opuServers.number()){
opuServersLock.unlock();
data.errors[0] = err;
return err.set(ErrorMC, BString("Module: ") + puPhysChannel.moduleNum + " is not available");
}
err = opuServers[puPhysChannel.moduleNum - 1]->getData(puPhysChannel, dataInfo, data, orbitNumber);
// Check if there were any Cycle Errors
if(!err){
errList = ocycleInfoList.getCycleErrors(dataInfo.cycleNumber);
if(errList.number()){
err = errList.front();
}
}
if(err.getErrorNo() == ErrorDataGone)
onumDataGoneErrors++;
opuServersLock.unlock();
data.errors[0] = err;
}
else {
BUInt32 numValues = 0;
Data dataSet[oconfigInfo.puReferences.size()];
if(dataInfo.numValues < oconfigInfo.puReferences.size()){
return err.set(ErrorParam, "NumValues to small for request");
}
// Get the data from all PUPE channels. This could be improved with multi-threading and
// geting the data from separate module controllers at the same time to reduce system latency
dataInfo.numValues = dataInfo.numValues / oconfigInfo.puReferences.size();
data.errors.resize(oconfigInfo.puReferences.size());
for(chan = 0; chan < oconfigInfo.puReferences.size(); chan++){
e = BError();
olock.lock();
puPhysChannel = oconfigInfo.puReferences[chan];
olock.unlock();
opuServersLock.rdLock();
if(puPhysChannel.moduleNum > opuServers.number()){
e.set(ErrorMC, BString("Module: ") + puPhysChannel.moduleNum + " is not available");
}
else {
e = opuServers[puPhysChannel.moduleNum - 1]->getData(puPhysChannel, dataInfo, dataSet[chan], orbitNumber);
#if TIME_MS_USE_DATAGET
// If we have set a startTime, use the orbit number for all other channels
if(!e && dataInfo.startTime){
// syslog(LOG_ERR, "GetData: Get orbit number for channel: %d at startTime: %d orbitNumber: %d\n", chan, dataInfo.startTime, orbitNumber);
dataInfo.orbitNumber = orbitNumber;
dataInfo.startTime = 0;
}
#endif
}
data.errors[chan] = e;
if(e && !err)
err = e;
opuServersLock.unlock();
}
// Check if there were any Cycle Errors
if(!err){
errList = ocycleInfoList.getCycleErrors(dataInfo.cycleNumber);
if(errList.number()){
err = errList.front();
}
for(chan = 0; chan < oconfigInfo.puReferences.size(); chan++){
data.errors[chan] = err;
}
}
if(err.getErrorNo() == ErrorDataGone)
onumDataGoneErrors++;
// Now merge the data
// Calculate maximum number of values
numValues = 0;
data.dataType = 0;
data.numBunches = 0;
for(chan = 0; chan < oconfigInfo.puReferences.size(); chan++){
if(!data.errors[chan]){
data.dataType = dataSet[chan].dataType;
data.numBunches = dataSet[chan].numBunches;
if(dataSet[chan].dataValues.size() > numValues)
numValues = dataSet[chan].dataValues.size();
}
}
// Calculate minimum number of values
for(chan = 0; chan < oconfigInfo.puReferences.size(); chan++){
if(!data.errors[chan] && (dataSet[chan].dataValues.size() < numValues))
numValues = dataSet[chan].dataValues.size();
}
// Make sure numValues is a multiple of the number of bunches
if(data.numBunches)
numValues = data.numBunches * (numValues / data.numBunches);
data.numValues = numValues * oconfigInfo.puReferences.size();
data.numChannels = oconfigInfo.puReferences.size();
data.dataValues.resize(data.numValues);
memset(data.dataValues.data(), 0, data.dataValues.size() * sizeof(DataValue));
// Merge the data
for(chan = 0; chan < oconfigInfo.puReferences.size(); chan++){
if(!data.errors[chan])
memcpy(&data.dataValues[chan * numValues], &dataSet[chan].dataValues[0], numValues * sizeof(DataValue));
}
}
}
return err;
}
BError Control::addEventServer(BString name){
dprintf(DBG_CMD, "Control::addEventServer\n");
return oeventServers.append(name);
}
BError Control::requestData(DataInfo dataInfo){
BError err;
dprintf(DBG_CMD, "Control::requestData\n");
olock.lock();
orequestList.append(dataInfo);
olock.unlock();
return err;
}