Timing.cpp

Go to the documentation of this file.
00001 //Copyright GSI 2012
00002 #include <fesa-core/Synchronization/Timing.h>
00003 #include <fesa-core-gsi/Exception/GSIException.h>
00004 #include <fesa-core/Synchronization/MultiplexingContext.h>
00005 #include <fesa-core/Synchronization/SynchronizationLabObjectFactory.h>
00006 #include <fesa-core-gsi/Synchronization/GSICycleDescriptor.h>
00007 #include <fesa-core-gsi/Exception/GSIException.h>
00008 extern "C"
00009 {
00010 #include <tim/TimLib.h>
00011 }
00012 
00013 #include <sys/time.h>
00014 
00015 #include <math.h>
00016 #include <string>
00017 #include <iostream>
00018 #include <sstream>
00019 
00020 namespace fesa
00021 {
00022 
00023 void parseCycleSelector(const std::string& cycleSelector,
00024                 fesa::CycleSelector& cycleSelectorStructure) {
00025 
00026         std::size_t sep1 = cycleSelector.find('.');
00027         if (sep1 == std::string::npos) {
00028                 throw fesaGSI::GSIException(__FILE__, __LINE__, FESAGSIErrorParsingTimingDescriptor.c_str(),
00029                                 cycleSelector.c_str());
00030         }
00031         cycleSelectorStructure.domain_ = cycleSelector.substr(0, sep1);
00032 
00033         std::size_t sep2 = cycleSelector.find('.', sep1 + 1);
00034         // In case of multiplexing manager names: PSB.USER
00035         // but in case of extra-criterions: PSB.PARTY.PROT
00036         if (sep2 == std::string::npos) {
00037                 sep2 = cycleSelector.size();
00038         }
00039 
00040         cycleSelectorStructure.criterion_ = cycleSelector.substr(sep1 + 1, sep2
00041                         - sep1 - 1);
00042         cycleSelectorStructure.value_ = cycleSelector;
00043 
00044 }
00045 
00046 void validateCycleSelector(fesa::CycleSelector& cycleSelector,
00047                 fesa::RequestType requestType) {
00048         if (requestType == fesa::SUBSCRIBE) {
00049                 // check if the cycleSelector is using valid group: exclusif or numerical but not bit-pattern
00050                 //            fesa::CycleDescriptor* td = fesa::CycleDescriptor::getCycleDescriptor(cycleSelector.domain_, cycleSelector.criterion_);
00051                 //            fesaGSI::GSICycleDescriptor* ctd = static_cast<fesaGSI::GSICycleDescriptor*>(td);
00052                 //TODO CycleDescriptor should implement getGroupType: Exclusif, numerical, bitpattern
00053                 //            if(ctd->getGroupType() == bitpattern)
00054                 //                throw fesaCERN::CERNException(__FILE__, __LINE__, FesaErrorTimingLibAccessFailed.c_str());
00055         }
00056 }
00057 
00058 bool match(const std::string& cycleSelector, fesa::MultiplexingContext* context) {
00059         if (cycleSelector.empty()) {
00060                 return true;
00061         }
00062 
00063         size_t sep1 = cycleSelector.find('.');
00064         size_t sep2 = cycleSelector.rfind('.');
00065         if ((sep1 == std::string::npos) || (sep2 == std::string::npos)) {
00066                 return false;
00067         }
00068 
00069         std::string machineName = cycleSelector.substr(0, sep1 - 1);
00070         std::string groupName = cycleSelector.substr(sep1 + 1, sep2 - sep1 - 1);
00071         std::string lineName = cycleSelector.substr(sep2 + 1,
00072                         cycleSelector.length() - sep2 - 1);
00073 
00074         if (groupName == "USER") {
00075                 if (!(context->getCycleName().empty())) {
00076                         if ((cycleSelector != context->getCycleName())) {
00077                                 return false;
00078                         }
00079                 }
00080         } else {
00081                 // Checking timingDomain
00082                 if (machineName.compare(context->getTimingDomainName()) != 0) {
00083                         return false;
00084                 }
00085 
00086                 // Getting the CycleDescriptor of the given group in order to find out the group number and line number
00087                 fesa::SynchronizationLabObjectFactory* syncFactory = fesa::SynchronizationLabObjectFactory::getInstance();
00088         fesaGSI::GSICycleDescriptor* pCd =  static_cast<fesaGSI::GSICycleDescriptor*>(syncFactory->getCycleDescriptor(machineName, groupName));
00089 
00090                 unsigned long groupNumber = (unsigned long) pCd->getTgmGroupId();
00091                 unsigned long lineNumber = (unsigned long) pCd->getCycleSelectorId(
00092                                 lineName);
00093 
00094                 // Getting the current group value for the given lineName
00095                 unsigned long lineValueFromTiming;
00096                 unsigned long next = 0; //TODO = (anticipated_) ? 1 : 0;
00097                 TimLibError err;
00098                 TimLibTime time;
00099                 time.Second = (long long) (round(context->getCycleStamp()
00100                                 / (long long) 1000000000));
00101                 time.Nano = context->getCycleStamp() - time.Second;
00102 
00103                 if ((err = TimLibGetGroupValueFromStamp(time, groupNumber, next,
00104                                 &lineValueFromTiming)) == TimLibErrorSUCCESS) {
00105                         if (lineNumber != lineValueFromTiming) {
00106                                 return false;
00107                         }
00108                 } else //Error from timing library
00109                 {
00110                         //TODO ERRLOG
00111             throw fesaGSI::GSIException(__FILE__, __LINE__, FesaErrorTimingLibAccessFailed.c_str());
00112                         return false;
00113                 }
00114         }
00115         return true;
00116 }
00117 
00118 long long getActualTime(bool& isHwTime) {
00119         TimLibTime hwtime;
00120         TimLibError err = TimLibGetTime(0, &hwtime);
00121 
00122         if (!err) {
00123                 isHwTime = true;
00124                 return (hwtime.Second * (long long) 1000000000 + hwtime.Nano);
00125         } else {
00126                 isHwTime = false;
00127                 struct timeval now;
00128                 gettimeofday(&now, 0);
00129                 return (now.tv_sec * (long long) 1000000000 + now.tv_usec
00130                                 * (long long) 1000);
00131         }
00132 }
00133 
00134 std::string getTimeString(long long time, char* format) {
00135 
00136         if (time == 0) {
00137                 bool isHwTime;
00138                 time = getActualTime(isHwTime);
00139         }
00140 
00141         int seconds = time / (long long) 1000000000;
00142         int nanos = time - (long long) 1000000000 * seconds;
00143 
00144         char timestring[32];
00145         strftime(timestring, sizeof(timestring), format, localtime(
00146                         (time_t *) &seconds));
00147 
00148         //ostringstream ost; // this crashes, so we code it with stringbuf and ostream
00149         std::stringbuf stb("", std::ios::out);
00150         std::ostream ost(&stb);
00151 
00152         ost << timestring << ".";
00153         ost.width(6);
00154         ost.fill('0');
00155         ost << nanos / 1000;
00156 
00157         return stb.str();
00158 }
00159 
00160 int getCycleTime() {
00161         // Force systematically an initialization because it can be call
00162         // from a ServerAction....
00163         TimLibError err = TimLibInitialize(TimLibDevice_ANY);
00164         if (err != 0) {
00165                 std::cout << "Timing::getCycleTime() error: " << TimLibErrorToString(err)
00166                                 << std::endl;
00167                 return -1;
00168         }
00169         TimLibTime hwtime;
00170         err = TimLibGetTime(0, &hwtime);
00171 
00172         if (!err)
00173                 return hwtime.CTrain;
00174         return -1;
00175 }
00176 }
00177 

Generated on 25 Jan 2013 for fesa-core-gsi by  doxygen 1.6.1