00001
00002 #include <sstream>
00003 #include <fstream>
00004 #include <malloc.h>
00005 #include <sys/time.h>
00006
00007
00008 #include <fesa-core-gsi/RealTime/TimingEventSource.h>
00009 #include <fesa-core-gsi/RealTime/TimingPayload.h>
00010 #include <fesa-core-gsi/Synchronization/TimingContext.h>
00011 #include <fesa-core-gsi/Exception/FesaGSIExceptionDef.h>
00012 #include <fesa-core-gsi/Synchronization/GSICycleDescriptor.h>
00013 #include <fesa-core/Core/FesaDefs.h>
00014 #include <fesa-core/Core/AbstractEquipment.h>
00015 #include <fesa-core/Utilities/ParserElements/EventElement.h>
00016 #include <fesa-core/Utilities/ParserElements/ParserElementDefs.h>
00017 #include <cmw-log/Logger.h>
00018 #include <fesa-core/Diagnostic/Diagnostics.h>
00019 #include <math.h>
00020
00021 namespace
00022 {
00023
00024 CMW::Log::Logger& logger = CMW::Log::LoggerFactory::getLogger("FESA.FWK.fesa-core-gsi.RealTime.TimingEventSource");
00025 const std::string diagTopic = fesa::DiagnosticUtils::eventTrackingStr;
00026
00027 }
00028
00029 namespace fesaGSI
00030 {
00031 int TimingEventSource::ourDebugOptions_;
00032 int TimingEventSource::LTIM_HARD_ID_TRANS = -1;
00033
00034 TimingEventSource::TimingEventSource() :
00035 fesa::AbstractEventSource(fesa::TIMING_EVENT_SOURCE_NAME, fesa::TimingSource)
00036 {
00037 ourDebugOptions_ = getDebugOptions();
00038
00039 fd_ = TimLibFdInitialize(TimLibDevice_ANY);
00040 if (fd_ == 0)
00041 {
00042 char* ignore = getenv("TimingEventSource_IgnoreHardware");
00043 if (!ignore)
00044 {
00045 throw GSIException(__FILE__, __LINE__, FESAGSIErrorInitializingTimLib.c_str());
00046 }
00047 }
00048
00049 TimLibFdQueue(fd_, 0, 0);
00050
00051 }
00052
00053 unsigned int TimingEventSource::getDebugOptions()
00054 {
00055 char* debugStr = getenv("TimingEventSource_DebugOptions");
00056
00057 if (!debugStr)
00058 {
00059 return 0;
00060 }
00061
00062 debugStr += strspn(debugStr, " \t");
00063
00064
00065 while (debugStr[0] == '0' && (debugStr[1] != 'x' && debugStr[1] != 'X' && debugStr[1] != '\0'))
00066 {
00067 debugStr += 1;
00068 }
00069 return strtol(debugStr, 0, 0);
00070 }
00071
00072 TimingEventSource::~TimingEventSource()
00073 {
00074 }
00075
00076 fesa::RTEvent* TimingEventSource::wait()
00077 {
00078 TimLibError err;
00079 TimLibClass t_class;
00080 unsigned long equip;
00081 unsigned long plnum;
00082 TimLibHardware source;
00083 TimLibTime trigger;
00084 TimLibTime start;
00085 unsigned long ctim;
00086 unsigned long module = 0;
00087 unsigned long missed = 0;
00088 unsigned long qsize = 0;
00089 TgmMachine tgmMachine;
00090
00091
00092
00093 for (;;)
00094 {
00095 fesaGSI::TimingContext* tc = 0;
00096 fesa::RTEventPayload * pTimingPayload = 0;
00097 fesa::RTEvent* theEvent = 0;
00098
00099 TimLibTime interruptStamp;
00100 unsigned long payload;
00101
00102 try
00103 {
00104
00105 err = TimLibFdWait(fd_, &t_class, &equip, &plnum, &source, &interruptStamp, &trigger, &start, &ctim,
00106 &payload, &module, &missed, &qsize, &tgmMachine);
00107
00108 if (err == TimLibErrorTIMEOUT)
00109 {
00110
00111 continue;
00112 }
00113
00114
00115
00116 else if (err != 0)
00117 {
00118
00119 struct timespec retryDelay = { 2, 0 };
00120 struct timespec time_left_before_wakeup;
00121 nanosleep(&retryDelay, &time_left_before_wakeup);
00122 continue;
00123 }
00124 const boost::shared_ptr<fesa::Diagnostics>& diagnostics = fesa::AbstractEquipment::getInstance()->getDiagnostics();
00125 fesa::DiagnosticUtils::DiagnosticMessage diagMsg;
00126 diagMsg.side = fesa::DiagnosticUtils::framework;
00127 diagMsg.source = fesa::DiagnosticUtils::event;
00128 diagMsg.name = getName();
00129 diagMsg.msg = "TimLibWait wake-up";
00130 diagnostics->log(diagTopic, diagMsg);
00131
00132 TimingInfo timingInfo;
00133
00134 if (t_class == TimLibClassCTIM)
00135 {
00136
00137 std::map<int, TimingInfo>::iterator itr = ctimEventsCol_.find(equip);
00138
00139 if (itr == ctimEventsCol_.end())
00140 {
00141 std::stringstream buf;
00142 std::ostringstream errorStrStream;
00143 errorStrStream << "ERROR: TiminEventSource::wait : received an unexpected event identified by TimingClass";
00144 LOG_ERROR_IF(logger, errorStrStream.str());
00145 continue;
00146 }
00147 else
00148 {
00149 timingInfo = (*itr).second;
00150 }
00151 }
00152 else if (t_class == TimLibClassPTIM)
00153 {
00154 std::map<int, TimingInfo>::iterator itr = ltimEventsCol_.find(equip);
00155
00156 if (itr == ltimEventsCol_.end())
00157 {
00158 std::stringstream buf;
00159 std::ostringstream errorStrStream;
00160 errorStrStream << "ERROR: TiminEventSource::wait : received an unexpected event identified by TimingClass";
00161 LOG_ERROR_IF(logger, errorStrStream.str());
00162 continue;
00163 }
00164 else
00165 {
00166 timingInfo = (*itr).second;
00167 }
00168 }
00169 else if (t_class == TimLibClassHARDWARE)
00170 {
00171 TimingKey key(equip, module);
00172
00173 std::map<TimingKey, TimingInfo>::iterator itr = ltimHardEventsCol_.find(key);
00174
00175 if (itr == ltimHardEventsCol_.end())
00176 {
00177 std::stringstream buf;
00178 std::ostringstream errorStrStream;
00179 errorStrStream << "ERROR: TiminEventSource::wait : received an unexpected event identified by TimingClass";
00180 LOG_ERROR_IF(logger, errorStrStream.str());
00181 continue;
00182 }
00183 else
00184 {
00185 timingInfo = (*itr).second;
00186 }
00187
00188 }
00189
00190 interruptStamp.Machine = tgmMachine;
00191
00192 pTimingPayload = new TimingPayload(payload);
00193 fesaGSI::TimingContext* context = new fesaGSI::TimingContext(interruptStamp, payload, timingInfo.forewarning_);
00194 theEvent = new fesa::RTEvent(timingInfo.concreteName_, context, this);
00195
00196
00197 diagMsg.msg = "Send RT event";
00198 diagnostics->log(diagTopic, diagMsg);
00199
00200 return theEvent;
00201 }
00202 catch (fesa::FesaException& ex)
00203 {
00204 if (tc != 0)
00205 delete tc;
00206 if (pTimingPayload != 0)
00207 delete pTimingPayload;
00208 if (theEvent != 0)
00209 delete theEvent;
00210
00211 std::stringstream buf;
00212 std::ostringstream errorStrStream;
00213 errorStrStream << "Event was not fired because the following exception occured: " << ex.getMessage();
00214 LOG_ERROR_IF(logger, errorStrStream.str());
00215 }
00216 catch (...)
00217 {
00218 if (tc != 0)
00219 delete tc;
00220 if (pTimingPayload != 0)
00221 delete pTimingPayload;
00222 if (theEvent != 0)
00223 delete theEvent;
00224
00225 std::stringstream buf;
00226 std::ostringstream errorStrStream;
00227 errorStrStream << "Event was not fired becausean unknown exception occured.";
00228 LOG_ERROR_IF(logger, errorStrStream.str());
00229 }
00230 }
00231 }
00232
00233 void TimingEventSource::connect(boost::shared_ptr<fesa::EventElement>& eventElement)
00234 {
00235 std::string concreteEventName = eventElement->getSourceTypeSpecificData(fesa::TIMING_TAG_CONCRETE_NAME);
00236
00237
00238
00239 TimLibClass theTimLibClass;
00240
00241 size_t posSep1 = concreteEventName.find('#');
00242 size_t posSep2 = concreteEventName.rfind('#', concreteEventName.size());
00243 if (posSep1 == std::string::npos || posSep2 == std::string::npos)
00244 {
00245 throw GSIException(__FILE__, __LINE__, FESAGSIErrorWrongTimingName.c_str(), concreteEventName.c_str());
00246 }
00247
00248
00249 std::string objectClassName = concreteEventName.substr(posSep1 + 1, posSep2 - posSep1 - 1);
00250 if (objectClassName == "CTIM")
00251 {
00252 theTimLibClass = TimLibClassCTIM;
00253 }
00254 else if (objectClassName == "LTIM")
00255 {
00256 theTimLibClass = TimLibClassPTIM;
00257 }
00258 else if (objectClassName == "LTIM-HARD")
00259 {
00260 theTimLibClass = TimLibClassHARDWARE;
00261 }
00262 else
00263 {
00264 throw GSIException(__FILE__, __LINE__, FESAGSIErrorUnknownTimingObjectClassName.c_str(),
00265 concreteEventName.c_str());
00266 }
00267
00268 int connectionId = -1;
00269 std::string idStr = concreteEventName.substr(posSep2 + 1);
00270 const char* pStr = idStr.c_str();
00271 if (pStr[0] == '0' && (pStr[1] == 'x' || pStr[1] == 'X'))
00272 {
00273 connectionId = strtol(pStr + 2, 0, 16);
00274 }
00275 else
00276 {
00277 connectionId = atol(pStr);
00278 }
00279
00280
00281 unsigned long module = 0;
00282
00283
00284
00285
00286 if ((theTimLibClass == TimLibClassPTIM) || (theTimLibClass == TimLibClassHARDWARE))
00287 {
00288 unsigned long m;
00289 unsigned long c;
00290 unsigned long d;
00291 TimLibError err = TimLibGetPtimObject(connectionId, &m, &c, &d);
00292 if (err != 0)
00293 {
00294 throw GSIException(__FILE__, __LINE__, FESAGSIErrorWhileGettingTimingObject.c_str(),
00295 concreteEventName.c_str());
00296 }
00297
00298
00299 if (theTimLibClass == TimLibClassHARDWARE)
00300 {
00301 connectionId = (unsigned long) (pow(2, c));
00302 }
00303
00304 module = m;
00305 }
00306 else if (theTimLibClass == TimLibClassCTIM)
00307 {
00308 module = TimLibGetModuleForCtim(connectionId);
00309 }
00310
00311 int equipId = connectionId;
00312 if (theTimLibClass == TimLibClassHARDWARE)
00313 {
00314 equipId *= LTIM_HARD_ID_TRANS;
00315 }
00316
00317 TimLibError err = TimLibFdConnect(fd_, theTimLibClass, connectionId, module);
00318 if (err != 0)
00319 {
00320 throw GSIException(__FILE__, __LINE__, FESAGSIErrorWhileConnectingTimingEvent.c_str(),
00321 concreteEventName.c_str());
00322 }
00323
00324 std::stringstream buf;
00325 std::ostringstream errorStrStream;
00326 errorStrStream << "TimLibConnect: " << concreteEventName << " : theTimLibClass: " << theTimLibClass << " : connectionId: " << connectionId << " : module: " << module;
00327 LOG_ERROR_IF(logger, errorStrStream.str());
00328
00329 TimingInfo timingInfo;
00330
00331 timingInfo.concreteName_ = concreteEventName;
00332 timingInfo.forewarning_ = false;
00333
00334 if (objectClassName == "CTIM")
00335 {
00336 ctimEventsCol_.insert(std::make_pair(connectionId, timingInfo));
00337 }
00338 else if (objectClassName == "LTIM")
00339 {
00340 ltimEventsCol_.insert(std::make_pair(connectionId, timingInfo));
00341 }
00342 else if (objectClassName == "LTIM-HARD")
00343 {
00344 TimingKey key(connectionId, module);
00345 ltimHardEventsCol_.insert(std::make_pair(key, timingInfo));
00346 }
00347
00348 return;
00349 }
00350
00351 }